protected function WebTestBase::drupalProcessAjaxResponse in Drupal 8
Processes an AJAX response into current content.
This processes the AJAX response as ajax.js does. It uses the response's JSON data, an array of commands, to update $this->content using equivalent DOM manipulation as is used by ajax.js. It does not apply custom AJAX commands though, because emulation is only implemented for the AJAX commands that ship with Drupal core.
Parameters
string $content: The current HTML content.
array $ajax_response: An array of AJAX commands.
array $ajax_settings: An array of AJAX settings which will be used to process the response.
array $drupal_settings: An array of settings to update the value of drupalSettings for the currently-loaded page.
See also
drupalPostAjaxForm()
ajax.js
1 call to WebTestBase::drupalProcessAjaxResponse()
- WebTestBase::drupalPostAjaxForm in core/
modules/ simpletest/ src/ WebTestBase.php - Executes an Ajax form submission.
File
- core/
modules/ simpletest/ src/ WebTestBase.php, line 1234
Class
- WebTestBase
- Test case for typical Drupal tests.
Namespace
Drupal\simpletestCode
protected function drupalProcessAjaxResponse($content, array $ajax_response, array $ajax_settings, array $drupal_settings) {
// ajax.js applies some defaults to the settings object, so do the same
// for what's used by this function.
$ajax_settings += [
'method' => 'replaceWith',
];
// DOM can load HTML soup. But, HTML soup can throw warnings, suppress
// them.
$dom = new \DOMDocument();
@$dom
->loadHTML($content);
// XPath allows for finding wrapper nodes better than DOM does.
$xpath = new \DOMXPath($dom);
foreach ($ajax_response as $command) {
// Error messages might be not commands.
if (!is_array($command)) {
continue;
}
switch ($command['command']) {
case 'settings':
$drupal_settings = NestedArray::mergeDeepArray([
$drupal_settings,
$command['settings'],
], TRUE);
break;
case 'insert':
$wrapperNode = NULL;
// When a command doesn't specify a selector, use the
// #ajax['wrapper'] which is always an HTML ID.
if (!isset($command['selector'])) {
$wrapperNode = $xpath
->query('//*[@id="' . $ajax_settings['wrapper'] . '"]')
->item(0);
}
elseif (in_array($command['selector'], [
'head',
'body',
])) {
$wrapperNode = $xpath
->query('//' . $command['selector'])
->item(0);
}
if ($wrapperNode) {
// ajax.js adds an enclosing DIV to work around a Safari bug.
$newDom = new \DOMDocument();
// DOM can load HTML soup. But, HTML soup can throw warnings,
// suppress them.
@$newDom
->loadHTML('<div>' . $command['data'] . '</div>');
// Suppress warnings thrown when duplicate HTML IDs are encountered.
// This probably means we are replacing an element with the same ID.
$newNode = @$dom
->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
$method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
// The "method" is a jQuery DOM manipulation function. Emulate
// each one using PHP's DOMNode API.
switch ($method) {
case 'replaceWith':
$wrapperNode->parentNode
->replaceChild($newNode, $wrapperNode);
break;
case 'append':
$wrapperNode
->appendChild($newNode);
break;
case 'prepend':
// If no firstChild, insertBefore() falls back to
// appendChild().
$wrapperNode
->insertBefore($newNode, $wrapperNode->firstChild);
break;
case 'before':
$wrapperNode->parentNode
->insertBefore($newNode, $wrapperNode);
break;
case 'after':
// If no nextSibling, insertBefore() falls back to
// appendChild().
$wrapperNode->parentNode
->insertBefore($newNode, $wrapperNode->nextSibling);
break;
case 'html':
foreach ($wrapperNode->childNodes as $childNode) {
$wrapperNode
->removeChild($childNode);
}
$wrapperNode
->appendChild($newNode);
break;
}
}
break;
// @todo Add suitable implementations for these commands in order to
// have full test coverage of what ajax.js can do.
case 'remove':
break;
case 'changed':
break;
case 'css':
break;
case 'data':
break;
case 'restripe':
break;
case 'add_css':
break;
case 'update_build_id':
$buildId = $xpath
->query('//input[@name="form_build_id" and @value="' . $command['old'] . '"]')
->item(0);
if ($buildId) {
$buildId
->setAttribute('value', $command['new']);
}
break;
}
}
$content = $dom
->saveHTML();
$this
->setRawContent($content);
$this
->setDrupalSettings($drupal_settings);
}