webprofiler-10.0.x-dev/src/DataCollector/HttpDataCollector.php

src/DataCollector/HttpDataCollector.php
<?php

declare(strict_types=1);

namespace Drupal\webprofiler\DataCollector;

use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\webprofiler\Http\HttpClientMiddleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Collects data about http calls during request.
 */
class HttpDataCollector extends DataCollector implements HasPanelInterface {

  use StringTranslationTrait, PanelTrait;

  /**
   * HttpDataCollector constructor.
   *
   * @param \Drupal\webprofiler\Http\HttpClientMiddleware $middleware
   *   The http client middleware.
   */
  public function __construct(
    private readonly HttpClientMiddleware $middleware,
  ) {
    $this->data['completed'] = [];
    $this->data['failed'] = [];
  }

  /**
   * {@inheritdoc}
   */
  public function getName(): string {
    return 'http';
  }

  /**
   * Reset the collected data.
   */
  public function reset(): void {
    $this->data = [];
  }

  /**
   * {@inheritdoc}
   */
  public function collect(Request $request, Response $response, ?\Throwable $exception = NULL): void {
    $completed = $this->middleware->getCompletedRequests();
    $failed = $this->middleware->getFailedRequests();

    foreach ($completed as $data) {
      /** @var \GuzzleHttp\Psr7\Request $request */
      $request = $data['request'];
      /** @var \GuzzleHttp\Psr7\Response $response */
      $response = $data['response'];
      /** @var \GuzzleHttp\TransferStats $stats */
      $stats = $data['stats'];

      $uri = $request->getUri();
      $this->data['completed'][] = [
        'request' => [
          'method' => $request->getMethod(),
          'uri' => [
            'schema' => $uri->getScheme(),
            'host' => $uri->getHost(),
            'port' => $uri->getPort(),
            'path' => $uri->getPath(),
            'query' => $uri->getQuery(),
            'fragment' => $uri->getFragment(),
          ],
          'headers' => $request->getHeaders(),
          'protocol' => $request->getProtocolVersion(),
          'request_target' => $request->getRequestTarget(),
          'stats' => [
            'transferTime' => $stats->getTransferTime(),
            'handlerStats' => $stats->getHandlerStats(),
          ],
        ],
        'response' => [
          'phrase' => $response->getReasonPhrase(),
          'status' => $response->getStatusCode(),
          'headers' => $response->getHeaders(),
          'protocol' => $response->getProtocolVersion(),
        ],
      ];
    }

    foreach ($failed as $data) {
      /** @var \GuzzleHttp\Psr7\Request $request */
      $request = $data['request'];
      /** @var \GuzzleHttp\Psr7\Response|null $response */
      $response = $data['response'];

      $uri = $request->getUri();
      $failureData = [
        'request' => [
          'method' => $request->getMethod(),
          'uri' => [
            'schema' => $uri->getScheme(),
            'host' => $uri->getHost(),
            'port' => $uri->getPort(),
            'path' => $uri->getPath(),
            'query' => $uri->getQuery(),
            'fragment' => $uri->getFragment(),
          ],
          'headers' => $request->getHeaders(),
          'protocol' => $request->getProtocolVersion(),
          'request_target' => $request->getRequestTarget(),
        ],
      ];

      if ($response != NULL) {
        $failureData['response'] = [
          'phrase' => $response->getReasonPhrase(),
          'status' => $response->getStatusCode(),
          'headers' => $response->getHeaders(),
          'protocol' => $response->getProtocolVersion(),
        ];
      }

      $this->data['failed'][] = $failureData;
    }
  }

  /**
   * Returns the number of completed requests.
   *
   * @return int
   *   The number of completed requests.
   */
  public function getCompletedRequestsCount(): int {
    return \count($this->getCompletedRequests());
  }

  /**
   * Returns the completed requests.
   *
   * @return array
   *   The completed requests.
   */
  public function getCompletedRequests(): array {
    return $this->data['completed'];
  }

  /**
   * The number of failed requests.
   *
   * @return int
   *   The number of failed requests.
   */
  public function getFailedRequestsCount(): int {
    return \count($this->getFailedRequests());
  }

  /**
   * Returns the failed requests.
   *
   * @return array
   *   The failed requests.
   */
  public function getFailedRequests(): array {
    return $this->data['failed'];
  }

  /**
   * {@inheritdoc}
   */
  public function getPanel(): array {
    return \array_merge(
      $this->renderHttpCalls($this->getCompletedRequests(), 'Completed'),
      $this->renderHttpCalls($this->getFailedRequests(), 'Failed'),
    );
  }

  /**
   * Render a list of blocks.
   *
   * @param array $calls
   *   The list of blocks to render.
   * @param string $label
   *   The list's label.
   *
   * @return array
   *   The render array of the list of blocks.
   */
  private function renderHttpCalls(array $calls, string $label): array {
    if (\count($calls) == 0) {
      return [
        $label => [
          '#markup' => '<p>' . $this->t('No @label HTTP calls collected',
              ['@label' => $label]) . '</p>',
        ],
      ];
    }

    $rows = [];
    foreach ($calls as $call) {
      $rows[] = [
        $call['request']['method'],
        [
          'data' => [
            '#type' => 'inline_template',
            '#template' => '{{ data|raw }}',
            '#context' => [
              'data' => $this->dumpData($this->cloneVar($call['request']['uri'])),
            ],
          ],
        ],
        [
          'data' => [
            '#type' => 'inline_template',
            '#template' => '{{ data|raw }}',
            '#context' => [
              'data' => $this->dumpData($this->cloneVar($call['request']['headers'])),
            ],
          ],
        ],
        $call['request']['protocol'],
        [
          'data' => [
            '#type' => 'inline_template',
            '#template' => '{{ data|raw }}',
            '#context' => [
              'data' => $this->dumpData($this->cloneVar($call['request']['stats'])),
            ],
          ],
        ],
        [
          'data' => [
            '#type' => 'inline_template',
            '#template' => '{{ data|raw }}',
            '#context' => [
              'data' => $this->dumpData($this->cloneVar($call['response'])),
            ],
          ],
        ],
      ];
    }

    return [
      $label => [
        '#theme' => 'webprofiler_dashboard_section',
        '#title' => $label,
        '#data' => [
          '#type' => 'table',
          '#header' => [
            $this->t('Method'),
            $this->t('Uri'),
            $this->t('Request headers'),
            $this->t('Request protocol'),
            $this->t('Request stats'),
            $this->t('Response'),
          ],
          '#rows' => $rows,
          '#attributes' => [
            'class' => [
              'webprofiler__table',
            ],
          ],
          '#sticky' => TRUE,
        ],
      ],
    ];
  }

}

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

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