<commit_before><?php
/*--------------------------------------------------------------------+
 | CiviCRM version 4.7                                                |
+--------------------------------------------------------------------+
 | Copyright CiviCRM LLC (c) 2004-2017                                |
+--------------------------------------------------------------------+
 | This file is a part of CiviCRM.                                    |
 |                                                                    |
 | CiviCRM is free software; you can copy, modify, and distribute it  |
 | under the terms of the GNU Affero General Public License           |
 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
 |                                                                    |
 | CiviCRM is distributed in the hope that it will be useful, but     |
 | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | See the GNU Affero General Public License for more details.        |
 |                                                                    |
 | You should have received a copy of the GNU Affero General Public   |
 | License and the CiviCRM Licensing Exception along                  |
 | with this program; if not, contact CiviCRM LLC                     |
 | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | GNU Affero General Public License or the licensing of CiviCRM,     |
 | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 +-------------------------------------------------------------------*/

/**
 * Class CRM_Core_Payment_Smartdebit
 *
 * Implementation of the Smartdebit payment processor class
 */
class CRM_Core_Payment_Smartdebit extends CRM_Core_Payment
{
  /**
   * We only need one instance of this object. So we use the singleton
   * pattern and cache the instance in this variable
   *
   * @var object
   * @static
   */
  static private $_singleton = NULL;

  /**
   * mode of operation: live or test
   *
   * @var object
   */
  protected $_mode = NULL;

  /**
   * Constructor
   *
   * @param string $mode the mode of operation: live or test
   * @param $paymentProcessor
   */
  function __construct($mode, &$paymentProcessor)
  {
    $this->_mode = $mode;
    $this->_paymentProcessor = $paymentProcessor;
    $this->_processorName = ts('Smart Debit Processor');
  }

  /**
   * singleton function used to manage this object
   *
   * @param string $mode the mode of operation: live or test
   * @param $paymentProcessor
   * @return object
   * @static
   *
   */
  static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = FALSE)
  {
    $processorName = $paymentProcessor['name'];
    if (self::$_singleton[$processorName] === NULL) {
      self::$_singleton[$processorName] = new self($mode, $paymentProcessor);
    }
    return self::$_singleton[$processorName];
  }

  /**
   * This function checks to see if we have the right config values
   *
   * @return string the error message if any
   * @public
   */
  function checkConfig()
  {
    $error = array();

    if (empty($this->_paymentProcessor['user_name'])) {
      $error[] = ts('The "username" is not set in the Smart Debit Payment Processor settings.');
    }

    if (empty($this->_paymentProcessor['password'])) {
      $error[] = ts('The "password" is not set in the Smart Debit Payment Processor settings.');
    }

    if (!empty($error)) {
      return implode('<p>', $error);
    }
    else {
      return NULL;
    }
  }

  /**
   * Get Smart Debit User Details
   *
   * @param null $id
   * @param bool $test
   * @param bool $isActive
   *
   * @return array|bool
   */
  public static function getProcessorDetails($id = NULL, $test = FALSE, $isActive = TRUE) {
    $params = array(
      'is_test' => $test,
      'is_active' => $isActive,
      'domain_id' => CRM_Core_Config::domainID(),
    );
    if (!empty($id)) {
      $params['id'] = $id;
    }
    else {
      $paymentProcessorTypeId = CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_PaymentProcessor', 'payment_processor_type_id', 'Smart_Debit');
      $params['payment_processor_type_id'] = $paymentProcessorTypeId;
      $params['options'] = array('sort' => "id DESC", 'limit' => 1);
    }

    try {
      $paymentProcessorDetails = civicrm_api3('PaymentProcessor', 'getsingle', $params);
    }
    catch (Exception $e) {
      CRM_Core_Session::setStatus(ts('Smart Debit API User Details Missing, Please check the Smart Debit Payment Processor is configured Properly'), 'Smart Debit', 'error');
      return FALSE;
    }

    return $paymentProcessorDetails;
  }

  /**
   * @param CRM_Core_Form $form
   * @return bool|void
   */
  function buildForm(&$form)
  {
    if ($form->isSubmitted()) return;

    // Set ddi_reference
    $defaults = array();
    $defaults['ddi_reference'] = CRM_Smartdebit_Base::getDDIReference();
    // Set preferred collection day default to the first choice.
    $collectionDaysArray = CRM_Smartdebit_Base::getCollectionDaysOptions();
    if (count($collectionDaysArray) > 0) {
      $defaults['preferred_collection_day'] = reset(array_keys($collectionDaysArray));
    }

    // Set default confirmby option
    $confirmBy = CRM_Smartdebit_Base::getConfirmByOptions();
    if (count($confirmBy) > 0) {
      $defaults['confirmation_method'] = reset(array_keys($confirmBy));
    }
    $form->setDefaults($defaults);

    // Add help and javascript
    CRM_Core_Region::instance('billing-block')->add(
      array('template' => 'CRM/Core/Payment/Smartdebit/Smartdebit.tpl', 'weight' => -1));

    return;
  }

  /**
   * Override custom PI validation
   *  to validate payment details with SmartDebit
   * Sets appropriate parameters and calls Smart Debit API to validate a payment (does not setup the payment)
   *
   * @param array $values
   * @param array $errors
   */
  public function validatePaymentInstrument($values, &$errors) {
    parent::validatePaymentInstrument($values, $errors);

    $smartDebitParams = self::preparePostArray($values);

    // Get the API Username and Password
    $username = $this->_paymentProcessor['user_name'];
    $password = $this->_paymentProcessor['password'];

    $url = CRM_Smartdebit_Api::buildUrl($this->_paymentProcessor, 'api/ddi/variable/validate');
    $response = CRM_Smartdebit_Api::requestPost($url, $smartDebitParams, $username, $password);

    $direct_debit_response = array();
    $direct_debit_response['data_type'] = 'recurring';
    $direct_debit_response['entity_type'] = 'contribution_recur';
    $direct_debit_response['first_collection_date'] = $smartDebitParams['variable_ddi[start_date]'];
    $direct_debit_response['preferred_collection_day'] = $values['preferred_collection_day'];
    $direct_debit_response['confirmation_method'] = $values['confirmation_method'];
    $direct_debit_response['ddi_reference'] = $values['ddi_reference'];
    $direct_debit_response['response_status'] = $response['message'];

    // On success an array is returned, last success element is an array of attributes
    if ((is_array($response['success'])) && isset(end($response['success'])['@attributes'])) {
      foreach (end($response['success'])['@attributes'] as $key => $value) {
        $direct_debit_response[$key] = $value;
      }
    }

    // Take action based upon the response status
    if ($response['success']) {
      $direct_debit_response['entity_id'] = isset($values['entity_id']) ? $values['entity_id'] : 0;
      self::recordSmartDebitResponse($direct_debit_response);
    }
    else {
      self::formatErrorsForContributionForm($response['error'], $errors);
    }
  }

  public static function formatErrorsForContributionForm($responseErrors, &$errors) {
    if (!is_array($responseErrors)) {
      $responseErrors = array($responseErrors);
    }
    foreach ($responseErrors as $error) {
      $shortErr = substr($error, 0, 14);
      switch ($shortErr) {
        case 'Sort code is i': // Sort code ..
          $errors['bank_identification_number'] = CRM_Utils_Array::value('bank_identification_number', $errors) . $error . '. ';
          break;
        case 'Account number': // Account number ..<commit_msg>NFC: Rename variable for consistency<commit_after><?php
/*--------------------------------------------------------------------+
 | CiviCRM version 4.7                                                |
+--------------------------------------------------------------------+
 | Copyright CiviCRM LLC (c) 2004-2017                                |
+--------------------------------------------------------------------+
 | This file is a part of CiviCRM.                                    |
 |                                                                    |
 | CiviCRM is free software; you can copy, modify, and distribute it  |
 | under the terms of the GNU Affero General Public License           |
 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
 |                                                                    |
 | CiviCRM is distributed in the hope that it will be useful, but     |
 | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | See the GNU Affero General Public License for more details.        |
 |                                                                    |
 | You should have received a copy of the GNU Affero General Public   |
 | License and the CiviCRM Licensing Exception along                  |
 | with this program; if not, contact CiviCRM LLC                     |
 | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | GNU Affero General Public License or the licensing of CiviCRM,     |
 | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 +-------------------------------------------------------------------*/

/**
 * Class CRM_Core_Payment_Smartdebit
 *
 * Implementation of the Smartdebit payment processor class
 */
class CRM_Core_Payment_Smartdebit extends CRM_Core_Payment
{
  /**
   * We only need one instance of this object. So we use the singleton
   * pattern and cache the instance in this variable
   *
   * @var object
   * @static
   */
  static private $_singleton = NULL;

  /**
   * mode of operation: live or test
   *
   * @var object
   */
  protected $_mode = NULL;

  /**
   * Constructor
   *
   * @param string $mode the mode of operation: live or test
   * @param $paymentProcessor
   */
  function __construct($mode, &$paymentProcessor)
  {
    $this->_mode = $mode;
    $this->_paymentProcessor = $paymentProcessor;
    $this->_processorName = ts('Smart Debit Processor');
  }

  /**
   * singleton function used to manage this object
   *
   * @param string $mode the mode of operation: live or test
   * @param $paymentProcessor
   * @return object
   * @static
   *
   */
  static function &singleton($mode, &$paymentProcessor, &$paymentForm = NULL, $force = FALSE)
  {
    $processorName = $paymentProcessor['name'];
    if (self::$_singleton[$processorName] === NULL) {
      self::$_singleton[$processorName] = new self($mode, $paymentProcessor);
    }
    return self::$_singleton[$processorName];
  }

  /**
   * This function checks to see if we have the right config values
   *
   * @return string the error message if any
   * @public
   */
  function checkConfig()
  {
    $error = array();

    if (empty($this->_paymentProcessor['user_name'])) {
      $error[] = ts('The "username" is not set in the Smart Debit Payment Processor settings.');
    }

    if (empty($this->_paymentProcessor['password'])) {
      $error[] = ts('The "password" is not set in the Smart Debit Payment Processor settings.');
    }

    if (!empty($error)) {
      return implode('<p>', $error);
    }
    else {
      return NULL;
    }
  }

  /**
   * Get Smart Debit User Details
   *
   * @param null $id
   * @param bool $test
   * @param bool $isActive
   *
   * @return array|bool
   */
  public static function getProcessorDetails($id = NULL, $test = FALSE, $isActive = TRUE) {
    $params = array(
      'is_test' => $test,
      'is_active' => $isActive,
      'domain_id' => CRM_Core_Config::domainID(),
    );
    if (!empty($id)) {
      $params['id'] = $id;
    }
    else {
      $paymentProcessorTypeId = CRM_Core_PseudoConstant::getKey('CRM_Financial_BAO_PaymentProcessor', 'payment_processor_type_id', 'Smart_Debit');
      $params['payment_processor_type_id'] = $paymentProcessorTypeId;
      $params['options'] = array('sort' => "id DESC", 'limit' => 1);
    }

    try {
      $paymentProcessorDetails = civicrm_api3('PaymentProcessor', 'getsingle', $params);
    }
    catch (Exception $e) {
      CRM_Core_Session::setStatus(ts('Smart Debit API User Details Missing, Please check the Smart Debit Payment Processor is configured Properly'), 'Smart Debit', 'error');
      return FALSE;
    }

    return $paymentProcessorDetails;
  }

  /**
   * @param CRM_Core_Form $form
   * @return bool|void
   */
  function buildForm(&$form)
  {
    if ($form->isSubmitted()) return;

    // Set ddi_reference
    $defaults = array();
    $defaults['ddi_reference'] = CRM_Smartdebit_Base::getDDIReference();
    // Set preferred collection day default to the first choice.
    $collectionDaysArray = CRM_Smartdebit_Base::getCollectionDaysOptions();
    if (count($collectionDaysArray) > 0) {
      $defaults['preferred_collection_day'] = reset(array_keys($collectionDaysArray));
    }

    // Set default confirmby option
    $confirmBy = CRM_Smartdebit_Base::getConfirmByOptions();
    if (count($confirmBy) > 0) {
      $defaults['confirmation_method'] = reset(array_keys($confirmBy));
    }
    $form->setDefaults($defaults);

    // Add help and javascript
    CRM_Core_Region::instance('billing-block')->add(
      array('template' => 'CRM/Core/Payment/Smartdebit/Smartdebit.tpl', 'weight' => -1));

    return;
  }

  /**
   * Override custom PI validation
   *  to validate payment details with SmartDebit
   * Sets appropriate parameters and calls Smart Debit API to validate a payment (does not setup the payment)
   *
   * @param array $params
   * @param array $errors
   */
  public function validatePaymentInstrument($params, &$errors) {
    parent::validatePaymentInstrument($params, $errors);

    $smartDebitParams = self::preparePostArray($params);
    CRM_Smartdebit_Hook::alterVariableDDIParams($params, $smartDebitParams, 'validate');

    // Get the API Username and Password
    $username = $this->_paymentProcessor['user_name'];
    $password = $this->_paymentProcessor['password'];

    $url = CRM_Smartdebit_Api::buildUrl($this->_paymentProcessor, 'api/ddi/variable/validate');
    $response = CRM_Smartdebit_Api::requestPost($url, $smartDebitParams, $username, $password);

    $direct_debit_response = array();
    $direct_debit_response['data_type'] = 'recurring';
    $direct_debit_response['entity_type'] = 'contribution_recur';
    $direct_debit_response['first_collection_date'] = $smartDebitParams['variable_ddi[start_date]'];
    $direct_debit_response['preferred_collection_day'] = $params['preferred_collection_day'];
    $direct_debit_response['confirmation_method'] = $params['confirmation_method'];
    $direct_debit_response['ddi_reference'] = $params['ddi_reference'];
    $direct_debit_response['response_status'] = $response['message'];

    // On success an array is returned, last success element is an array of attributes
    if ((is_array($response['success'])) && isset(end($response['success'])['@attributes'])) {
      foreach (end($response['success'])['@attributes'] as $key => $value) {
        $direct_debit_response[$key] = $value;
      }
    }

    // Take action based upon the response status
    if ($response['success']) {
      $direct_debit_response['entity_id'] = isset($params['entity_id']) ? $params['entity_id'] : 0;
      self::recordSmartDebitResponse($direct_debit_response);
    }
    else {
      self::formatErrorsForContributionForm($response['error'], $errors);
    }
  }

  public static function formatErrorsForContributionForm($responseErrors, &$errors) {
    if (!is_array($responseErrors)) {
      $responseErrors = array($responseErrors);
    }
    foreach ($responseErrors as $error) {
      $shortErr = substr($error, 0, 14);
      switch ($shortErr) {
        case 'Sort code is i': // Sort code ..
          $errors['bank_identification_number'] = CRM_Utils_Array::value('bank_identification_number', $errors) . $error . '. ';
          break;
        case 'Account number': // Account number ..
{'fraction_non_alphanumeric': 0.15168203040823655, 'fraction_numerical': 0.0031126541362384774, 'mean_word_length': 2.6037532355478863, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1983166', 'n_tokens_mistral': 4756, 'n_tokens_neox': 4562, 'n_words': 1213}