AjaxResponse.php

Definition of Drupal\Core\Ajax\AjaxResponse.

Namespace

Drupal\Core\Ajax

File

drupal/core/lib/Drupal/Core/Ajax/AjaxResponse.php
View source
  1. <?php
  2. /**
  3. * @file
  4. * Definition of Drupal\Core\Ajax\AjaxResponse.
  5. */
  6. namespace Drupal\Core\Ajax;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpFoundation\Request;
  9. /**
  10. * JSON response object for AJAX requests.
  11. */
  12. class AjaxResponse extends JsonResponse {
  13. /**
  14. * The array of ajax commands.
  15. *
  16. * @var array
  17. */
  18. protected $commands = array();
  19. /**
  20. * Add an AJAX command to the response.
  21. *
  22. * @param object $command
  23. * An AJAX command object implementing CommandInterface.
  24. * @param boolean $prepend
  25. * A boolean which determines whether the new command should be executed
  26. * before previously added commands. Defaults to FALSE.
  27. *
  28. * @return AjaxResponse
  29. * The current AjaxResponse.
  30. */
  31. public function addCommand($command, $prepend = FALSE) {
  32. if ($prepend) {
  33. array_unshift($this->commands, $command->render());
  34. }
  35. else {
  36. $this->commands[] = $command->render();
  37. }
  38. return $this;
  39. }
  40. /**
  41. * Sets the response's data to be the array of AJAX commands.
  42. *
  43. * @param Request $request
  44. * A request object.
  45. *
  46. * @return Response
  47. * The current response.
  48. */
  49. public function prepare(Request $request) {
  50. $this->setData($this->ajaxRender($request));
  51. return parent::prepare($request);
  52. }
  53. /**
  54. * Prepares the AJAX commands for sending back to the client.
  55. *
  56. * @param Request $request
  57. * The request object that the AJAX is responding to.
  58. *
  59. * @return array
  60. * An array of commands ready to be returned as JSON.
  61. */
  62. protected function ajaxRender(Request $request) {
  63. // Ajax responses aren't rendered with html.tpl.php, so we have to call
  64. // drupal_get_css() and drupal_get_js() here, in order to have new files
  65. // added during this request to be loaded by the page. We only want to send
  66. // back files that the page hasn't already loaded, so we implement simple
  67. // diffing logic using array_diff_key().
  68. $ajax_page_state = $request->request->get('ajax_page_state');
  69. foreach (array('css', 'js') as $type) {
  70. // It is highly suspicious if $_POST['ajax_page_state'][$type] is empty,
  71. // since the base page ought to have at least one JS file and one CSS file
  72. // loaded. It probably indicates an error, and rather than making the page
  73. // reload all of the files, instead we return no new files.
  74. if (empty($ajax_page_state[$type])) {
  75. $items[$type] = array();
  76. }
  77. else {
  78. $function = 'drupal_add_' . $type;
  79. $items[$type] = $function();
  80. drupal_alter($type, $items[$type]);
  81. // @todo Inline CSS and JS items are indexed numerically. These can't be
  82. // reliably diffed with array_diff_key(), since the number can change
  83. // due to factors unrelated to the inline content, so for now, we
  84. // strip the inline items from Ajax responses, and can add support for
  85. // them when drupal_add_css() and drupal_add_js() are changed to use
  86. // a hash of the inline content as the array key.
  87. foreach ($items[$type] as $key => $item) {
  88. if (is_numeric($key)) {
  89. unset($items[$type][$key]);
  90. }
  91. }
  92. // Ensure that the page doesn't reload what it already has.
  93. $items[$type] = array_diff_key($items[$type], $ajax_page_state[$type]);
  94. }
  95. }
  96. // Render the HTML to load these files, and add AJAX commands to insert this
  97. // HTML in the page. We pass TRUE as the $skip_alter argument to prevent the
  98. // data from being altered again, as we already altered it above. Settings
  99. // are handled separately, afterwards.
  100. if (isset($items['js']['settings'])) {
  101. unset($items['js']['settings']);
  102. }
  103. $styles = drupal_get_css($items['css'], TRUE);
  104. $scripts_footer = drupal_get_js('footer', $items['js'], TRUE);
  105. $scripts_header = drupal_get_js('header', $items['js'], TRUE);
  106. // Prepend commands to add the resources, preserving their relative order.
  107. $resource_commands = array();
  108. if (!empty($styles)) {
  109. $resource_commands[] = new AddCssCommand($styles);
  110. }
  111. if (!empty($scripts_header)) {
  112. $resource_commands[] = new PrependCommand('head', $scripts_header);
  113. }
  114. if (!empty($scripts_footer)) {
  115. $resource_commands[] = new AppendCommand('body', $scripts_footer);
  116. }
  117. foreach (array_reverse($resource_commands) as $resource_command) {
  118. $this->addCommand($resource_command, TRUE);
  119. }
  120. // Prepend a command to merge changes and additions to Drupal.settings.
  121. $scripts = drupal_add_js();
  122. if (!empty($scripts['settings'])) {
  123. $settings = drupal_merge_js_settings($scripts['settings']['data']);
  124. $this->addCommand(new SettingsCommand($settings, TRUE), TRUE);
  125. }
  126. $commands = $this->commands;
  127. drupal_alter('ajax_render', $commands);
  128. return $commands;
  129. }
  130. }

Classes

Namesort descending Description
AjaxResponse JSON response object for AJAX requests.