Commit e51d9dec authored by catch's avatar catch
Browse files

Issue #2575737 by Cottser, davidhernandez: Copy templates, CSS, and related...

Issue #2575737 by Cottser, davidhernandez: Copy templates, CSS, and related assets to Stable and override core libraries' CSS
parent ccd1f0b2
<?php
/**
* @file
* Contains \Drupal\system\Tests\Theme\StableLibraryOverrideTest.
*/
namespace Drupal\system\Tests\Theme;
use Drupal\simpletest\KernelTestBase;
/**
* Tests Stable's library overrides.
*
* @group Theme
*/
class StableLibraryOverrideTest extends KernelTestBase {
/**
* The theme manager.
*
* @var \Drupal\Core\Theme\ThemeManagerInterface
*/
protected $themeManager;
/**
* The theme initialization.
*
* @var \Drupal\Core\Theme\ThemeInitializationInterface
*/
protected $themeInitialization;
/**
* The library discovery service.
*
* @var \Drupal\Core\Asset\LibraryDiscoveryInterface
*/
protected $libraryDiscovery;
/**
* A list of all core modules.
*
* @var string[]
*/
protected $allModules;
/**
* A list of libraries to skip checking, in the format extension/library_name.
*
* @var string[]
*/
protected $librariesToSkip = [];
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->themeManager = $this->container->get('theme.manager');
$this->themeInitialization = $this->container->get('theme.initialization');
$this->libraryDiscovery = $this->container->get('library.discovery');
$this->container->get('theme_installer')->install(['stable']);
// Enable all core modules.
$all_modules = system_rebuild_module_data();
$all_modules = array_filter($all_modules, function ($module) {
// Filter contrib, hidden, already enabled modules and modules in the
// Testing package.
if ($module->origin !== 'core' || !empty($module->info['hidden']) || $module->status == TRUE || $module->info['package'] == 'Testing') {
return FALSE;
}
return TRUE;
});
$this->allModules = array_keys($all_modules);
sort($this->allModules);
$this->enableModules($this->allModules);
}
/**
* Ensures that Stable overrides all relevant core library assets.
*/
public function testStableLibraryOverrides() {
// First get the clean library definitions with no active theme.
$libraries_before = $this->getAllLibraries();
$libraries_before = $this->removeVendorAssets($libraries_before);
$this->themeManager->setActiveTheme($this->themeInitialization->getActiveThemeByName('stable'));
$this->libraryDiscovery->clearCachedDefinitions();
// Now get the library definitions with Stable as the active theme.
$libraries_after = $this->getAllLibraries();
$libraries_after = $this->removeVendorAssets($libraries_after);
$root = \Drupal::root();
foreach ($libraries_before as $extension => $libraries) {
foreach ($libraries as $library_name => $library) {
// Allow skipping libraries.
if (in_array("$extension/$library_name", $this->librariesToSkip)) {
continue;
}
$library_after = $libraries_after[$extension][$library_name];
// Check that all the CSS assets are overridden.
foreach ($library['css'] as $index => $asset) {
$clean_path = $asset['data'];
$stable_path = $library_after['css'][$index]['data'];
// Make core/misc assets look like they are coming from a "core"
// module.
$replacements = [
'core/misc/' => "core/modules/core/css/",
];
$expected_path = strtr($clean_path, $replacements);
// Adjust the module asset paths to correspond with the Stable folder
// structure.
$expected_path = str_replace("core/modules/$extension/css/", "core/themes/stable/css/$extension/", $expected_path);
$assert_path = str_replace("core/modules/$extension/", '', $clean_path);
$this->assertEqual($expected_path, $stable_path, "$assert_path from the $extension/$library_name library is overridden in Stable.");
}
}
}
}
/**
* Removes all vendor libraries and assets from the library definitions.
*
* @param array[] $all_libraries
* An associative array of libraries keyed by extension, then by library
* name, and so on.
*
* @return array[]
* The reduced array of libraries.
*/
protected function removeVendorAssets($all_libraries) {
foreach ($all_libraries as $extension => $libraries) {
foreach ($libraries as $library_name => $library) {
if (isset($library['remote'])) {
unset($all_libraries[$extension][$library_name]);
}
foreach (['css', 'js'] as $asset_type) {
foreach ($library[$asset_type] as $index => $asset) {
if (strpos($asset['data'], 'core/assets/vendor') !== FALSE) {
unset($all_libraries[$extension][$library_name][$asset_type][$index]);
// Re-key the array of assets. This is needed because
// libraries-override doesn't always preserve the order.
if (!empty($all_libraries[$extension][$library_name][$asset_type])) {
$all_libraries[$extension][$library_name][$asset_type] = array_values($all_libraries[$extension][$library_name][$asset_type]);
}
}
}
}
}
}
return $all_libraries;
}
/**
* Gets all libraries for core and all installed modules.
*
* @return array[]
* An associative array of libraries keyed by extension, then by library
* name, and so on.
*/
protected function getAllLibraries() {
$modules = \Drupal::moduleHandler()->getModuleList();
$module_list = array_keys($modules);
sort($module_list);
$this->assertEqual($this->allModules, $module_list, 'All core modules are installed.');
$libraries['core'] = $this->libraryDiscovery->getLibrariesByExtension('core');
$root = \Drupal::root();
foreach ($modules as $module_name => $module) {
$library_file = $module->getPath() . '/' . $module_name . '.libraries.yml';
if (is_file($root . '/' . $library_file)) {
$libraries[$module_name] = $this->libraryDiscovery->getLibrariesByExtension($module_name);
}
}
return $libraries;
}
}
{% extends "@block/block.html.twig" %}
{% extends "block.html.twig" %}
{#
/**
* @file
......
......@@ -44,12 +44,12 @@ libraries-override:
core/drupal.dropbutton:
css:
component:
misc/dropbutton/dropbutton.css: /themes/my_theme/css/dropbutton.css
/core/themes/stable/css/core/dropbutton/dropbutton.css: /themes/my_theme/css/dropbutton.css
# Use stream wrappers.
core/drupal.vertical-tabs:
css:
component:
misc/vertical-tabs.css: public://my_css/vertical-tabs.css
/core/themes/stable/css/core/vertical-tabs.css: public://my_css/vertical-tabs.css
# Use a protocol-relative URI.
core/jquery.ui:
css:
......
......@@ -53,7 +53,7 @@ public function testGrid() {
// Ensure styles are properly added for grid views.
$this->drupalGet('test-grid');
$this->assertRaw('views/css/views.module.css');
$this->assertRaw('stable/css/views/views.module.css');
}
/**
......
<?php
/**
* @file
* Contains \Drupal\KernelTests\Core\Theme\StableTemplateOverrideTest.
*/
namespace Drupal\KernelTests\Core\Theme;
use Drupal\Core\Theme\Registry;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests Stable's template overrides.
*
* @group Theme
*/
class StableTemplateOverrideTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['system', 'user'];
/**
* An array of template names to skip, without the extension.
*
* @var string[]
*/
protected $templatesToSkip = [
'views-form-views-form',
];
/**
* The theme handler.
*
* @var \Drupal\Core\Extension\ThemeHandlerInterface
*/
protected $themeHandler;
/**
* A list of all core modules.
*
* @var string[]
*/
protected $allModules;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->themeHandler = $this->container->get('theme_handler');
$this->container->get('theme_installer')->install(['stable']);
$this->installSchema('system', 'router');
$this->installAllModules();
}
/**
* Installs all core modules.
*/
protected function installAllModules() {
// Needed for system_rebuild_module_data().
include_once $this->root . '/core/modules/system/system.module';
// Enable all core modules.
$all_modules = system_rebuild_module_data();
$all_modules = array_filter($all_modules, function ($module) {
// Filter contrib, hidden, already enabled modules and modules in the
// Testing package.
if ($module->origin !== 'core' || !empty($module->info['hidden']) || $module->status == TRUE || $module->info['package'] == 'Testing') {
return FALSE;
}
return TRUE;
});
$this->allModules = array_keys($all_modules);
sort($this->allModules);
$module_installer = $this->container->get('module_installer');
$module_installer->install($this->allModules);
$this->installConfig(['system', 'user']);
}
/**
* Ensures that Stable overrides all relevant core templates.
*/
public function testStableTemplateOverrides() {
$registry = new Registry(\Drupal::root(), \Drupal::cache(), \Drupal::lock(), \Drupal::moduleHandler(), $this->themeHandler, \Drupal::service('theme.initialization'), 'stable');
$registry->setThemeManager(\Drupal::theme());
$registry_full = $registry->get();
foreach ($registry_full as $hook => $info) {
if (isset($info['template'])) {
// Allow skipping templates.
if (in_array($info['template'], $this->templatesToSkip)) {
continue;
}
$this->assertEquals('core/themes/stable', $info['theme path'], $info['template'] . '.html.twig overridden in Stable.');
}
}
}
}
/* Block listing page */
.region-title__action {
display: inline-block;
margin-left: 1em; /* LTR */
}
[dir="rtl"] .region-title__action {
margin-left: 0;
margin-right: 1em;
}
/* Block demo mode */
.block-region {
background-color: #ff6;
margin-top: 4px;
margin-bottom: 4px;
padding: 3px;
}
a.block-demo-backlink,
a.block-demo-backlink:link,
a.block-demo-backlink:visited {
background-color: #b4d7f0;
border-radius: 0 0 10px 10px;
color: #000;
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: small;
line-height: 20px;
left: 20px; /*LTR*/
padding: 5px 10px;
position: fixed;
z-index: 499;
}
a.block-demo-backlink:hover {
text-decoration: underline;
}
/* Configure block form - Block description */
.block-form .form-item-settings-admin-label label {
display: inline;
}
.block-form .form-item-settings-admin-label label:after {
content: ':';
}
/**
* CSS added to iframe-based instances only.
*/
body {
font-family: Arial, Verdana, sans-serif;
font-size: 15px;
color: #222;
background-color: #fff;
margin: 8px;
}
@media screen and (max-width: 600px) {
/* A font-size of 16px prevents iOS from zooming. */
body {
font-size: 16px;
}
}
ol, ul, dl {
/* Preserved spaces for list items with text direction other than the list.
* (CKEditor issues #6249,#8049) */
padding: 0 40px;
}
/**
* @file
* Styles for configuration of CKEditor module.
*
* Many of these styles are adapted directly from the default CKEditor theme
* "moono".
*/
.ckeditor-toolbar {
border: 1px solid #b6b6b6;
padding: 0.1667em 0.1667em 0.08em;
box-shadow: 0 1px 0 white inset;
background: #cfd1cf;
background-image: -webkit-linear-gradient(top, whiteSmoke, #cfd1cf);
background-image: linear-gradient(top, whiteSmoke, #cfd1cf);
margin: 5px 0;
/* Disallow any user selections in the drag-and-drop toolbar config UI. */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ckeditor-toolbar-active {
margin-top: 0.25em;
}
.ckeditor-toolbar-disabled {
margin-bottom: 0.5em;
}
.ckeditor-toolbar ul,
.ckeditor-toolbar-disabled ul {
list-style: none;
margin: 0;
padding: 0;
}
/* This is required to win over specificity of [dir="rtl"] ul */
[dir="rtl"] .ckeditor-toolbar ul,
[dir="rtl"] .ckeditor-toolbar-disabled ul {
margin-right: 0;
}
.ckeditor-row {
padding: 2px 0 3px;
border-radius: 3px;
}
.ckeditor-group-names-are-visible .ckeditor-row {
border: 1px solid whitesmoke;
}
.ckeditor-row + .ckeditor-row {
margin-top: 0.25em;
}
.ckeditor-toolbar-group,
.ckeditor-toolbar-group-placeholder,
.ckeditor-add-new-group {
float: left; /* LTR */
}
[dir="rtl"] .ckeditor-toolbar-group,
[dir="rtl"] .ckeditor-toolbar-group-placeholder,
[dir="rtl"] .ckeditor-add-new-group {
float: right;
}
.ckeditor-toolbar-groups {
min-height: 2em;
}
.ckeditor-toolbar-group {
margin: 0 0.3333em;
cursor: move;
}
.ckeditor-group-names-are-visible .ckeditor-toolbar-group,
.ckeditor-add-new-group {
border: 1px dotted #a6a6a6;
border-radius: 3px;
padding: 0.2em 0.4em;
}
.ckeditor-toolbar-group.placeholder,
.ckeditor-toolbar-group.placeholder .ckeditor-toolbar-group-name {
cursor: not-allowed;
}
.ckeditor-toolbar-group.placeholder .ckeditor-toolbar-group-name {
font-style: italic;
}
.ckeditor-toolbar-group-name {
display: none;
font-size: 1em;
font-weight: normal;
margin: 0.25em 0;
}
.ckeditor-group-names-are-visible .ckeditor-toolbar-group-name {
display: block;
cursor: pointer;
}
.ckeditor-toolbar-active .placeholder,
.ckeditor-toolbar-active .ckeditor-add-new-group {
display: none;
}
.ckeditor-group-names-are-visible .placeholder,
.ckeditor-group-names-are-visible .ckeditor-add-new-group {
display: block;
}
.ckeditor-toolbar-group-buttons {
float: left; /* LTR */
}
[dir="rtl"] .ckeditor-toolbar-group-buttons {
float: right;
}
.ckeditor-groupnames-toggle {
cursor: pointer;
float: right; /* LTR */
}
[dir="rtl"] .ckeditor-groupnames-toggle {
float: left;
}
.ckeditor-toolbar .ckeditor-toolbar-group > li {
border: 1px solid white;
border-radius: 5px;
background-image: -webkit-linear-gradient(transparent 60%, rgba(0, 0, 0, 0.1));
background-image: linear-gradient(transparent 60%, rgba(0, 0, 0, 0.1));
margin: 3px 6px;
padding: 3px;
}
.ckeditor-toolbar-configuration .fieldset-description{
margin-bottom: 1em;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-available,
.ckeditor-toolbar-disabled .ckeditor-toolbar-dividers {
box-sizing: border-box;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-available {
float: left; /* LTR */
width: 80%;
}
[dir="rtl"] .ckeditor-toolbar-disabled .ckeditor-toolbar-available {
float: right;
}
.ckeditor-toolbar-disabled .ckeditor-toolbar-dividers {
float: right; /* LTR */
width: 20%;
}
[dir="rtl"] .ckeditor-toolbar-disabled .ckeditor-toolbar-dividers {
float: left;
}
.ckeditor-toolbar-disabled .ckeditor-buttons li a,
.ckeditor-toolbar .ckeditor-buttons,
.ckeditor-add-new-group button {
border: 1px solid #a6a6a6;
border-bottom-color: #979797;
border-radius: 3px;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5), 0 0 2px rgba(255, 255, 255, 0.15) inset, 0 1px 0 rgba(255, 255, 255, 0.15) inset;
}
.ckeditor-toolbar-disabled .ckeditor-buttons {
border: 0;
}
.ckeditor-toolbar-disabled .ckeditor-buttons li {
margin: 2px;
}
.ckeditor-buttons {
min-height: 26px;
min-width: 26px;
}
.ckeditor-buttons li {
padding: 0;
margin: 0;
float: left; /* LTR */
}
[dir="rtl"] .ckeditor-buttons li {
float: right;
}
.ckeditor-buttons li a,
.ckeditor-add-new-group button {
background: #e4e4e4;
background-image: -webkit-linear-gradient(top, white, #e4e4e4);
background-image: linear-gradient(top, white, #e4e4e4);
color: #474747;
}
.ckeditor-buttons li a {
border: 0;
cursor: move;
display: block;
min-height: 18px;
line-height: 1.4;
padding: 4px 6px;
position: relative;
text-decoration: none;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
white-space: nowrap;
}
.ckeditor-toolbar-dividers {
float: right; /* LTR */
}
[dir="rtl"] .ckeditor-toolbar-dividers {
float: left;
}
.ckeditor-buttons li .cke-icon-only {
text-indent: -9999px;
width: 16px;
/* Firefox includes the offscreen text in the focus indicator, resulting in a
far too wide focus indicator. This fixes that. */
overflow: hidden;
}
.ckeditor-buttons li .cke_ltr {