acquia_commercemanager-8.x-1.122/modules/acm/src/Connector/AgentRequestTrait.php

modules/acm/src/Connector/AgentRequestTrait.php
<?php

namespace Drupal\acm\Connector;

use Acquia\Hmac\Exception\MalformedResponseException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\TransferStats;
use GuzzleHttp\Exception\RequestException;

/**
 * Trait AgentRequestTrait.
 *
 * @package Drupal\acm\Connector
 *
 * @ingroup acm
 */
trait AgentRequestTrait {

  /**
   * Version of API.
   *
   * @var string
   */
  protected $apiVersion;

  /**
   * HTTP (Guzzle) Connector Client Factory.
   *
   * @var ClientFactory
   */
  protected $clientFactory;

  /**
   * Debug / Verbose Connection Logging.
   *
   * @var bool
   */
  private $debug;

  /**
   * System / Watchdog Logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * TryAgentRequest.
   *
   * Try a simple request with the Guzzle client, adding debug callbacks
   * and catching / logging request exceptions if needed.
   *
   * @param callable $doReq
   *   Request closure, passed client and opts array.
   * @param string $action
   *   Action name for logging.
   * @param string $reskey
   *   Result data key (or NULL)
   * @param string $acm_uuid
   *   The acm_uuid used to create the client.
   *
   * @return mixed
   *   API response.
   *
   * @throws \Exception
   */
  protected function tryAgentRequest(callable $doReq, $action, $reskey = NULL, $acm_uuid = "") {

    $client = $this->clientFactory->createClient($acm_uuid);
    $reqOpts = [];
    $logger = ($this->logger) ?: \Drupal::logger('acm');

    if ($this->debug) {
      $logger->info(sprintf('%s: Attempting Request.', $action));

      // Log transfer final endpoint and total time in debug mode.
      $reqOpts['on_stats'] =
        function (TransferStats $stats) use ($logger, $action) {
          $code =
            ($stats->hasResponse()) ?
              $stats->getResponse()->getStatusCode() :
              0;

          $logger->info(sprintf(
            '%s: Requested %s in %.4f [%d].',
            $action,
            $stats->getEffectiveUri(),
            $stats->getTransferTime(),
            $code
          ));
        };
    }

    if ($acm_uuid) {
      // This can be overridden in doReq function or using updateStoreContext.
      $reqOpts['query']['store_id'] = $acm_uuid;
    }
    else {
      // This can be overridden in doReq function or using updateStoreContext.
      $reqOpts['query']['store_id'] = $this->storeId;
    }

    // Make Request.
    try {
      /** @var \GuzzleHttp\Psr7\Response $result */
      $result = $doReq($client, $reqOpts);
    }
    catch (\Exception $e) {
      $class = get_class($e);

      $mesg = sprintf(
        '%s: %s during request: (%d) - %s',
        $action,
        $class,
        $e->getCode(),
        $e->getMessage()
      );

      $logger->error($mesg);

      // REDUNDANT at 20180531 because now we set http_errors = false.
      if ($e->getCode() == 404
        || $e instanceof MalformedResponseException
        || $e instanceof ConnectException) {
        throw new \Exception(acm_api_down_global_error_message(), APIWrapper::API_DOWN_ERROR_CODE);
      }
      elseif ($e instanceof RequestException) {
        throw new ConnectorException($mesg, $e->getCode(), $e);
      }
      else {
        throw $e;
      }
    }

    // This code means we must always return valid JSON for every HTTP status.
    // Is that what we want to enforce? Probably yes.
    $response = json_decode($result->getBody(), TRUE);
    if (($response === NULL) || ($this->apiVersion === 'v1' && !isset($response['success']))) {
      $mesg = sprintf(
        '%s: Invalid / Unrecognized Connector response: %s',
        $action,
        $result->getBody()
      );

      $logger->error($mesg);
      throw new ConnectorException($mesg);
    }

    // Earlier we set http_errors = false during client-creation so now
    // we need to handle all response statuses here.
    // For now (at 20180531) we simply handle http 500 'customer not found'
    // And revert to the previous behaviour for all other non-200 responses.
    $exception = NULL;
    switch ($result->getStatusCode()) {
      case 200:
        // Continue.
        break;

      case 500:
        if (array_key_exists('code', $response)) {
          if ($response['code'] == CustomerNotFoundException::CUSTOMER_NOT_FOUND_CODE) {
            // Are we logging here? CustomerNotFound is routine so
            // we choose not to log this exception.
            $exception = new CustomerNotFoundException($response['message'], $response['code']);
          }
          else {
            $exception = new ConnectorException($response['message'], $response['code']);
          }
        }
        else {
          $exception = new ConnectorException($result->getBody(), $result->getStatusCode());
        }
        break;

      default:
        throw new ConnectorException($result->getBody(), $result->getStatusCode());
    }

    if ($exception) {
      throw $exception;
    }

    if ($this->apiVersion === 'v1' && !$response['success']) {
      $logger->info(sprintf(
        '%s: Connector request unsuccessful: %s',
        $action,
        $result->getBody()
      ));

      // Process the response to check if error is downtime error
      // from Magento.
      $errors = [];
      if (preg_match('/response:(.*)/i', $result->getBody(), $errors)) {
        if (isset($errors[1])) {
          $error = json_decode(strtolower($errors[1]), TRUE);

          if (isset($error['status'])) {
            $error_code = (int) $error['status'];

            if ($error_code >= 500 && $error_code < 600) {
              throw new \Exception(acm_api_down_global_error_message(), APIWrapper::API_DOWN_ERROR_CODE);
            }
          }
        }
      }

      throw new ConnectorResultException($response);
    }

    if ($this->apiVersion === 'v1' && strlen($reskey)) {
      if (!isset($response[$reskey])) {
        throw new ConnectorResultException($response);
      }

      return ($response[$reskey]);
    }
    else {
      if ($this->debug) {
        $logger->debug("Response: " . nl2br(print_r($response, TRUE)));
      }
      return ($response);
    }
  }

}

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

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