<commit_before><?php

/**
 * ProccessorMessage.Processnewmessages API specification (optional)
 * This is used for documentation and validation.
 *
 * @param array $spec description of fields supported by this API call
 * @return void
 * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
 */
function _civicrm_api3_proccessor_message_processnewmessages_spec(&$spec) {

}

/**
 * ProccessorMessage.Processnewmessages API
 *
 * @param array $params
 * @return array API result descriptor
 * @see civicrm_api3_create_success
 * @see civicrm_api3_create_error
 * @throws API_Exception
 */
function civicrm_api3_proccessor_message_processnewmessages($params) {
  $rec_count = handle_the_messages();
  $returnValues = array("record count:" . $rec_count);

  return civicrm_api3_create_success($returnValues, $params, 'ProcessorMessage', 'processnewmessages');
}

function handle_the_messages() {
  $all_message_types_tocheck = array();
  $ewayemailrecur_type = "eWay_Recurring";

  $pay_pal_type = "PayPal";
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $pay_pal_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);
  $tmp = $result['values'][0];

  if ($tmp['id'] == $pay_pal_type) {
    $bool_str = $tmp['name'];
    $pay_pal_enabled = $bool_str === 'true' ? true : false;
  }

  if ($pay_pal_enabled) {
    $all_message_types_tocheck[] = "PayPal";
  }

  $authnet_type = "AuthNet";
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $authnet_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);

  $tmp = $result['values'][0];
  if ($tmp['id'] == $authnet_type) {
    $bool_str = $tmp['name'];
    $authnet_enabled = $bool_str === 'true' ? true : false;
  }

  if ($authnet_enabled) {
    $all_message_types_tocheck[] = "AuthNet";
  }

  // Now check for eWay recurring (email notifications)
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $ewayemailrecur_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);
  $tmp = $result['values'][0];

  if ($tmp['id'] == $ewayemailrecur_type) {
    $bool_str = $tmp['name'];
    $ewayrecur_enabled = $bool_str === 'true' ? true : false;
  }

  if ($ewayrecur_enabled) {
    $all_message_types_tocheck[] = "eWay";
  }

  // For each processor type in use, process related messages
  $rec_count = 0;
  foreach ($all_message_types_tocheck as $cur_type) {

    if ($cur_type == "iATS") {
      $messages_table_name = 'pogstone_iats_messages';
      $sql = " SELECT    msg.id, msg.transaction_id as transaction_id ,
     msg.trans_date,
     msg.recur_id as crm_recur_id  , msg.payment_instrument_id
    FROM $messages_table_name msg
    LEFT JOIN civicrm_contribution c ON msg.transaction_id = c.trxn_id
    WHERE msg.payment_instrument_id IN ( '1', '2') AND c.id is NULL
    AND msg.processed IS NULL
    ";
    }
    elseif ($cur_type == "PayPal") {
      $messages_table_name = 'pogstone_paypal_messages';
      $sql = "SELECT msgs.id, msgs.amount, msgs.txn_id, substr( msgs.payment_date, 10, 3 ) as payment_date_month ,
    substr( msgs.payment_date, 14, 2 ) as payment_date_day ,
    substr( msgs.payment_date, 18, 4 ) as payment_date_year ,
    concat(msgs.last_name, ',' , msgs.first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` , date_format(message_date, '%Y%m%d'  ) as message_date , `payment_status` ,
      rp_invoice_id, recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.txn_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.id = (  substr( rp_invoice_id, LOCATE( '&r=' , rp_invoice_id) + 3,   ( LOCATE(
    '&b=', rp_invoice_id ) - 3 -  (LOCATE( '&r=' , rp_invoice_id)  ) ) ) )  LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.payment_status = 'Completed' AND length(msgs.recurring_payment_id) > 0 AND c.id IS NULL
       AND msgs.message_date >= '2013-03-01'
       AND msgs.processed IS NULL
       GROUP by msgs.ipn_track_id ";
    }
    elseif ($cur_type == "AuthNet") {
      $messages_table_name = 'pogstone_authnet_messages';
      $sql = "SELECT msgs.id, concat(x_last_name, ',' , x_first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` , date_format(message_date, '%Y%m%d'  ) as message_date ,
           x_amount as message_amount,
           `x_response_code` , `x_response_reason_code` , `x_response_reason_text` , `x_avs_code` , `x_auth_code` , `x_trans_id` ,
     `x_method` , `x_card_type` , `x_account_number` , `x_first_name` , `x_last_name` , `x_company` , `x_address` , `x_city` , `x_state` , `x_zip` ,
      `x_country` , `x_phone` , `x_fax` , `x_email` , `x_invoice_num` , `x_description` , `x_type` , `x_cust_id` , `x_ship_to_first_name` , `x_ship_to_last_name` , `x_ship_to_company` , `x_ship_to_address` , `x_ship_to_city` , `x_ship_to_state` , `x_ship_to_zip` , `x_ship_to_country` , `x_amount` , `x_tax` , `x_duty` , `x_freight` , `x_tax_exempt` , `x_po_num` , `x_MD5_Hash` , `x_cvv2_resp_code` , `x_cavv_response` , `x_test_request` , `x_subscription_id` , `x_subscription_paynum` , recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.x_trans_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.x_subscription_id LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.x_response_code = '1' AND length(msgs.x_subscription_id) > 0 AND c.id IS NULL
       AND msgs.message_date >= '2013-03-01'
       AND msgs.processed IS NULL
        ";
    }
    elseif ($cur_type == "eWay") {
      // Currently only completed eWay transactions have an amount > 0.
      // Raw 'eway_email_date' is always in America/New York time zone. Need to adjust to the time zone of the client, such as Sydney in Australia
      $hours_to_add = "";

      $org_timezone = variable_get('pogstone_local_timezone', NULL);
      if ($org_timezone == 'Australia/Sydney') {
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }
      else if ($org_timezone == 'Australia/Melbourne') {
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }
      else if ($org_timezone == 'Australia/Perth') {
        $num_sec = 60 * 60 * 12;
        $hours_to_add = '12 HOUR';
      }
      else {
        print "<br>org time zone not recognized: " . $org_timezone;
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }

      // field 'eway_email_date' is of type datetime
      //$tmp_a =  $email_timestamp + $num_sec;
      //   print "<br><br>email timestamp: ".$email_timestamp."<br> Adjusted ts: ".$tmp_a;
      // $paymentDate = date('Ymd H:i:s', $tmp_a) ;
      $messages_table_name = 'pogstone_eway_messages';
      $sql = "SELECT recur.id as crm_recur_id,  msgs.eway_transaction_id,
               DATE_ADD( `eway_email_date`,  INTERVAL " . $hours_to_add . " ) as adj_eway_email_date , `eway_currency`, `eway_amount`,
                `eway_transaction_id`, `eway_name`, `eway_address`,
                `eway_invoice_reference_number`, `eway_email_subject`, `eway_email_body`,
                c.id as crm_contrib_id, c.contact_id as contact_id, contact_a.sort_name as crm_contact_name, ct.name as contrib_type_name,
                recur.id as crm_recur_id, recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id,
                 recur_contact.id as recur_contact_id,
                recur_contact.sort_name as recur_contact_name , recur.amount  as crm_amount
               FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.eway_transaction_id = c.trxn_id
               LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.eway_invoice_reference_number
               LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id
               LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id
               LEFT JOIN civicrm_contact contact_a ON c.contact_id = contact_a.id
               LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.eway_amount > 0
               AND msgs.eway_invoice_reference_number LIKE '%(r)' AND c.id IS NULL
               AND msgs.eway_trans_type = 'payment'  ";
    }

    $tmp_server_path = realpath($_SERVER['DOCUMENT_ROOT'] . '/../');
    $filename_prefix = date('Y-m-d');

    $now = date('Y-m-d  H:i:s');

    // Store the posted values in an associative array
    $fields = array();
    // print "<h2>Section: Find new payment processor messages and attempt to create contribution records</h2>";
    if (strlen($sql) > 0) {
      $dao = CRM_Core_DAO::executeQuery($sql);

      while ($dao->fetch()) {
        $message_valid_to_process = true;

        $cid = $dao->recur_contact_id;
        $contrib_type_id = $dao->recur_contribution_type;
        $recur_id = $dao->crm_recur_id;
        $crm_contact_name = $dao->crm_contact_name;
        $card_billingname = $dao->sort_name;
        $crm_amount = $dao->crm_amount;


        if ($cur_type == "iATS") {
          $receive_date = $dao->trans_date;

          $trxn_id = $dao->transaction_id;

          $payment_instrument_id = $dao->payment_instrument_id;
        }
        else if ($cur_type == "PayPal") {
          $date_raw_year = $dao->payment_date_year;
          $date_raw_month = $dao->payment_date_month;
          $date_raw_day = $dao->payment_date_day;

          $tmp_sql_date = $date_raw_year . "-" . $date_raw_month . "-" . $date_raw_day;

          $receive_date = $tmp_sql_date;
          $amount = $dao->amount;
          $trxn_id = $dao->txn_id;
          $processor_subscription_id = $dao->recurring_payment_id;
          $payment_instrument_id = "1";  // Assume Credit Card
          // print "<br>Inside paypal section: amt: ".$amount;
        }
        else if ($cur_type == "AuthNet") {

          $receive_date = $dao->message_date;
          $amount = $dao->x_amount;
          $trxn_id = $dao->x_trans_id;
          $processor_subscription_id = $dao->x_subscription_id;
          $payment_instrument_id = "1";  // Assume Credit Card

          $tmp_trans_amount = number_format($amount, 2);
          $tmp_crm_amount = number_format($crm_amount, 2);
          if ($tmp_crm_amount <> $tmp_trans_amount) {
            $message_valid_to_process = false;
            $message_error_text = "Transaction amount ($tmp_trans_amount) does NOT match CRM amount ($tmp_crm_amount) for this subscription";
          }
        }
        else if ($cur_type == "eWay") {
          // recur.id as crm_recur_id,  msgs.eway_transaction_id,   `eway_email_date`,

          $receive_date = $dao->adj_eway_email_date;
          $amount = $dao->eway_amount;

          $trxn_id = $dao->eway_transaction_id;
          $processor_subscription_id = $dao->crm_recur_id;
          $payment_instrument_id = "1";  // Assume Credit Card
        }

        // this is the fancy new way introduced for version 4.3.x or better
        if (strlen($recur_id) > 0) {
          if (strlen($trxn_id) == 0) {
            //    print "<br><br>Cannot process this message, trxn_id is empty. ";
            //    print "<br> \n Error on contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id;
          }
          else if ($message_valid_to_process <> true) {
            // print "<br><br>Cannot process this message: ".$message_error_text;
            //  print "<br> \n Error on contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id;
          }
          else {
            //  print "<h2>Process for contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id."</h2>";
            if ($log_handle) {
              fwrite($log_handle, "\n Process for contact id: " . $cid . " -- Name on Card: " . $card_billingname . " -- CRM Name: " . $crm_contact_name . " crm_recur_id: " . $recur_id . " trxn id: " . $trxn_id . "  ----------------------------------------------------\n\n");
            }
            $rtn_code = UpdateRecurringContributionSubscription($log_handle, $recur_id, $trxn_id, $receive_date, $payment_instrument_id);

            // TODO: Check rtn_code to see if there was an error.
            $rec_count++;
          }
        }
        else {
          // print "<br>Error: Could not find crm_recur_id for x_subscription_id: ".$processor_subscription_id;
        }

        // Mark message as processed. Reference: https://pogstone.zendesk.com/agent/tickets/11083
        $sql = "
          UPDATE $messages_table_name
          SET processed = %1
          WHERE id = %2
        ";
        $dao_params = array(
          1 => array($now, 'String'),
          2 => array($dao->id, 'Int'),
        );
        CRM_Core_DAO::executeQuery($sql, $dao_params);
      }

      $dao->free();

      handle_messges_with_no_contrib($cur_type, $now);
    }
  }

  handleCancelledSubscriptions();
  return $rec_count;
}

