You are here

class BlueprintManager in Subrequests 3.x

Same name and namespace in other branches
  1. 8.2 src/Blueprint/BlueprintManager.php \Drupal\subrequests\Blueprint\BlueprintManager

Hierarchy

Expanded class hierarchy of BlueprintManager

2 files declare their use of BlueprintManager
BlueprintManagerTest.php in tests/src/Unit/Blueprint/BlueprintManagerTest.php
FrontController.php in src/Controller/FrontController.php
1 string reference to 'BlueprintManager'
subrequests.services.yml in ./subrequests.services.yml
subrequests.services.yml
1 service uses BlueprintManager
subrequests.blueprint_manager in ./subrequests.services.yml
Drupal\subrequests\Blueprint\BlueprintManager

File

src/Blueprint/BlueprintManager.php, line 12

Namespace

Drupal\subrequests\Blueprint
View source
class BlueprintManager {

  /**
   * The deserializer.
   *
   * @var \Symfony\Component\Serializer\SerializerInterface
   */
  protected $serializer;
  public function __construct(Serializer $serializer) {
    $this->serializer = $serializer;
  }

  /**
   * Takes the user input and returns a subrequest tree ready for execution.
   *
   * @param string $input
   *   The input from the user.
   *
   * @return \Drupal\subrequests\SubrequestsTree
   */
  public function parse($input, Request $request) {

    /** @var \Drupal\subrequests\SubrequestsTree $output */
    $output = $this->serializer
      ->deserialize($input, SubrequestsTree::class, 'json');
    $output
      ->setMasterRequest($request);

    // Forward the Host header to place nice with decoupled routers.
    $this
      ->forwardHeader('host', $request, $output);
    return $output;
  }

  /**
   * @param \Symfony\Component\HttpFoundation\Response[] $responses
   *   The responses to combine.
   * @param string $format
   *   The format to combine the responses on. Default is multipart/related.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The combined response with a 207.
   */
  public function combineResponses(array $responses, $format) {
    $context = [
      'sub-content-type' => $this
        ->negotiateSubContentType($responses),
    ];

    // Set the content.
    $normalized = $this->serializer
      ->normalize($responses, $format, $context);
    $response = CacheableResponse::create($normalized['content'], 207, $normalized['headers']);

    // Set the cacheability metadata.
    $cacheable_responses = array_filter($responses, function ($response) {
      return $response instanceof CacheableResponseInterface;
    });
    array_walk($cacheable_responses, function (CacheableResponseInterface $partial_response) use ($response) {
      $response
        ->addCacheableDependency($partial_response
        ->getCacheableMetadata());
    });
    return $response;
  }

  /**
   * Negotiates the sub Content-Type.
   *
   * Checks if all responses have the same Content-Type header. If they do, then
   * it returns that one. If not, it defaults to 'application/json'.
   *
   * @param \Symfony\Component\HttpFoundation\Response[] $responses
   *   The responses.
   *
   * @return string
   *   The collective content type. 'application/json' if no conciliation is
   *   possible.
   */
  protected function negotiateSubContentType($responses) {
    $output = array_reduce($responses, function ($carry, Response $response) {
      $ct = $response->headers
        ->get('Content-Type');
      if (!isset($carry)) {
        $carry = $ct;
      }
      if ($carry !== $ct) {
        $carry = 'application/json';
      }
      return $carry;
    });
    return $output ?: 'application/json';
  }

  /**
   * Forward the master request's header to the subrequest.
   *
   * @param string $name
   *   The header name to forward.
   * @param \Symfony\Component\HttpFoundation\Request $from
   *   The request to copy headers from.
   * @param \Drupal\subrequests\SubrequestsTree $tree
   *   The target request to copy headers to.
   */
  protected function forwardHeader($name, Request $from, SubrequestsTree $tree) {
    foreach ($tree as $level) {
      foreach ($level as $subrequest) {

        /** @var $subrequest \Drupal\subrequests\Subrequest */
        if (isset($subrequest->headers[$name])) {
          continue;
        }
        $subrequest->headers[$name] = $from->headers
          ->get($name);
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
BlueprintManager::$serializer protected property The deserializer.
BlueprintManager::combineResponses public function
BlueprintManager::forwardHeader protected function Forward the master request's header to the subrequest.
BlueprintManager::negotiateSubContentType protected function Negotiates the sub Content-Type.
BlueprintManager::parse public function Takes the user input and returns a subrequest tree ready for execution.
BlueprintManager::__construct public function