care-8.x-1.x-dev/care.module

care.module
<?php

/**
 * @file
 * Utility functions to call CARE web services.
 */

define('IGNORE_ERRORS', TRUE);

/**
 * Call CARE SOAP client with method name and associative array of data.
 *
 * This function handles and logs errors that occur at the SOAP level, or for
 * invalid CARE method calls. It also logs any CARE errors returned from valid
 * calls, unless the $ignore_care_errors optional argument is set to
 * IGNORE_ERRORS.
 *
 * @param string $method_name
 *   The name of the SOAP method to call, e.g. "AddContact".
 * @param array $data
 *   A PHP associative array of parameter data, e.g.
 *     array('Title' => 'Mr', 'Forenames' => 'Fred').
 * @param array $type_data
 *   An optional CARE type and name for the method, if needed, e.g.
 *     array('pSelectDataType' => 'xcdtContactMembershipDetails')
 * @param bool $ignore_care_errors
 *   Set to TRUE if CARE errors should be ignored and not logged.
 *
 * @return SimpleXMLElement
 *   Containing the result, or an object with an ErrorMessage in the case of any
 *   failure.
 */
function care_call_method($method_name, array $data = [], array $type_data = NULL, $ignore_care_errors = FALSE) {
  // Store client object for later calls.
  static $client = NULL;
  $settings = Drupal::config('care.settings');
  $log_calls = $settings->get('care_log_calls');
  $log_results = $settings->get('care_log_results');
  $log = Drupal::logger('care');
  // Don't wait for connection to time out again if it previously failed.
  static $connection_failed = FALSE;
  $result_xml = new SimpleXMLElement('<xml></xml>');
  if ($connection_failed) {
    $log->error('Error: skipped CARE call as a previous call failed to connect');
    $result_xml->addChild('ErrorMessage', t('Error: skipped CARE call as a previous call failed to connect'));
    return $result_xml;
  }
  // Create a SOAP client object for CARE if not already done.
  if (!$client) {
    if ($settings->get('care_database_to_use') === 'test') {
      $service_address_url = $settings->get('care_test_wsdl_url');
      $service_username = $settings->get('care_test_ntlm_username');
      $service_password = $settings->get('care_test_ntlm_password');
    }
    else {
      $service_address_url = $settings->get('care_wsdl_url');
      $service_username = $settings->get('care_ntlm_username');
      $service_password = $settings->get('care_ntlm_password');
    }
    $soap_options = [
      'wsdl_cache' => WSDL_CACHE_BOTH,
    ];
    if ($log_results) {
      $soap_options += [
        'trace' => TRUE,
      ];
    }
    try {
      if (class_exists('SoapClient')) {
        if ($service_username && $service_password) {
          $client = new NtlmSoapClient($service_address_url, $soap_options);
        }
        else {
          $client = new SoapClient($service_address_url, $soap_options);
        }
      }
      else {
        throw new RuntimeException('SoapClient class does not exist.');
      }
    }
    catch (Exception $e) {
      $log->error('Error: @message', [
        '@message' => $e->getMessage(),
      ]);
      $connection_failed = TRUE;
      $result_xml->addChild('ErrorMessage', 'Failed to connect: ' . $e->getMessage());
      return $result_xml;
    }
  }
  // Create new SimpleXML element.
  $xml = new SimpleXMLElement('<Parameters></Parameters>');
  // Add parameters with values as XML child elements.
  foreach ($data as $parameter => $value) {
    if ($parameter) {
      // addChild escapes "<" and ">" but not "&".
      $value = str_replace('&', '&amp;', $value);
      $xml->addChild($parameter, $value);
    }
    else {
      $log->warning('Missing parameter name (PHP array key) for parameter for !method call. Data array: !data', [
        '!method' => $method_name,
        '!data' => print_r($data, TRUE),
      ]);
    }
  }

  // Call the SOAP method.
  try {
    if (is_array($type_data)) {
      // Call typed care method, two arguments.
      $type_type = key($type_data);
      $typename = $type_data[$type_type];
      if ($log_calls !== 'none') {
        $log->notice('@method call: <pre>@params</pre>', [
          '@method' => $method_name,
          '@params' => _care_pretty_xml($xml, $log_results !== 'full'),
        ]);
      }
      $result = $client->$method_name([
        $type_type => $typename,
        'pXMLParams' => $xml->asXML(),
      ]);
      // Return the result as a new SimpleXML element.
      $result_name = $method_name . 'Result';
      $result_xml = new SimpleXMLElement($result->$result_name);
      if ($log_results !== 'none') {
        $log->notice('@method result (@size): <pre>@result</pre>', [
          '@method' => $method_name,
          '@size' => format_size(strlen($client->__getLastResponse())),
          '@result' => _care_pretty_xml($result_xml, $log_results !== 'full'),
        ]);
      }
    }
    else {
      // Call simple care method, one argument.
      if ($log_calls !== 'none') {
        $log->notice('@method call: <pre>@params</pre>', [
          '@method' => $method_name,
          '@params' => _care_pretty_xml($xml),
        ]);
      }
      $result = $client->$method_name([
        'pXMLParams' => $xml->asXML(),
      ]);
      // Return the result as a new SimpleXML element.
      $result_name = $method_name . 'Result';
      $result_xml = new SimpleXMLElement($result->$result_name);
      if ($log_results !== 'none') {
        $log->notice('@method result (@size): <pre>@result</pre>', [
          '@method' => $method_name,
          '@size' => format_size(strlen($client->__getLastResponse())),
          '@result' => _care_pretty_xml($result_xml, $log_results !== 'full'),
        ]);
      }
    }
  }
  catch (Exception $e) {
    $log->error('CARE Error: @message', [
      '@message' => $e->getMessage(),
    ]);
    $result_xml->addChild('ErrorMessage', $e->getMessage());
    return $result_xml;
  }

  // Log any CARE error results.
  if (!$ignore_care_errors && isset($result_xml->ErrorMessage)) {
    $log->error('@method Error: @message', [
      '@method' => $method_name,
      '@message' => (string) $result_xml->ErrorMessage,
    ]);
  }

  return $result_xml;
}