// Test with hard-coded message
// Next 3 values should come from the payment processor message.
/*
  $crm_recur_id = "3";
  $trxn_id = "41122";
  $trxn_receive_date = "20130703";

  UpdateRecurringContributionSubscription($log_handle, $crm_recur_id , $trxn_id, $trxn_receive_date  );
 */

/**
 * For messages not yet associated with a contribution, associate them.
 *
 *
 * @param String $cur_type e.g., 'AuthNet'
 * @param String $timestamp A mysql datetime string. Messages may have already
 *    been processed at $timestamp by handle_the_messages(), but this function
 *    will handle them once more for its own purposes; however it will not
 *    handle any messages already processed at a time other than $timestamp.
 */
function handle_messges_with_no_contrib($cur_type, $timestamp) {
  $start_date = '2015-01-15';

  if ($cur_type == "AuthNet") {
    $messages_table_name = 'pogstone_authnet_messages';

    $sql = " SELECT concat(x_last_name, ',' , x_first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` ,
            date_format(message_date, '%Y-%m-%d'  ) as message_date , `x_type` as trans_type ,
           x_amount as message_amount,
           `x_response_code` , `x_response_reason_code` , `x_response_reason_text` , `x_avs_code` , `x_auth_code` , `x_trans_id` ,
     `x_method` , `x_card_type` , `x_account_number` , `x_first_name` , `x_last_name` , `x_company` , `x_address` , `x_city` , `x_state` , `x_zip` ,
      `x_country` , `x_phone` , `x_fax` , `x_email` , `x_invoice_num` , `x_description` ,  `x_cust_id` , `x_ship_to_first_name` , `x_ship_to_last_name` , `x_ship_to_company` , `x_ship_to_address` , `x_ship_to_city` , `x_ship_to_state` , `x_ship_to_zip` , `x_ship_to_country` , `x_amount` , `x_tax` , `x_duty` , `x_freight` , `x_tax_exempt` , `x_po_num` , `x_MD5_Hash` , `x_cvv2_resp_code` , `x_cavv_response` , `x_test_request` , `x_subscription_id` , `x_subscription_paynum` , recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.x_trans_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.x_subscription_id LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id
       WHERE c.id IS NULL
       AND date(msgs.message_date) >= '$start_date'
       AND x_trans_id <> '0'
       AND x_type IN ( 'auth_capture', 'capture_only',  'credit' )
       AND (msgs.processed IS NULL OR msgs.processed = %1)
        ";

    $dao_params = array(
      1 => array($timestamp, 'String'),
    );

    //  sql for messages missing a contribution:
    $dao = & CRM_Core_DAO::executeQuery($sql, $dao_params);
    while ($dao->fetch()) {

      $trans_id = $dao->x_trans_id;
      $trans_type = $dao->trans_type;
      $message_date = $dao->message_date;
      $response_code = $dao->x_response_code;
      $response_reason_code = $dao->x_response_reason_code;
      $response_reason_text = $dao->x_response_reason_text;
      $crm_recur_id = $dao->crm_recur_id;
      $recur_ct = $dao->recur_ct;
      $recur_contact_id = $dao->recur_contact_id;
      $x_cust_id = $dao->x_cust_id;
      $recur_contribution_type = $dao->recur_contribution_type;
      $trans_description = $dao->x_description;


      //
      $msg_email = $dao->x_email;
      $msg_first_name = $dao->x_first_name;
      $msg_last_name = $dao->x_last_name;
      $message_amount = $dao->message_amount;
      // print "<br><Hr> trans type: ".$trans_type;



      if ($trans_type == "auth_capture" || $trans_type == "capture_only" || $trans_type == "credit") {
        if (strlen($recur_contact_id) == 0) {
          if (strlen($x_cust_id) == 0 || ( is_int($x_cust_id) == false)) {

            $contact_id_tmp = get_contact_from_msg($msg_first_name, $msg_last_name, $msg_email);
          }
          else {
            $contact_id_tmp = $x_cust_id;
          }
        }
        else {
          $contact_id_tmp = $recur_contact_id;
        }

        //print "<br>At this point we have a contact id:".$contact_id_tmp;
        if ($response_code == "1") {
          // completed
          //   print "<br>completed transaction";
          $contribution_status_id = "1"; // CiviCRM Completed status
          if ($trans_type == "auth_capture" || $trans_type == "capture_only") {
            $tmp_source = "automated record-($trans_description)";
          }
          else if ($trans_type == "credit") {
            $tmp_source = "automated record-(Auth.net credit) ($trans_description)";
          }
        }
        else if ($response_code == "2" || $response_code == "3") {
          // failed
          //   print "<br>failed transaction";
          $contribution_status_id = "4"; // CiviCRM Failed status
          $tmp_source = "automated record-" . $response_code . "-" . $response_reason_code . "-" . $response_reason_text . " ($trans_description)";
        }

        $tmp_payment_instrument_id = "1"; // assume credit card for now




        if (strlen($recur_contribution_type) == 0) {
          // Get financial type id for "Unknown Financial";
          $tmp_financial_type_id = getFinancialTypeID_forMessage();
        }
        else {
          $tmp_financial_type_id = $recur_contribution_type;
        }
        if (strlen($tmp_financial_type_id) > 0) {
          if (strlen($crm_recur_id) > 0) {
            $contrib_params = array(
              'version' => 3,
              'sequential' => 1,
              'financial_type_id' => $tmp_financial_type_id,
              'contribution_payment_instrument_id' => $tmp_payment_instrument_id,
              'receive_date' => $message_date,
              'contribution_status_id' => $contribution_status_id,
              'contribution_source' => $tmp_source,
              'total_amount' => $message_amount,
              'contribution_recur_id' => $crm_recur_id,
              'contact_id' => $contact_id_tmp,
              'trxn_id' => $trans_id,
            );
          }
          else {

            $contrib_params = array(
              'version' => 3,
              'sequential' => 1,
              'financial_type_id' => $tmp_financial_type_id,
              'contribution_payment_instrument_id' => $tmp_payment_instrument_id,
              'receive_date' => $message_date,
              'contribution_status_id' => $contribution_status_id,
              'contribution_source' => $tmp_source,
              'total_amount' => $message_amount,
              'contact_id' => $contact_id_tmp,
              'trxn_id' => $trans_id,
            );
          }

          
          $result = civicrm_api('Contribution', 'create', $contrib_params);
          if ($result[is_error] == 1) {

            //print "<br>ERROR creating contribution: ";
            //print "<br>params to api: ";
            //print_r( $contrib_params);
            //print "<br>API result: ";
            //print_r( $result);
          }
        }
        
        // Mark message as processed. Reference: https://pogstone.zendesk.com/agent/tickets/11083
        $sql = "
          UPDATE $messages_table_name
          SET processed = %1
          WHERE id = %2
        ";
        $dao_params = array(<commit_msg>refs #1373: zendesk #11083: SQL fix for Authnet processing, fix php notice.<commit_after><?php

/**
 * ProccessorMessage.Processnewmessages API specification (optional)
 * This is used for documentation and validation.
 *
 * @param array $spec description of fields supported by this API call
 * @return void
 * @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
 */
function _civicrm_api3_proccessor_message_processnewmessages_spec(&$spec) {

}

/**
 * ProccessorMessage.Processnewmessages API
 *
 * @param array $params
 * @return array API result descriptor
 * @see civicrm_api3_create_success
 * @see civicrm_api3_create_error
 * @throws API_Exception
 */
function civicrm_api3_proccessor_message_processnewmessages($params) {
  $rec_count = handle_the_messages();
  $returnValues = array("record count:" . $rec_count);

  return civicrm_api3_create_success($returnValues, $params, 'ProcessorMessage', 'processnewmessages');
}

function handle_the_messages() {
  $all_message_types_tocheck = array();
  $ewayemailrecur_type = "eWay_Recurring";

  $pay_pal_type = "PayPal";
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $pay_pal_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);
  $tmp = $result['values'][0];

  if ($tmp['id'] == $pay_pal_type) {
    $bool_str = $tmp['name'];
    $pay_pal_enabled = $bool_str === 'true' ? true : false;
  }

  if ($pay_pal_enabled) {
    $all_message_types_tocheck[] = "PayPal";
  }

  $authnet_type = "AuthNet";
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $authnet_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);

  $tmp = $result['values'][0];
  if ($tmp['id'] == $authnet_type) {
    $bool_str = $tmp['name'];
    $authnet_enabled = $bool_str === 'true' ? true : false;
  }

  if ($authnet_enabled) {
    $all_message_types_tocheck[] = "AuthNet";
  }

  // Now check for eWay recurring (email notifications)
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'vendor_type' => $ewayemailrecur_type,
  );

  $result = civicrm_api('PaymentProcessorTypeHelper', 'get', $params);
  $tmp = $result['values'][0];

  if ($tmp['id'] == $ewayemailrecur_type) {
    $bool_str = $tmp['name'];
    $ewayrecur_enabled = $bool_str === 'true' ? true : false;
  }

  if ($ewayrecur_enabled) {
    $all_message_types_tocheck[] = "eWay";
  }

  // For each processor type in use, process related messages
  $rec_count = 0;
  foreach ($all_message_types_tocheck as $cur_type) {

    if ($cur_type == "iATS") {
      $messages_table_name = 'pogstone_iats_messages';
      $sql = " SELECT    msg.id, msg.transaction_id as transaction_id ,
     msg.trans_date,
     msg.recur_id as crm_recur_id  , msg.payment_instrument_id
    FROM $messages_table_name msg
    LEFT JOIN civicrm_contribution c ON msg.transaction_id = c.trxn_id
    WHERE msg.payment_instrument_id IN ( '1', '2') AND c.id is NULL
    AND msg.processed IS NULL
    ";
    }
    elseif ($cur_type == "PayPal") {
      $messages_table_name = 'pogstone_paypal_messages';
      $sql = "SELECT msgs.id, msgs.amount, msgs.txn_id, substr( msgs.payment_date, 10, 3 ) as payment_date_month ,
    substr( msgs.payment_date, 14, 2 ) as payment_date_day ,
    substr( msgs.payment_date, 18, 4 ) as payment_date_year ,
    concat(msgs.last_name, ',' , msgs.first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` , date_format(message_date, '%Y%m%d'  ) as message_date , `payment_status` ,
      rp_invoice_id, recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.txn_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.id = (  substr( rp_invoice_id, LOCATE( '&r=' , rp_invoice_id) + 3,   ( LOCATE(
    '&b=', rp_invoice_id ) - 3 -  (LOCATE( '&r=' , rp_invoice_id)  ) ) ) )  LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.payment_status = 'Completed' AND length(msgs.recurring_payment_id) > 0 AND c.id IS NULL
       AND msgs.message_date >= '2013-03-01'
       AND msgs.processed IS NULL
       GROUP by msgs.ipn_track_id ";
    }
    elseif ($cur_type == "AuthNet") {
      $messages_table_name = 'pogstone_authnet_messages';
      $sql = "SELECT msgs.id, concat(x_last_name, ',' , x_first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` , date_format(message_date, '%Y%m%d'  ) as message_date ,
           x_amount as message_amount,
           `x_response_code` , `x_response_reason_code` , `x_response_reason_text` , `x_avs_code` , `x_auth_code` , `x_trans_id` ,
     `x_method` , `x_card_type` , `x_account_number` , `x_first_name` , `x_last_name` , `x_company` , `x_address` , `x_city` , `x_state` , `x_zip` ,
      `x_country` , `x_phone` , `x_fax` , `x_email` , `x_invoice_num` , `x_description` , `x_type` , `x_cust_id` , `x_ship_to_first_name` , `x_ship_to_last_name` , `x_ship_to_company` , `x_ship_to_address` , `x_ship_to_city` , `x_ship_to_state` , `x_ship_to_zip` , `x_ship_to_country` , `x_amount` , `x_tax` , `x_duty` , `x_freight` , `x_tax_exempt` , `x_po_num` , `x_MD5_Hash` , `x_cvv2_resp_code` , `x_cavv_response` , `x_test_request` , `x_subscription_id` , `x_subscription_paynum` , recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.x_trans_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.x_subscription_id LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.x_response_code = '1' AND length(msgs.x_subscription_id) > 0 AND c.id IS NULL
       AND msgs.message_date >= '2013-03-01'
       AND msgs.processed IS NULL
        ";
    }
    elseif ($cur_type == "eWay") {
      // Currently only completed eWay transactions have an amount > 0.
      // Raw 'eway_email_date' is always in America/New York time zone. Need to adjust to the time zone of the client, such as Sydney in Australia
      $hours_to_add = "";

      $org_timezone = variable_get('pogstone_local_timezone', NULL);
      if ($org_timezone == 'Australia/Sydney') {
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }
      else if ($org_timezone == 'Australia/Melbourne') {
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }
      else if ($org_timezone == 'Australia/Perth') {
        $num_sec = 60 * 60 * 12;
        $hours_to_add = '12 HOUR';
      }
      else {
        print "<br>org time zone not recognized: " . $org_timezone;
        $num_sec = 60 * 60 * 14;
        $hours_to_add = '14 HOUR';
      }

      // field 'eway_email_date' is of type datetime
      //$tmp_a =  $email_timestamp + $num_sec;
      //   print "<br><br>email timestamp: ".$email_timestamp."<br> Adjusted ts: ".$tmp_a;
      // $paymentDate = date('Ymd H:i:s', $tmp_a) ;
      $messages_table_name = 'pogstone_eway_messages';
      $sql = "SELECT recur.id as crm_recur_id,  msgs.eway_transaction_id,
               DATE_ADD( `eway_email_date`,  INTERVAL " . $hours_to_add . " ) as adj_eway_email_date , `eway_currency`, `eway_amount`,
                `eway_transaction_id`, `eway_name`, `eway_address`,
                `eway_invoice_reference_number`, `eway_email_subject`, `eway_email_body`,
                c.id as crm_contrib_id, c.contact_id as contact_id, contact_a.sort_name as crm_contact_name, ct.name as contrib_type_name,
                recur.id as crm_recur_id, recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id,
                 recur_contact.id as recur_contact_id,
                recur_contact.sort_name as recur_contact_name , recur.amount  as crm_amount
               FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.eway_transaction_id = c.trxn_id
               LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.eway_invoice_reference_number
               LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id
               LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id
               LEFT JOIN civicrm_contact contact_a ON c.contact_id = contact_a.id
               LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id WHERE msgs.eway_amount > 0
               AND msgs.eway_invoice_reference_number LIKE '%(r)' AND c.id IS NULL
               AND msgs.eway_trans_type = 'payment'  ";
    }

    $tmp_server_path = realpath($_SERVER['DOCUMENT_ROOT'] . '/../');
    $filename_prefix = date('Y-m-d');

    $now = date('Y-m-d  H:i:s');

    // Store the posted values in an associative array
    $fields = array();
    // print "<h2>Section: Find new payment processor messages and attempt to create contribution records</h2>";
    if (strlen($sql) > 0) {
      $dao = CRM_Core_DAO::executeQuery($sql);

      while ($dao->fetch()) {
        $message_valid_to_process = true;

        $cid = $dao->recur_contact_id;
        $contrib_type_id = $dao->recur_contribution_type;
        $recur_id = $dao->crm_recur_id;
        $crm_contact_name = $dao->crm_contact_name;
        $card_billingname = $dao->sort_name;
        $crm_amount = $dao->crm_amount;


        if ($cur_type == "iATS") {
          $receive_date = $dao->trans_date;

          $trxn_id = $dao->transaction_id;

          $payment_instrument_id = $dao->payment_instrument_id;
        }
        else if ($cur_type == "PayPal") {
          $date_raw_year = $dao->payment_date_year;
          $date_raw_month = $dao->payment_date_month;
          $date_raw_day = $dao->payment_date_day;

          $tmp_sql_date = $date_raw_year . "-" . $date_raw_month . "-" . $date_raw_day;

          $receive_date = $tmp_sql_date;
          $amount = $dao->amount;
          $trxn_id = $dao->txn_id;
          $processor_subscription_id = $dao->recurring_payment_id;
          $payment_instrument_id = "1";  // Assume Credit Card
          // print "<br>Inside paypal section: amt: ".$amount;
        }
        else if ($cur_type == "AuthNet") {

          $receive_date = $dao->message_date;
          $amount = $dao->x_amount;
          $trxn_id = $dao->x_trans_id;
          $processor_subscription_id = $dao->x_subscription_id;
          $payment_instrument_id = "1";  // Assume Credit Card

          $tmp_trans_amount = number_format($amount, 2);
          $tmp_crm_amount = number_format($crm_amount, 2);
          if ($tmp_crm_amount <> $tmp_trans_amount) {
            $message_valid_to_process = false;
            $message_error_text = "Transaction amount ($tmp_trans_amount) does NOT match CRM amount ($tmp_crm_amount) for this subscription";
          }
        }
        else if ($cur_type == "eWay") {
          // recur.id as crm_recur_id,  msgs.eway_transaction_id,   `eway_email_date`,

          $receive_date = $dao->adj_eway_email_date;
          $amount = $dao->eway_amount;

          $trxn_id = $dao->eway_transaction_id;
          $processor_subscription_id = $dao->crm_recur_id;
          $payment_instrument_id = "1";  // Assume Credit Card
        }

        // this is the fancy new way introduced for version 4.3.x or better
        if (strlen($recur_id) > 0) {
          if (strlen($trxn_id) == 0) {
            //    print "<br><br>Cannot process this message, trxn_id is empty. ";
            //    print "<br> \n Error on contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id;
          }
          else if ($message_valid_to_process <> true) {
            // print "<br><br>Cannot process this message: ".$message_error_text;
            //  print "<br> \n Error on contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id;
          }
          else {
            //  print "<h2>Process for contact id: ".$cid." -- Name on Card: ".$card_billingname." -- CRM Name: ".$crm_contact_name." crm_recur_id: ".$recur_id."</h2>";
            if ($log_handle) {
              fwrite($log_handle, "\n Process for contact id: " . $cid . " -- Name on Card: " . $card_billingname . " -- CRM Name: " . $crm_contact_name . " crm_recur_id: " . $recur_id . " trxn id: " . $trxn_id . "  ----------------------------------------------------\n\n");
            }
            $rtn_code = UpdateRecurringContributionSubscription($log_handle, $recur_id, $trxn_id, $receive_date, $payment_instrument_id);

            // TODO: Check rtn_code to see if there was an error.
            $rec_count++;
          }
        }
        else {
          // print "<br>Error: Could not find crm_recur_id for x_subscription_id: ".$processor_subscription_id;
        }

        // Mark message as processed. Reference: https://pogstone.zendesk.com/agent/tickets/11083
        $sql = "
          UPDATE $messages_table_name
          SET processed = %1
          WHERE id = %2
        ";
        $dao_params = array(
          1 => array($now, 'String'),
          2 => array($dao->id, 'Int'),
        );
        CRM_Core_DAO::executeQuery($sql, $dao_params);
      }

      $dao->free();

      handle_messges_with_no_contrib($cur_type, $now);
    }
  }

  handleCancelledSubscriptions();
  return $rec_count;
}

// Test with hard-coded message
// Next 3 values should come from the payment processor message.
/*
  $crm_recur_id = "3";
  $trxn_id = "41122";
  $trxn_receive_date = "20130703";

  UpdateRecurringContributionSubscription($log_handle, $crm_recur_id , $trxn_id, $trxn_receive_date  );
 */

/**
 * For messages not yet associated with a contribution, associate them.
 *
 *
 * @param String $cur_type e.g., 'AuthNet'
 * @param String $timestamp A mysql datetime string. Messages may have already
 *    been processed at $timestamp by handle_the_messages(), but this function
 *    will handle them once more for its own purposes; however it will not
 *    handle any messages already processed at a time other than $timestamp.
 */
function handle_messges_with_no_contrib($cur_type, $timestamp) {
  $start_date = '2015-01-15';

  if ($cur_type == "AuthNet") {
    $messages_table_name = 'pogstone_authnet_messages';

    $sql = " SELECT msgs.id, concat(x_last_name, ',' , x_first_name) as sort_name , `civicrm_recur_id` , c.id as crm_contrib_id, c.contact_id as crm_contact_id, con.sort_name as crm_contact_name, recur.id as crm_recur_id, ct.name as contrib_type_name, recur_ct.id as recur_contribution_type , recur_ct.name as recur_contrib_type_name, recur.contact_id as recur_contact_id, recur_contact.id as recur_contact_id, recur_contact.sort_name as recur_contact_name, `rec_type` ,
            date_format(message_date, '%Y-%m-%d'  ) as message_date , `x_type` as trans_type ,
           x_amount as message_amount,
           `x_response_code` , `x_response_reason_code` , `x_response_reason_text` , `x_avs_code` , `x_auth_code` , `x_trans_id` ,
     `x_method` , `x_card_type` , `x_account_number` , `x_first_name` , `x_last_name` , `x_company` , `x_address` , `x_city` , `x_state` , `x_zip` ,
      `x_country` , `x_phone` , `x_fax` , `x_email` , `x_invoice_num` , `x_description` ,  `x_cust_id` , `x_ship_to_first_name` , `x_ship_to_last_name` , `x_ship_to_company` , `x_ship_to_address` , `x_ship_to_city` , `x_ship_to_state` , `x_ship_to_zip` , `x_ship_to_country` , `x_amount` , `x_tax` , `x_duty` , `x_freight` , `x_tax_exempt` , `x_po_num` , `x_MD5_Hash` , `x_cvv2_resp_code` , `x_cavv_response` , `x_test_request` , `x_subscription_id` , `x_subscription_paynum` , recur.amount  as crm_amount
      FROM $messages_table_name as msgs LEFT JOIN civicrm_contribution c ON msgs.x_trans_id = c.trxn_id LEFT JOIN civicrm_contact con ON c.contact_id = con.id LEFT JOIN civicrm_contribution_recur recur ON recur.processor_id = msgs.x_subscription_id LEFT JOIN civicrm_financial_type recur_ct ON recur.financial_type_id = recur_ct.id LEFT JOIN civicrm_contact recur_contact ON recur.contact_id = recur_contact.id LEFT JOIN civicrm_financial_type ct ON c.financial_type_id = ct.id
       WHERE c.id IS NULL
       AND date(msgs.message_date) >= '$start_date'
       AND x_trans_id <> '0'
       AND x_type IN ( 'auth_capture', 'capture_only',  'credit' )
       AND (msgs.processed IS NULL OR msgs.processed = %1)
        ";

    $dao_params = array(
      1 => array($timestamp, 'String'),
    );

    //  sql for messages missing a contribution:
    $dao = & CRM_Core_DAO::executeQuery($sql, $dao_params);
    while ($dao->fetch()) {

      $trans_id = $dao->x_trans_id;
      $trans_type = $dao->trans_type;
      $message_date = $dao->message_date;
      $response_code = $dao->x_response_code;
      $response_reason_code = $dao->x_response_reason_code;
      $response_reason_text = $dao->x_response_reason_text;
      $crm_recur_id = $dao->crm_recur_id;
      $recur_ct = $dao->recur_ct;
      $recur_contact_id = $dao->recur_contact_id;
      $x_cust_id = $dao->x_cust_id;
      $recur_contribution_type = $dao->recur_contribution_type;
      $trans_description = $dao->x_description;


      //
      $msg_email = $dao->x_email;
      $msg_first_name = $dao->x_first_name;
      $msg_last_name = $dao->x_last_name;
      $message_amount = $dao->message_amount;
      // print "<br><Hr> trans type: ".$trans_type;



      if ($trans_type == "auth_capture" || $trans_type == "capture_only" || $trans_type == "credit") {
        if (strlen($recur_contact_id) == 0) {
          if (strlen($x_cust_id) == 0 || ( is_int($x_cust_id) == false)) {

            $contact_id_tmp = get_contact_from_msg($msg_first_name, $msg_last_name, $msg_email);
          }
          else {
            $contact_id_tmp = $x_cust_id;
          }
        }
        else {
          $contact_id_tmp = $recur_contact_id;
        }

        //print "<br>At this point we have a contact id:".$contact_id_tmp;
        if ($response_code == "1") {
          // completed
          //   print "<br>completed transaction";
          $contribution_status_id = "1"; // CiviCRM Completed status
          if ($trans_type == "auth_capture" || $trans_type == "capture_only") {
            $tmp_source = "automated record-($trans_description)";
          }
          else if ($trans_type == "credit") {
            $tmp_source = "automated record-(Auth.net credit) ($trans_description)";
          }
        }
        else if ($response_code == "2" || $response_code == "3") {
          // failed
          //   print "<br>failed transaction";
          $contribution_status_id = "4"; // CiviCRM Failed status
          $tmp_source = "automated record-" . $response_code . "-" . $response_reason_code . "-" . $response_reason_text . " ($trans_description)";
        }

        $tmp_payment_instrument_id = "1"; // assume credit card for now




        if (strlen($recur_contribution_type) == 0) {
          // Get financial type id for "Unknown Financial";
          $tmp_financial_type_id = getFinancialTypeID_forMessage();
        }
        else {
          $tmp_financial_type_id = $recur_contribution_type;
        }
        if (strlen($tmp_financial_type_id) > 0) {
          if (strlen($crm_recur_id) > 0) {
            $contrib_params = array(
              'version' => 3,
              'sequential' => 1,
              'financial_type_id' => $tmp_financial_type_id,
              'contribution_payment_instrument_id' => $tmp_payment_instrument_id,
              'receive_date' => $message_date,
              'contribution_status_id' => $contribution_status_id,
              'contribution_source' => $tmp_source,
              'total_amount' => $message_amount,
              'contribution_recur_id' => $crm_recur_id,
              'contact_id' => $contact_id_tmp,
              'trxn_id' => $trans_id,
            );
          }
          else {

            $contrib_params = array(
              'version' => 3,
              'sequential' => 1,
              'financial_type_id' => $tmp_financial_type_id,
              'contribution_payment_instrument_id' => $tmp_payment_instrument_id,
              'receive_date' => $message_date,
              'contribution_status_id' => $contribution_status_id,
              'contribution_source' => $tmp_source,
              'total_amount' => $message_amount,
              'contact_id' => $contact_id_tmp,
              'trxn_id' => $trans_id,
            );
          }

          
          $result = civicrm_api3('Contribution', 'create', $contrib_params);
        }
        
        // Mark message as processed. Reference: https://pogstone.zendesk.com/agent/tickets/11083
        $sql = "
          UPDATE $messages_table_name
          SET processed = %1
          WHERE id = %2
        ";
        $dao_params = array(
{'fraction_non_alphanumeric': 0.12437131608292938, 'fraction_numerical': 0.0073507657995949115, 'mean_word_length': 2.960165825522711, 'pattern_counts': {'":': 0, '<': 56, '<?xml version=': 0, '>': 228, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2004518', 'n_tokens_mistral': 15755, 'n_tokens_neox': 15192, 'n_words': 3141}