diff options
author | webchick <webchick@24967.no-reply.drupal.org> | 2012-02-28 22:11:46 -0800 |
---|---|---|
committer | webchick <webchick@24967.no-reply.drupal.org> | 2012-02-28 22:11:46 -0800 |
commit | 4ac6433a74df2e4b443fa6a314adb3ad4a152d8b (patch) | |
tree | c5680ef3dd68f49b359937fb42e97061f7d49b42 | |
parent | 0f8e2094a3cf33a8018ee394e56bad57b3d0f89c (diff) | |
download | brdo-4ac6433a74df2e4b443fa6a314adb3ad4a152d8b.tar.gz brdo-4ac6433a74df2e4b443fa6a314adb3ad4a152d8b.tar.bz2 |
Issue #967166 by effulgentsia, Cottser, no_commit_credit, KrisBulman: Fixed Content rendered via AJAX does not respect stylesheets removed in .info files.
-rw-r--r-- | includes/common.inc | 20 | ||||
-rw-r--r-- | modules/simpletest/drupal_web_test_case.php | 90 | ||||
-rw-r--r-- | modules/simpletest/tests/ajax.test | 21 | ||||
-rw-r--r-- | modules/simpletest/tests/ajax_test.module | 8 |
4 files changed, 88 insertions, 51 deletions
diff --git a/includes/common.inc b/includes/common.inc index d799616d4..021e1a47d 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2969,6 +2969,18 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) { // Sort CSS items, so that they appear in the correct order. uasort($css, 'drupal_sort_css_js'); + // Provide the page with information about the individual CSS files used, + // information not otherwise available when CSS aggregation is enabled. The + // setting is attached later in this function, but is set here, so that CSS + // files removed below are still considered "used" and prevented from being + // added in a later AJAX request. + // Skip if no files were added to the page or jQuery.extend() will overwrite + // the Drupal.settings.ajaxPageState.css object with an empty array. + if (!empty($css)) { + // Cast the array to an object to be on the safe side even if not empty. + $setting['ajaxPageState']['css'] = (object) array_fill_keys(array_keys($css), 1); + } + // Remove the overridden CSS files. Later CSS files override former ones. $previous_item = array(); foreach ($css as $key => $item) { @@ -2989,13 +3001,7 @@ function drupal_get_css($css = NULL, $skip_alter = FALSE) { '#items' => $css, ); - // Provide the page with information about the individual CSS files used, - // information not otherwise available when CSS aggregation is enabled. - // Skip if no files were added to the page or jQuery.extend() will overwrite - // the Drupal.settings.ajaxPageState.css object with an empty array. - // Cast the array to an object to be on the safe side even if not empty. - if (!empty($css)) { - $setting['ajaxPageState']['css'] = (object) array_fill_keys(array_keys($css), 1); + if (!empty($setting)) { $styles['#attached']['js'][] = array('type' => 'setting', 'data' => $setting); } diff --git a/modules/simpletest/drupal_web_test_case.php b/modules/simpletest/drupal_web_test_case.php index 9095e22e1..a457a89b3 100644 --- a/modules/simpletest/drupal_web_test_case.php +++ b/modules/simpletest/drupal_web_test_case.php @@ -2049,6 +2049,8 @@ class DrupalWebTestCase extends DrupalTestCase { // them. $dom = new DOMDocument(); @$dom->loadHTML($content); + // XPath allows for finding wrapper nodes better than DOM does. + $xpath = new DOMXPath($dom); foreach ($return as $command) { switch ($command['command']) { case 'settings': @@ -2056,52 +2058,52 @@ class DrupalWebTestCase extends DrupalTestCase { break; case 'insert': - // @todo ajax.js can process commands that include a 'selector', but - // these are hard to emulate with DOMDocument. For now, we only - // implement 'insert' commands that use $ajax_settings['wrapper']. + $wrapperNode = NULL; + // When a command doesn't specify a selector, use the + // #ajax['wrapper'] which is always an HTML ID. if (!isset($command['selector'])) { - // $dom->getElementById() doesn't work when drupalPostAJAX() is - // invoked multiple times for a page, so use XPath instead. This - // also sets us up for adding support for $command['selector'] in - // the future, once we figure out how to transform a jQuery - // selector to XPath. - $xpath = new DOMXPath($dom); $wrapperNode = $xpath->query('//*[@id="' . $ajax_settings['wrapper'] . '"]')->item(0); - if ($wrapperNode) { - // ajax.js adds an enclosing DIV to work around a Safari bug. - $newDom = new DOMDocument(); - $newDom->loadHTML('<div>' . $command['data'] . '</div>'); - $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; - } + } + // @todo Ajax commands can target any jQuery selector, but these are + // hard to fully emulate with XPath. For now, just handle 'head' + // and 'body', since these are used by ajax_render(). + elseif (in_array($command['selector'], array('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(); + $newDom->loadHTML('<div>' . $command['data'] . '</div>'); + $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; diff --git a/modules/simpletest/tests/ajax.test b/modules/simpletest/tests/ajax.test index 8e731b8e7..014a35042 100644 --- a/modules/simpletest/tests/ajax.test +++ b/modules/simpletest/tests/ajax.test @@ -195,6 +195,27 @@ class AJAXFrameworkTestCase extends AJAXTestCase { $this->assertEqual($new_js, $original_js + array($expected['js'] => 1), t('Page state now has the %js file.', array('%js' => $expected['js']))); $this->assertCommand($commands, array('data' => $expected_js_html), t('Page now has the %js file.', array('%js' => $expected['js']))); } + + /** + * Tests that overridden CSS files are not added during lazy load. + */ + function testLazyLoadOverriddenCSS() { + // The test theme overrides system.base.css without an implementation, + // thereby removing it. + theme_enable(array('test_theme')); + variable_set('theme_default', 'test_theme'); + + // This gets the form, and emulates an Ajax submission on it, including + // adding markup to the HEAD and BODY for any lazy loaded JS/CSS files. + $this->drupalPostAJAX('ajax_forms_test_lazy_load_form', array('add_files' => TRUE), array('op' => t('Submit'))); + + // Verify that the resulting HTML does not load the overridden CSS file. + // We add a "?" to the assertion, because Drupal.settings may include + // information about the file; we only really care about whether it appears + // in a LINK or STYLE tag, for which Drupal always adds a query string for + // cache control. + $this->assertNoText('system.base.css?', 'Ajax lazy loading does not add overridden CSS files.'); + } } /** diff --git a/modules/simpletest/tests/ajax_test.module b/modules/simpletest/tests/ajax_test.module index 4148a0839..21be01942 100644 --- a/modules/simpletest/tests/ajax_test.module +++ b/modules/simpletest/tests/ajax_test.module @@ -32,6 +32,14 @@ function ajax_test_menu() { } /** + * Implements hook_system_theme_info(). + */ +function ajax_test_system_theme_info() { + $themes['test_theme'] = drupal_get_path('module', 'ajax_test') . '/themes/test_theme/test_theme.info'; + return $themes; +} + +/** * Menu callback; Return an element suitable for use by ajax_deliver(). * * Additionally ensures that ajax_render() incorporates JavaScript settings |