/**
 * Private function to pretty-print XML from a SimpleXML object.
 *
 * @param \SimpleXMLElement $xml
 *   XML data to pretty-print.
 * @param bool $redact
 *   Whether to redact/hide personal information.
 *
 * @return string
 *   Pretty-printed XML.
 */
function _care_pretty_xml(SimpleXMLElement $xml, $redact = TRUE) {
  if ($redact) {
    $xml = clone $xml;
    _care_redact_xml_tree($xml);
  }
  if (extension_loaded('dom')) {
    $doc = new DOMDocument('1.0');
    $doc->formatOutput = TRUE;
    $dom_node = dom_import_simplexml($xml);
    $dom_node = $doc->importNode($dom_node, TRUE);
    $doc->appendChild($dom_node);
    $output = $doc->saveXML();
  }
  else {
    $output = $xml->asXML();
  }
  return $output;
}

function _care_redact_xml_tree(SimpleXMLElement $xml_node) {
  foreach ($xml_node->children() as $child) {
    _care_redact_xml_tree($child);
  }
  $obfuscate_fields = [
    'AddressNumber',
    'ContactNumber',
    'ContactPositionNumber',
    'DefaultContactNumber',
    'MemberNumber',
    'MembershipNumber',
    'OrganisationNumber',
    'ParentNumber',
    'PaymentPlanNumber',
  ];
  foreach ($obfuscate_fields as $field_name) {
    if (isset($xml_node->$field_name) && (string) $xml_node->$field_name !== '') {
      $xml_node->$field_name = substr($xml_node->$field_name, 0, -5) . 'xxxx' . substr($xml_node->$field_name, -1);
    }
  }
  $redact_fields = [
    'Address',
    'AddressLine',
    'AddressLine1',
    'AddressLine2',
    'AddressLine3',
    'AddressMultiLine',
    'ContactName',
    'CurrentAddressLine',
    'CurrentAddressMultiLine',
    'DateOfBirth',
    'DefaultContactName',
    'Forenames',
    'HouseName',
    'InformalSalutation',
    'LabelName',
    'Name',
    'Number',
    'OrganisationName',
    'Postcode',
    'PreferredForename',
    'Salutation',
    'Surname',
    'TownAddressLine',
  ];
  foreach ($redact_fields as $field_name) {
    if (isset($xml_node->$field_name) && (string) $xml_node->$field_name !== '') {
      $xml_node->$field_name = '--redacted--';
    }
  }
}

/**
 * Utility function to convert ISO 3166-1 codes to CARE country codes.
 *
 * @noinspection PhpUnused
 *
 * @param string $iso_code
 *   The ISO code to convert into a CARE country code.
 *
 * @return string
 *   The CARE country code.
 */
function care_iso3166_to_country($iso_code) {
  return _care_lookup_code($iso_code, 'ISO' . strlen($iso_code), 'CARE_code');
}

/**
 * Utility function to convert CARE country codes to ISO 3166-1 codes.
 *
 * @noinspection PhpUnused
 *
 * @param string $country_code
 *   The CARE country code to convert.
 * @param int $letters
 *   The length of the required ISO code in letters.
 *
 * @return string
 *   The ISO code.
 */
function care_country_to_iso3166($country_code, $letters = 2) {
  return _care_lookup_code($country_code, 'CARE_code', 'ISO' . $letters);
}

/**
 * @param string $code
 *   The code to convert.
 * @param string $from
 *   The column to look for the code in.
 * @param string $to
 *   The column containing the converted code.
 *
 * @return string
 *   The converted code.
 */
function _care_lookup_code($code, $from, $to) {
  $to_code = '';
  $file = fopen(drupal_get_path('module', 'care') . '/iso_country_mapping.csv', 'rb');
  $header = fgetcsv($file);
  $from_index = array_search($from, $header, TRUE);
  $to_index = array_search($to, $header, TRUE);
  while (($line = fgetcsv($file)) !== FALSE) {
    if ($line[$from_index] === $code) {
      $to_code = $line[$to_index];
    }
  }
  fclose($file);
  return $to_code;
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc