make the cutoff donation amount a config variable
[fsfdrupalauth.git] / lib / Auth / Source / FSFDrupalAuth.php
index 58723bf9ecd9417cf39c38eebd1b57d72644786f..69f60b473f2b26e4d9550c1bb477822c958bd9f7 100644 (file)
@@ -44,19 +44,35 @@ class FSFDrupalAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
     private $query_main;
     private $query_membership;
     private $query_staff;
+
     private $query_nomination_process_donations;
     private $query_nomination_process_gift_receipt;
+    private $query_nomination_process_adhoc;
+
+    private $query_discussion_process_old_membership;
+    private $query_discussion_process_donations;
+    private $query_discussion_process_adhoc;
 
     /**
      * SQL query parameters, or variables that help determine which attributes
      * someone has
      */
     private $fsf_org_id;
+    private $gift_redeem_page_id;
+
+    private $nomination_process_active;
     private $nomination_process_contrib_start_date;
     private $nomination_process_contrib_end_date;
-    private $gift_redeem_page_id;
-    private $donation_threshold;
-    private $membership_donation_threshold;
+    private $nomination_process_adhoc_access_group_id;
+    private $membership_monthly_rate;
+    private $student_membership_monthly_rate;
+
+    private $discussion_process_active;
+    private $discussion_process_contrib_start_date;
+    private $discussion_process_contrib_end_date;
+    private $discussion_process_adhoc_access_group_id;
+    private $discussion_process_adhoc_no_access_group_id;
+    private $discussion_process_donation_amount;
 
     /**
      * Constructor for this authentication source.
@@ -73,14 +89,39 @@ class FSFDrupalAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
         parent::__construct($info, $config);
 
         // Make sure that all required parameters are present.
-       foreach (['dsn', 'username', 'password', 'query_main',
-               'query_membership', 'query_staff',
+       foreach (['dsn',
+               'username',
+               'password',
+
+               'query_main',
+               'query_membership',
+               'query_staff',
+
                'query_nomination_process_donations',
-               'query_nomination_process_gift_receipt', 'gift_redeem_page_id',
-               'fsf_org_id', 'donation_threshold',
-               'membership_donation_threshold',
+               'query_nomination_process_gift_receipt',
+               'query_nomination_process_adhoc',
+
+               'fsf_org_id',
+               'gift_redeem_page_id',
+
+               'nomination_process_active',
                'nomination_process_contrib_start_date',
-               'nomination_process_contrib_end_date'] as $param) {
+               'nomination_process_contrib_end_date',
+               'nomination_process_adhoc_access_group_id',
+               'membership_monthly_rate',
+               'student_membership_monthly_rate',
+
+               'query_discussion_process_old_membership',
+               'query_discussion_process_donations',
+               'query_discussion_process_adhoc',
+
+               'discussion_process_active',
+               'discussion_process_contrib_start_date',
+               'discussion_process_contrib_end_date',
+               'discussion_process_adhoc_access_group_id',
+               'discussion_process_adhoc_no_access_group_id',
+               'discussion_process_donation_amount',]
+               as $param) {
 
             if (!array_key_exists($param, $config)) {
                 throw new Exception('Missing required attribute \''.$param.
@@ -184,18 +225,18 @@ class FSFDrupalAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
             $return_value = proc_close($process);
 
             //Logger::debug('fsfdrupalauth:'.$this->authId.': authenticator stdout: '.$result);
-    
+
             $errors_found_yet = false;
             if ($errors != "") {
                 Logger::error('fsfdrupalauth:'.$this->authId.': authenticator stderr: '.$errors);
                 $errors_found_yet = true;
             }
-    
+
             if ($return_value != 0) {
                 Logger::error('fsfdrupalauth:'.$this->authId.': authenticator non-zero return code: '.$return_value);
                 $errors_found_yet = true;
             }
-    
+
             return (!$errors_found_yet && is_string($result) && rtrim($result) == "true");
 
         } else {
@@ -282,55 +323,186 @@ class FSFDrupalAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
         }
 
         //
-        // query for access to board nomination process
+        // helper functions for access to board nomination / discussion process
         //
 
-       $start_date = $this->nomination_process_contrib_start_date;
-       $end_date   = $this->nomination_process_contrib_end_date;
-
        /**
          * @param string $query_name  Name of query in authsources
-         * @param number $amount  Amount to compare result to
-         * @param boolean $all_contribs  Pass as 'all_contribs' param. The var may also be null to exclude it
-         * @param boolean $gift_redeem_page_id  Pass as 'gift_redeem_page_id' param. The var may also be null to exclude it
+         * @param array $extra_params  Associative array of parameters to include in query
         */
