You are here

class JsResponse in JS Callback Handler 8.3

JsResponse.

Hierarchy

Expanded class hierarchy of JsResponse

2 files declare their use of JsResponse
js.api.php in ./js.api.php
JS Callback Handler APIs.
JsCallbackBase.php in src/Plugin/Js/JsCallbackBase.php

File

src/JsResponse.php, line 14

Namespace

Drupal\js
View source
class JsResponse extends AjaxResponse {
  use DependencySerializationTrait {
    __sleep as __traitSleep;
    __wakeup as __traitWakeup;
  }
  use StringTranslationTrait;

  /**
   * JS Callback service.
   *
   * @var \Drupal\js\Js
   */
  protected $js;

  /**
   * The content mime type.
   *
   * @var string
   */
  protected $mimeType = 'application/json';

  /**
   * {@inheritdoc}
   */
  public function __construct($data = NULL, $status = 200, array $headers = []) {
    parent::__construct($data, $status, $headers);
  }

  /**
   * {@inheritdoc}
   */
  public function __sleep() {
    $keys = $this
      ->__traitSleep();

    // If a response is serialized, that means the content has already been
    // constructed from the data. Because the data may contain objects that
    // aren't serializable (way down in the render array), then it should just
    // be removed entirely to avoid any container serializations.
    return array_diff($keys, [
      'data',
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function __wakeup() {
    $this
      ->__traitWakeup();
    $this->data = Json::decode($this->content);
  }

  /**
   * Retrieves the data set by the callback.
   *
   * @return mixed
   *   The data set by the callback.
   */
  public function getData() {
    return $this->data;
  }

  /**
   * Retrieves the mime type of the response.
   *
   * @return string
   *   The mime type.
   */
  public function getMimeType() {
    return $this->mimeType;
  }

  /**
   * Retrieves a header value by name.
   *
   * @param string $name
   *   The header to retrieve.
   * @param mixed $default
   *   The default value if header is not set.
   * @param bool $first
   *   Flag indicating whether to return only the first value or all values for
   *   the header, TRUE by default.
   *
   * @return string|array
   *   The first header value if $first is true, an array of values otherwise.
   */
  public function getHeader($name, $default = NULL, $first = TRUE) {
    return $this->headers
      ->get($name, $default, $first);
  }

  /**
   * Helper method to determine if an array is renderable.
   *
   * @param array $data
   *   The array to check.
   * @param bool $recursive
   *   If TRUE, the entire array (children) is searched, otherwise only the
   *   first level is checked.
   *
   * @return bool
   *   TRUE if renderable, FALSE if not.
   */
  function isRenderable($data = [], $recursive = TRUE) {

    // Immediately return if not an array.
    if (!is_array($data)) {
      return FALSE;
    }
    static $keys = [
      '#type',
      '#theme',
      '#theme_wrappers',
      '#children',
      '#markup',
      '#pre_render',
      '#post_render',
      '#lazy_builder',
      '#attached',
    ];
    if (array_intersect($keys, Element::properties($data))) {
      return TRUE;
    }
    if ($recursive) {

      // Cannot use \Drupal\Core\Render\Element::children here since that can
      // potentially trigger E_USER_ERROR if the array is invalid. Instead,
      // just filter the array by checking if the key is a "child" key.
      $children = array_filter(array_keys($data), '\\Drupal\\Core\\Render\\Element::child');
      foreach ($children as $child) {
        if (is_array($data[$child]) && $this
          ->isRenderable($data[$child])) {
          return TRUE;
        }
      }
    }
    return FALSE;
  }

  /**
   * Processes the content for output.
   *
   * If content is a render array, it may contain attached assets to be
   * processed.
   *
   * @param array|string $data
   *   The data to be rendered, passed by reference.
   *
   * @return string
   *   HTML rendered content.
   */
  protected function render(&$data = []) {

    // Immediately return if data is not renderable.
    if (!$this
      ->isRenderable($data)) {
      return $data;
    }
    return trim(\Drupal::service('renderer')
      ->renderRoot($data));
  }

  /**
   * {@inheritdoc}
   *
   * @return $this
   */
  public function setContent($content) {
    if (is_array($content) || $content instanceof \ArrayObject) {
      $json = $content;
      if ($this->js) {

        // Set renderable data as "content".
        if (!$this
          ->isRedirection() && $this
          ->isRenderable($content)) {

          //          // GET requests must be cached by query arguments.
          //          if ($this->js->getRequest()->getMethod() === 'GET') {
          //            $content['#cache']['context'][] = 'url.query_args';
          //          }
          $json = [
            'content' => $this
              ->render($content),
          ];
        }

        // Include general Drupal information on non-redirecting requests.
        if (!$this
          ->isRedirection()) {
          $json['title'] = $this->js
            ->getCallback()
            ->call('getTitle');
          $json['messages'] = drupal_get_messages();
        }

        // Add a reliable response parameter.
        $json['response']['code'] = $this
          ->getStatusCode();
        $json['response']['message'] = isset(static::$statusTexts[$json['response']['code']]) ? static::$statusTexts[$json['response']['code']] : $this
          ->t('Unknown');
      }
      $this->headers
        ->remove('Content-Encoding');
      $content = Json::encode($json);
    }
    parent::setContent($content);
    return $this;
  }

  /**
   * Sets the data returned from a callback.
   *
   * @param mixed $data
   *   The data to set.
   *
   * @return $this
   */
  public function setData($data = []) {
    $this->data = $data;
    $this
      ->setContent($this->data);
    return $this;
  }

  /**
   * Sets an header by name, explicitly.
   *
   * @param string $name
   *   The name of the header.
   * @param string|array $value
   *   The value or an array of values to set.
   * @param bool $replace
   *   Flag indicating whether to replace the value or not, TRUE by default.
   *
   * @return $this
   */
  public function setHeader($name, $value, $replace = TRUE) {
    $this->headers
      ->set($name, $value, $replace);
    return $this;
  }

  /**
   * Sets the JS Callback Handler instance.
   *
   * @param \Drupal\js\Js $js
   *
   * @return $this
   */
  public function setJs(Js $js) {
    $this->js = $js;
    return $this;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AjaxResponse::$commands protected property The array of ajax commands.
AjaxResponse::addCommand public function Add an AJAX command to the response.
AjaxResponse::getCommands public function Gets all AJAX commands.
AttachmentsTrait::$attachments protected property The attachments for this response.
AttachmentsTrait::addAttachments public function
AttachmentsTrait::getAttachments public function
AttachmentsTrait::setAttachments public function
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function Aliased as: __traitSleep 1
DependencySerializationTrait::__wakeup public function Aliased as: __traitWakeup 2
JsResponse::$js protected property JS Callback service.
JsResponse::$mimeType protected property The content mime type.
JsResponse::getData public function Retrieves the data set by the callback.
JsResponse::getHeader public function Retrieves a header value by name.
JsResponse::getMimeType public function Retrieves the mime type of the response.
JsResponse::isRenderable function Helper method to determine if an array is renderable.
JsResponse::render protected function Processes the content for output.
JsResponse::setContent public function
JsResponse::setData public function Sets the data returned from a callback.
JsResponse::setHeader public function Sets an header by name, explicitly.
JsResponse::setJs public function Sets the JS Callback Handler instance.
JsResponse::__construct public function Constructor.
JsResponse::__sleep public function
JsResponse::__wakeup public function
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.