-       $meets_a_donation_criterion = function ($query_name, $amount, $all_contribs, $gift_redeem_page_id)
-           use ($username, $start_date, $end_date, $attributes) {
+       $donation_query = function ($query_name, $extra_params)
+           use ($username) {
 
-               $parameters =
-                       ['username'   => $username,
-                        'start_date' => $start_date,
-                        'end_date'   => $end_date];
+               $parameters = ['username' => $username];
 
-               if ($all_contribs !== null) {
-                       $parameters['all_contribs'] = $all_contribs;
-               }
-               if ($gift_redeem_page_id !== null) {
-                       $parameters['gift_redeem_page_id'] = $gift_redeem_page_id;
+               foreach ($extra_params as $key => $value) {
+                       $parameters[$key] = $value;
                }
 
-               $result = $this->query_db($query_name, $parameters);
+               return $this->query_db($query_name, $parameters);
+       };
+
+       $old_membership_query = $donation_query;
 
+       $compare_res = function ($result, $amount) {
                foreach ($result[0] as $key => $value) {
-                   if ($value < $amount) {
-                       continue;
-                   } elseif ($attributes['is_member'] == ['true']) {
-                       return true;
-                   }
+                       if (intval($value) >= $amount) {
+                               return true;
+                       }
                }
+               return false;
+       };
 
+       // set dates here, used by helper functions below
+       $nomination_process_start_date = $this->nomination_process_contrib_start_date;
+       $nomination_process_end_date   = $this->nomination_process_contrib_end_date;
+       $discussion_process_start_date = $this->discussion_process_contrib_start_date;
+       $discussion_process_end_date   = $this->discussion_process_contrib_end_date;
+
+
+       // looks for memberships / comparable donations in time window. also
+       // looks for a membership or donation (included as a param) that
+       // occurred up to a year before, and that would have carried over into
+       // the time window with a single donation. this approximates whether
+       // the person was, or would have been, a member during the configured
+       // time window.
+       $nomination_process_analyze_history = function ($selective_donations_history)
+           use ($nomination_process_start_date, $nomination_process_end_date) {
+
+               $eligible = false;
+
+               $start_date_obj = new \DateTime($nomination_process_start_date);
+               $end_date_obj = new \DateTime($nomination_process_end_date);
+
+               foreach ($selective_donations_history as $row) {
+
+                       $amount = intval($row['amount']);
+                       $member_type_id = $row['member_type_id'];
+                       $receive_date_obj = new \DateTime($row['receive_date']);
+
+                       if ($amount < 5) {
+                               continue;
+
+                       } elseif ($receive_date_obj >= $start_date_obj and $receive_date_obj <= $end_date_obj) {
+                               return true;
+
+                       } elseif ($receive_date_obj < $start_date_obj) {
+                               switch ($member_type_id) {
+                                       case '1':
+                                       case '2':
+                                               $rate = intval($this->student_membership_monthly_rate);
+                                               break;
+                                       case '8':
+                                       case '9':
+                                       case null:
+                                       default:
+                                               $rate = intval($this->membership_monthly_rate);
+                                               break;
+                               }
+                               $membership_end_date_obj = new \DateTime($row['receive_date']);
+                               $membership_end_date_obj->add(new \DateInterval("P" . ceil($amount / $rate) . "M"));
+
+                               if ($membership_end_date_obj >= $start_date_obj) {
+                                       return true;
+                               }
+                       }
+               }
                return false;
        };
 
-       if ($meets_a_donation_criterion('query_nomination_process_donations', intval($this->donation_threshold), true, null)
-           || $meets_a_donation_criterion('query_nomination_process_donations', intval($this->membership_donation_threshold), false, null)
-           || $meets_a_donation_criterion('query_nomination_process_gift_receipt', 1, null, intval($this->gift_redeem_page_id))) {
+       $discussion_process_analyze_history = function ($selective_donations_history)
+           use ($discussion_process_start_date, $discussion_process_end_date) {
+
+               $eligible = false;
+               $total = 0;
+
+               $start_date_obj = new \DateTime($discussion_process_start_date);
+               $end_date_obj = new \DateTime($discussion_process_end_date);
+
+               foreach ($selective_donations_history as $row) {
+
+                       $amount = intval($row['amount']);
+                       $member_type_id = $row['member_type_id'];
+                       $receive_date_obj = new \DateTime($row['receive_date']);
+
+                       if (($receive_date_obj > $start_date_obj) && ($receive_date_obj < $end_date_obj)) {
+                               $total += $amount;
+                       }
+               }
+
+               if ($total >= $this->discussion_process_donation_amount) {
+                       return true;
+               } else {
+                       return false;
+               }
+       };
+
+       //
+       // nomination form participation specific checks
+       //
+
+       $donation_params    = ['start_date' => $nomination_process_start_date, 'end_date' => $nomination_process_end_date];
+       $gift_member_params = ['start_date' => $nomination_process_start_date, 'end_date' => $nomination_process_end_date, 'gift_redeem_page_id' => intval($this->gift_redeem_page_id)];
+       $adhoc_params       = ['adhoc_access_group_id' => intval($this->nomination_process_adhoc_access_group_id)];
+
+       if ($this->nomination_process_active != 'true' ) {
+               $attributes['nomination_process'] = ['false'];
+
+       } elseif ($compare_res($donation_query('query_nomination_process_adhoc', $adhoc_params), 1)) {
+               $attributes['nomination_process'] = ['true'];
+
+       } elseif ($attributes['is_member'] != ['true']) {
+               Logger::debug('fsfdrupalauth:'.$this->authId.
+                       ': Not a member / comparable donor during window for board process.');
+               $attributes['nomination_process'] = ['false'];
+
+       } elseif ($nomination_process_analyze_history($donation_query('query_nomination_process_donations', $donation_params))
+               || $compare_res($donation_query('query_nomination_process_gift_receipt', $gift_member_params), 1)) {
 
                $attributes['nomination_process'] = ['true'];
+
        } else {
+               Logger::debug('fsfdrupalauth:'.$this->authId.
+                       ': Not a member / comparable donor during window for board process.');
                $attributes['nomination_process'] = ['false'];
        }
 
+       //
+       // discussion form participation specific checks
+       //
+
+       $donation_params    = ['start_date' => $discussion_process_start_date, 'end_date' => $discussion_process_end_date];
+       $old_member_params  = $donation_params;
+       $adhoc_params       = ['adhoc_access_group_id' => intval($this->discussion_process_adhoc_access_group_id)];
+       $adhoc_params_no    = ['adhoc_access_group_id' => intval($this->discussion_process_adhoc_no_access_group_id)];
+
+       if ($this->discussion_process_active != 'true' ) {
+               $attributes['discussion_process'] = ['false'];
+
+       } elseif ($compare_res($donation_query('query_discussion_process_adhoc', $adhoc_params_no), 1)) {
+               Logger::debug('fsfdrupalauth:'.$this->authId.
+                       ': Nominee not eligible for board nominee discussion process.');
+               $attributes['discussion_process'] = ['false'];
+
+       } elseif ($compare_res($donation_query('query_discussion_process_adhoc', $adhoc_params), 1)) {
+               $attributes['discussion_process'] = ['true'];
+
+       } elseif ($attributes['is_member'] != ['true']) {
+               Logger::debug('fsfdrupalauth:'.$this->authId.
+                       ': Not eligible for board nominee discussion process.');
+               $attributes['discussion_process'] = ['false'];
+
+       } elseif ($compare_res($old_membership_query('query_discussion_process_old_membership', $old_member_params), 1)
+               || $discussion_process_analyze_history($donation_query('query_discussion_process_donations', $donation_params))) {
+
+               $attributes['discussion_process'] = ['true'];
+
+       } else {
+               Logger::debug('fsfdrupalauth:'.$this->authId.
+                       ': Not eligible for board nominee discussion process.');
+               $attributes['discussion_process'] = ['false'];
+       }
+
         //
         // query on staff
         //
@@ -353,9 +525,9 @@ class FSFDrupalAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
                 }
                 $value = (string) $value;
 
-                if ($value === $username) {
+                if (strtolower($value) === strtolower($username)) {
                     // they are staff
-                    $attributes[$key] = ['true'];
+                    $attributes['is_fsf_staff'] = ['true'];
                     break;
                 }
             }