Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\block;
|
||||
|
||||
use Drupal\Component\Plugin\Exception\ContextException;
|
||||
use Drupal\Component\Plugin\Exception\MissingValueContextException;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
|
@ -61,13 +62,12 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
|
|||
* @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
|
||||
* The lazy context repository service.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository ) {
|
||||
public function __construct(EntityTypeInterface $entity_type, ContextHandlerInterface $context_handler, ContextRepositoryInterface $context_repository) {
|
||||
parent::__construct($entity_type);
|
||||
$this->contextHandler = $context_handler;
|
||||
$this->contextRepository = $context_repository;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -84,12 +84,16 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
|
|||
else {
|
||||
$conditions = [];
|
||||
$missing_context = FALSE;
|
||||
$missing_value = FALSE;
|
||||
foreach ($entity->getVisibilityConditions() as $condition_id => $condition) {
|
||||
if ($condition instanceof ContextAwarePluginInterface) {
|
||||
try {
|
||||
$contexts = $this->contextRepository->getRuntimeContexts(array_values($condition->getContextMapping()));
|
||||
$this->contextHandler->applyContextMapping($condition, $contexts);
|
||||
}
|
||||
catch (MissingValueContextException $e) {
|
||||
$missing_value = TRUE;
|
||||
}
|
||||
catch (ContextException $e) {
|
||||
$missing_context = TRUE;
|
||||
}
|
||||
|
@ -100,14 +104,15 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
|
|||
if ($missing_context) {
|
||||
// If any context is missing then we might be missing cacheable
|
||||
// metadata, and don't know based on what conditions the block is
|
||||
// accessible or not. For example, blocks that have a node type
|
||||
// condition will have a missing context on any non-node route like the
|
||||
// frontpage.
|
||||
// @todo Avoid setting max-age 0 for some or all cases, for example by
|
||||
// treating available contexts without value differently in
|
||||
// https://www.drupal.org/node/2521956.
|
||||
// accessible or not. Make sure the result cannot be cached.
|
||||
$access = AccessResult::forbidden()->setCacheMaxAge(0);
|
||||
}
|
||||
elseif ($missing_value) {
|
||||
// The contexts exist but have no value. Deny access without
|
||||
// disabling caching. For example the node type condition will have a
|
||||
// missing context on any non-node route like the frontpage.
|
||||
$access = AccessResult::forbidden();
|
||||
}
|
||||
elseif ($this->resolveConditions($conditions, 'and') !== FALSE) {
|
||||
// Delegate to the plugin.
|
||||
$block_plugin = $entity->getPlugin();
|
||||
|
@ -118,12 +123,15 @@ class BlockAccessControlHandler extends EntityAccessControlHandler implements En
|
|||
}
|
||||
$access = $block_plugin->access($account, TRUE);
|
||||
}
|
||||
catch (MissingValueContextException $e) {
|
||||
// The contexts exist but have no value. Deny access without
|
||||
// disabling caching.
|
||||
$access = AccessResult::forbidden();
|
||||
}
|
||||
catch (ContextException $e) {
|
||||
// Setting access to forbidden if any context is missing for the same
|
||||
// reasons as with conditions (described in the comment above).
|
||||
// @todo Avoid setting max-age 0 for some or all cases, for example by
|
||||
// treating available contexts without value differently in
|
||||
// https://www.drupal.org/node/2521956.
|
||||
// If any context is missing then we might be missing cacheable
|
||||
// metadata, and don't know based on what conditions the block is
|
||||
// accessible or not. Make sure the result cannot be cached.
|
||||
$access = AccessResult::forbidden()->setCacheMaxAge(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Provides form for block instance forms.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockForm extends EntityForm {
|
||||
|
||||
|
@ -237,7 +239,8 @@ class BlockForm extends EntityForm {
|
|||
// @todo Allow list of conditions to be configured in
|
||||
// https://www.drupal.org/node/2284687.
|
||||
$visibility = $this->entity->getVisibility();
|
||||
foreach ($this->manager->getDefinitionsForContexts($form_state->getTemporaryValue('gathered_contexts')) as $condition_id => $definition) {
|
||||
$definitions = $this->manager->getFilteredDefinitions('block_ui', $form_state->getTemporaryValue('gathered_contexts'), ['block' => $this->entity]);
|
||||
foreach ($definitions as $condition_id => $definition) {
|
||||
// Don't display the current theme condition.
|
||||
if ($condition_id == 'current_theme') {
|
||||
continue;
|
||||
|
@ -357,7 +360,7 @@ class BlockForm extends EntityForm {
|
|||
// Save the settings of the plugin.
|
||||
$entity->save();
|
||||
|
||||
drupal_set_message($this->t('The block configuration has been saved.'));
|
||||
$this->messenger()->addStatus($this->t('The block configuration has been saved.'));
|
||||
$form_state->setRedirect(
|
||||
'block.admin_display_theme',
|
||||
[
|
||||
|
|
|
@ -15,6 +15,8 @@ interface BlockInterface extends ConfigEntityInterface {
|
|||
*
|
||||
* @deprecated in Drupal 8.3.x, will be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Core\Block\BlockPluginInterface::BLOCK_LABEL_VISIBLE.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2829775
|
||||
*/
|
||||
const BLOCK_LABEL_VISIBLE = BlockPluginInterface::BLOCK_LABEL_VISIBLE;
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Form\FormBuilderInterface;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Theme\ThemeManagerInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -56,6 +57,13 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
*/
|
||||
protected $limit = FALSE;
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* Constructs a new BlockListBuilder object.
|
||||
*
|
||||
|
@ -68,11 +76,12 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder
|
||||
* The form builder.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder) {
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder, MessengerInterface $messenger) {
|
||||
parent::__construct($entity_type, $storage);
|
||||
|
||||
$this->themeManager = $theme_manager;
|
||||
$this->formBuilder = $form_builder;
|
||||
$this->messenger = $messenger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +92,8 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
$entity_type,
|
||||
$container->get('entity.manager')->getStorage($entity_type->id()),
|
||||
$container->get('theme.manager'),
|
||||
$container->get('form_builder')
|
||||
$container->get('form_builder'),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -212,7 +222,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
'#theme_wrappers' => [
|
||||
'container' => [
|
||||
'#attributes' => ['class' => 'region-title__action'],
|
||||
]
|
||||
],
|
||||
],
|
||||
'#prefix' => $title,
|
||||
'#type' => 'link',
|
||||
|
@ -367,7 +377,7 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface
|
|||
$entity->setRegion($entity_values['region']);
|
||||
$entity->save();
|
||||
}
|
||||
drupal_set_message(t('The block settings have been updated.'));
|
||||
$this->messenger->addStatus($this->t('The block settings have been updated.'));
|
||||
|
||||
// Remove any previously set block placement.
|
||||
$this->request->query->remove('block-placement');
|
||||
|
|
|
@ -53,7 +53,7 @@ class BlockController extends ControllerBase {
|
|||
*/
|
||||
public function performOperation(BlockInterface $block, $op) {
|
||||
$block->$op()->save();
|
||||
drupal_set_message($this->t('The block settings have been updated.'));
|
||||
$this->messenger()->addStatus($this->t('The block settings have been updated.'));
|
||||
return $this->redirect('block.admin_display');
|
||||
}
|
||||
|
||||
|
|
|
@ -101,13 +101,21 @@ class BlockLibraryController extends ControllerBase {
|
|||
['data' => $this->t('Operations')],
|
||||
];
|
||||
|
||||
// Only add blocks which work without any available context.
|
||||
$definitions = $this->blockManager->getDefinitionsForContexts($this->contextRepository->getAvailableContexts());
|
||||
// Order by category, and then by admin label.
|
||||
$definitions = $this->blockManager->getSortedDefinitions($definitions);
|
||||
|
||||
$region = $request->query->get('region');
|
||||
$weight = $request->query->get('weight');
|
||||
|
||||
// Only add blocks which work without any available context.
|
||||
$definitions = $this->blockManager->getFilteredDefinitions('block_ui', $this->contextRepository->getAvailableContexts(), [
|
||||
'theme' => $theme,
|
||||
'region' => $region,
|
||||
]);
|
||||
// Order by category, and then by admin label.
|
||||
$definitions = $this->blockManager->getSortedDefinitions($definitions);
|
||||
// Filter out definitions that are not intended to be placed by the UI.
|
||||
$definitions = array_filter($definitions, function (array $definition) {
|
||||
return empty($definition['_block_ui_hidden']);
|
||||
});
|
||||
|
||||
$rows = [];
|
||||
foreach ($definitions as $plugin_id => $plugin_definition) {
|
||||
$row = [];
|
||||
|
|
|
@ -48,7 +48,8 @@ class BlockListController extends EntityListController {
|
|||
* The current request.
|
||||
*
|
||||
* @return array
|
||||
* A render array as expected by drupal_render().
|
||||
* A render array as expected by
|
||||
* \Drupal\Core\Render\RendererInterface::render().
|
||||
*/
|
||||
public function listing($theme = NULL, Request $request = NULL) {
|
||||
$theme = $theme ?: $this->config('system.theme')->get('default');
|
||||
|
|
|
@ -17,6 +17,13 @@ use Drupal\Core\Entity\EntityStorageInterface;
|
|||
* @ConfigEntityType(
|
||||
* id = "block",
|
||||
* label = @Translation("Block"),
|
||||
* label_collection = @Translation("Blocks"),
|
||||
* label_singular = @Translation("block"),
|
||||
* label_plural = @Translation("blocks"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count block",
|
||||
* plural = "@count blocks",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\block\BlockAccessControlHandler",
|
||||
* "view_builder" = "Drupal\block\BlockViewBuilder",
|
||||
|
|
|
@ -7,6 +7,8 @@ use Drupal\Core\Url;
|
|||
|
||||
/**
|
||||
* Provides a deletion confirmation form for the block instance deletion form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockDeleteForm extends EntityDeleteForm {
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ class BlockVisibility extends ProcessPluginBase implements ContainerFactoryPlugi
|
|||
// anything else -- the block will simply have no PHP or request_path
|
||||
// visibility configuration.
|
||||
elseif ($this->skipPHP) {
|
||||
throw new MigrateSkipRowException();
|
||||
throw new MigrateSkipRowException(sprintf("The block with bid '%d' from module '%s' will have no PHP or request_path visibility configuration.", $row->getSourceProperty('bid'), $row->getSourceProperty('module'), $destination_property));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -10,7 +10,7 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
|||
*
|
||||
* @MigrateSource(
|
||||
* id = "block",
|
||||
* source_provider = "block"
|
||||
* source_module = "block"
|
||||
* )
|
||||
*/
|
||||
class Block extends DrupalSqlBase {
|
||||
|
@ -84,7 +84,7 @@ class Block extends DrupalSqlBase {
|
|||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'module' => $this->t('The module providing the block.'),
|
||||
'delta' => $this->t('The block\'s delta.'),
|
||||
'delta' => $this->t("The block's delta."),
|
||||
'theme' => $this->t('Which theme the block is placed in.'),
|
||||
'status' => $this->t('Whether or not the block is enabled.'),
|
||||
'weight' => $this->t('Weight of the block for ordering within regions.'),
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\block\Plugin\migrate\source\Block;
|
||||
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Gets i18n block data from source database.
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_block_translation",
|
||||
* source_module = "i18nblocks"
|
||||
* )
|
||||
*/
|
||||
class BlockTranslation extends Block {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
// Let the parent set the block table to use, but do not use the parent
|
||||
// query. Instead build a query so can use an inner join to the selected
|
||||
// block table.
|
||||
parent::query();
|
||||
$query = $this->select('i18n_blocks', 'i18n')
|
||||
->fields('i18n')
|
||||
->fields('b', ['bid', 'module', 'delta', 'theme', 'title']);
|
||||
$query->innerJoin($this->blockTable, 'b', ('b.module = i18n.module AND b.delta = i18n.delta'));
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'bid' => $this->t('The block numeric identifier.'),
|
||||
'ibid' => $this->t('The i18n_blocks block numeric identifier.'),
|
||||
'module' => $this->t('The module providing the block.'),
|
||||
'delta' => $this->t("The block's delta."),
|
||||
'type' => $this->t('Block type'),
|
||||
'language' => $this->t('Language for this field.'),
|
||||
'theme' => $this->t('Which theme the block is placed in.'),
|
||||
'default_theme' => $this->t('The default theme.'),
|
||||
'title' => $this->t('Block title.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$row->setSourceProperty('default_theme', $this->defaultTheme);
|
||||
return SourcePluginBase::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids = parent::getIds();
|
||||
$ids['module']['alias'] = 'b';
|
||||
$ids['delta']['alias'] = 'b';
|
||||
$ids['theme']['alias'] = 'b';
|
||||
$ids['language']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the block system with admin themes.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockAdminThemeTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'contextual'];
|
||||
|
||||
/**
|
||||
* Check for the accessibility of the admin theme on the block admin page.
|
||||
*/
|
||||
public function testAdminTheme() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer themes']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Ensure that access to block admin page is denied when theme is not
|
||||
// installed.
|
||||
$this->drupalGet('admin/structure/block/list/bartik');
|
||||
$this->assertResponse(403);
|
||||
|
||||
// Install admin theme and confirm that tab is accessible.
|
||||
\Drupal::service('theme_handler')->install(['bartik']);
|
||||
$edit['admin_theme'] = 'bartik';
|
||||
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
||||
$this->drupalGet('admin/structure/block/list/bartik');
|
||||
$this->assertResponse(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure contextual links are disabled in Seven theme.
|
||||
*/
|
||||
public function testSevenAdminTheme() {
|
||||
// Create administrative user.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access administration pages',
|
||||
'administer themes',
|
||||
'access contextual links',
|
||||
'view the administration theme',
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Install admin theme and confirm that tab is accessible.
|
||||
\Drupal::service('theme_handler')->install(['seven']);
|
||||
$edit['admin_theme'] = 'seven';
|
||||
$this->drupalPostForm('admin/appearance', $edit, t('Save configuration'));
|
||||
|
||||
// Define our block settings.
|
||||
$settings = [
|
||||
'theme' => 'seven',
|
||||
'region' => 'header',
|
||||
];
|
||||
|
||||
// Place a block.
|
||||
$block = $this->drupalPlaceBlock('local_tasks_block', $settings);
|
||||
|
||||
// Open admin page.
|
||||
$this->drupalGet('admin');
|
||||
|
||||
// Check if contextual link classes are unavailable.
|
||||
$this->assertNoRaw('<div data-contextual-id="block:block=' . $block->id() . ':langcode=en"></div>');
|
||||
$this->assertNoRaw('contextual-region');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
|
||||
/**
|
||||
* Tests form in block caching.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockFormInBlockTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_test', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Enable our test block.
|
||||
$this->drupalPlaceBlock('test_form_in_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if form in block's redirect isn't cached.
|
||||
*/
|
||||
public function testCachePerPage() {
|
||||
$form_values = ['email' => 'test@example.com'];
|
||||
|
||||
// Go to "test-page" and test if the block is enabled.
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your .com email address.', 'form found');
|
||||
|
||||
// Make sure that we're currently still on /test-page after submitting the
|
||||
// form.
|
||||
$this->drupalPostForm(NULL, $form_values, t('Submit'));
|
||||
$this->assertUrl('test-page');
|
||||
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
|
||||
|
||||
// Go to a different page and see if the block is enabled there as well.
|
||||
$this->drupalGet('test-render-title');
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your .com email address.', 'form found');
|
||||
|
||||
// Make sure that submitting the form didn't redirect us to the first page
|
||||
// we submitted the form from after submitting the form from
|
||||
// /test-render-title.
|
||||
$this->drupalPostForm(NULL, $form_values, t('Submit'));
|
||||
$this->assertUrl('test-render-title');
|
||||
$this->assertText(t('Your email address is @email', ['@email' => 'test@example.com']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the actual placeholders
|
||||
*/
|
||||
public function testPlaceholders() {
|
||||
$this->drupalGet('test-multiple-forms');
|
||||
|
||||
$placeholder = 'form_action_' . Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
|
||||
$this->assertText('Form action: ' . $placeholder, 'placeholder found.');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests block module's installation.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockInstallTest extends WebTestBase {
|
||||
|
||||
public function testCacheTagInvalidationUponInstallation() {
|
||||
// Warm the page cache.
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText('Powered by Drupal');
|
||||
$this->assertNoCacheTag('config:block_list');
|
||||
|
||||
// Install the block module, and place the "Powered by Drupal" block.
|
||||
$this->container->get('module_installer')->install(['block', 'shortcut']);
|
||||
$this->rebuildContainer();
|
||||
$this->container->get('router.builder')->rebuild();
|
||||
$this->drupalPlaceBlock('system_powered_by_block');
|
||||
|
||||
// Check the same page, block.module's hook_install() should have
|
||||
// invalidated the 'rendered' cache tag to make blocks show up.
|
||||
$this->drupalGet('');
|
||||
$this->assertCacheTag('config:block_list');
|
||||
$this->assertText('Powered by Drupal');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests display of menu blocks with multiple languages.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockLanguageCacheTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'language', 'menu_ui'];
|
||||
|
||||
/**
|
||||
* List of langcodes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $langcodes = [];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create test languages.
|
||||
$this->langcodes = [ConfigurableLanguage::load('en')];
|
||||
for ($i = 1; $i < 3; ++$i) {
|
||||
$language = ConfigurableLanguage::create([
|
||||
'id' => 'l' . $i,
|
||||
'label' => $this->randomString(),
|
||||
]);
|
||||
$language->save();
|
||||
$this->langcodes[$i] = $language;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a block in a language, check blocks page in all languages.
|
||||
*/
|
||||
public function testBlockLinks() {
|
||||
// Create admin user to be able to access block admin.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'administer blocks',
|
||||
'access administration pages',
|
||||
'administer menu',
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// Create the block cache for all languages.
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
|
||||
$this->clickLinkPartialName('Place block');
|
||||
}
|
||||
|
||||
// Create a menu in the default language.
|
||||
$edit['label'] = $this->randomMachineName();
|
||||
$edit['id'] = Unicode::strtolower($edit['label']);
|
||||
$this->drupalPostForm('admin/structure/menu/add', $edit, t('Save'));
|
||||
$this->assertText(t('Menu @label has been added.', ['@label' => $edit['label']]));
|
||||
|
||||
// Check that the block is listed for all languages.
|
||||
foreach ($this->langcodes as $langcode) {
|
||||
$this->drupalGet('admin/structure/block', ['language' => $langcode]);
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertText($edit['label']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests blocks are being rendered in order by weight.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockRenderOrderTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'block'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create a test user.
|
||||
$end_user = $this->drupalCreateUser([
|
||||
'access content',
|
||||
]);
|
||||
$this->drupalLogin($end_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the render order of the blocks.
|
||||
*/
|
||||
public function testBlockRenderOrder() {
|
||||
// Enable test blocks and place them in the same region.
|
||||
$region = 'header';
|
||||
$test_blocks = [
|
||||
'stark_powered' => [
|
||||
'weight' => '-3',
|
||||
'id' => 'stark_powered',
|
||||
'label' => 'Test block A',
|
||||
],
|
||||
'stark_by' => [
|
||||
'weight' => '3',
|
||||
'id' => 'stark_by',
|
||||
'label' => 'Test block C',
|
||||
],
|
||||
'stark_drupal' => [
|
||||
'weight' => '3',
|
||||
'id' => 'stark_drupal',
|
||||
'label' => 'Test block B',
|
||||
],
|
||||
];
|
||||
|
||||
// Place the test blocks.
|
||||
foreach ($test_blocks as $test_block) {
|
||||
$this->drupalPlaceBlock('system_powered_by_block', [
|
||||
'label' => $test_block['label'],
|
||||
'region' => $region,
|
||||
'weight' => $test_block['weight'],
|
||||
'id' => $test_block['id'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->drupalGet('');
|
||||
$test_content = $this->getRawContent('');
|
||||
|
||||
$controller = $this->container->get('entity_type.manager')->getStorage('block');
|
||||
foreach ($controller->loadMultiple() as $return_block) {
|
||||
$id = $return_block->id();
|
||||
if ($return_block_weight = $return_block->getWeight()) {
|
||||
$this->assertTrue($test_blocks[$id]['weight'] == $return_block_weight, 'Block weight is set as "' . $return_block_weight . '" for ' . $id . ' block.');
|
||||
$position[$id] = strpos($test_content, Html::getClass('block-' . $test_blocks[$id]['id']));
|
||||
}
|
||||
}
|
||||
$this->assertTrue($position['stark_powered'] < $position['stark_by'], 'Blocks with different weight are rendered in the correct order.');
|
||||
$this->assertTrue($position['stark_drupal'] < $position['stark_by'], 'Blocks with identical weight are rendered in alphabetical order.');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
/**
|
||||
* Tests branding block display.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockSystemBrandingTest extends BlockTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'system'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Set a site slogan.
|
||||
$this->config('system.site')
|
||||
->set('slogan', 'Community plumbing')
|
||||
->save();
|
||||
// Add the system branding block to the page.
|
||||
$this->drupalPlaceBlock('system_branding_block', ['region' => 'header', 'id' => 'site-branding']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests system branding block configuration.
|
||||
*/
|
||||
public function testSystemBrandingSettings() {
|
||||
$site_logo_xpath = '//div[@id="block-site-branding"]//a[@class="site-logo"]';
|
||||
$site_name_xpath = '//div[@id="block-site-branding"]//div[@class="site-name"]';
|
||||
$site_slogan_xpath = '//div[@id="block-site-branding"]//div[@class="site-slogan"]';
|
||||
|
||||
// Set default block settings.
|
||||
$this->drupalGet('');
|
||||
$site_logo_element = $this->xpath($site_logo_xpath);
|
||||
$site_name_element = $this->xpath($site_name_xpath);
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
// Test that all branding elements are displayed.
|
||||
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
|
||||
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
|
||||
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
|
||||
$this->assertCacheTag('config:system.site');
|
||||
|
||||
// Be sure the slogan is XSS-filtered.
|
||||
$this->config('system.site')
|
||||
->set('slogan', '<script>alert("Community carpentry");</script>')
|
||||
->save();
|
||||
$this->drupalGet('');
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
$this->assertEqual($site_slogan_element[0], 'alert("Community carpentry");', 'The site slogan was XSS-filtered.');
|
||||
|
||||
// Turn just the logo off.
|
||||
$this->config('block.block.site-branding')
|
||||
->set('settings.use_site_logo', 0)
|
||||
->save();
|
||||
$this->drupalGet('');
|
||||
$site_logo_element = $this->xpath($site_logo_xpath);
|
||||
$site_name_element = $this->xpath($site_name_xpath);
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
// Re-test all branding elements.
|
||||
$this->assertTrue(empty($site_logo_element), 'The branding block logo was disabled.');
|
||||
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
|
||||
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
|
||||
$this->assertCacheTag('config:system.site');
|
||||
|
||||
// Turn just the site name off.
|
||||
$this->config('block.block.site-branding')
|
||||
->set('settings.use_site_logo', 1)
|
||||
->set('settings.use_site_name', 0)
|
||||
->save();
|
||||
$this->drupalGet('');
|
||||
$site_logo_element = $this->xpath($site_logo_xpath);
|
||||
$site_name_element = $this->xpath($site_name_xpath);
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
// Re-test all branding elements.
|
||||
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
|
||||
$this->assertTrue(empty($site_name_element), 'The branding block site name was disabled.');
|
||||
$this->assertTrue(!empty($site_slogan_element), 'The branding block slogan was found.');
|
||||
$this->assertCacheTag('config:system.site');
|
||||
|
||||
// Turn just the site slogan off.
|
||||
$this->config('block.block.site-branding')
|
||||
->set('settings.use_site_name', 1)
|
||||
->set('settings.use_site_slogan', 0)
|
||||
->save();
|
||||
$this->drupalGet('');
|
||||
$site_logo_element = $this->xpath($site_logo_xpath);
|
||||
$site_name_element = $this->xpath($site_name_xpath);
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
// Re-test all branding elements.
|
||||
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
|
||||
$this->assertTrue(!empty($site_name_element), 'The branding block site name was found.');
|
||||
$this->assertTrue(empty($site_slogan_element), 'The branding block slogan was disabled.');
|
||||
$this->assertCacheTag('config:system.site');
|
||||
|
||||
// Turn the site name and the site slogan off.
|
||||
$this->config('block.block.site-branding')
|
||||
->set('settings.use_site_name', 0)
|
||||
->set('settings.use_site_slogan', 0)
|
||||
->save();
|
||||
$this->drupalGet('');
|
||||
$site_logo_element = $this->xpath($site_logo_xpath);
|
||||
$site_name_element = $this->xpath($site_name_xpath);
|
||||
$site_slogan_element = $this->xpath($site_slogan_xpath);
|
||||
// Re-test all branding elements.
|
||||
$this->assertTrue(!empty($site_logo_element), 'The branding block logo was found.');
|
||||
$this->assertTrue(empty($site_name_element), 'The branding block site name was disabled.');
|
||||
$this->assertTrue(empty($site_slogan_element), 'The branding block slogan was disabled.');
|
||||
$this->assertCacheTag('config:system.site');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,551 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
||||
/**
|
||||
* Tests basic block functionality.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockTest extends BlockTestBase {
|
||||
|
||||
/**
|
||||
* Tests block visibility.
|
||||
*/
|
||||
public function testBlockVisibility() {
|
||||
$block_name = 'system_powered_by_block';
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
// Enable a standard block.
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$edit = [
|
||||
'id' => strtolower($this->randomMachineName(8)),
|
||||
'region' => 'sidebar_first',
|
||||
'settings[label]' => $title,
|
||||
'settings[label_display]' => TRUE,
|
||||
];
|
||||
// Set the block to be hidden on any user path, and to be shown only to
|
||||
// authenticated users.
|
||||
$edit['visibility[request_path][pages]'] = '/user*';
|
||||
$edit['visibility[request_path][negate]'] = TRUE;
|
||||
$edit['visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']'] = TRUE;
|
||||
$this->drupalGet('admin/structure/block/add/' . $block_name . '/' . $default_theme);
|
||||
$this->assertFieldChecked('edit-visibility-request-path-negate-0');
|
||||
|
||||
$this->drupalPostForm(NULL, $edit, t('Save block'));
|
||||
$this->assertText('The block configuration has been saved.', 'Block was saved');
|
||||
|
||||
$this->clickLink('Configure');
|
||||
$this->assertFieldChecked('edit-visibility-request-path-negate-1');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($title, 'Block was displayed on the front page.');
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
|
||||
|
||||
// Confirm that the block is not displayed to anonymous users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($title, 'Block was not displayed to anonymous users.');
|
||||
|
||||
// Confirm that an empty block is not displayed.
|
||||
$this->assertNoText('Powered by Drupal', 'Empty block not displayed.');
|
||||
$this->assertNoRaw('sidebar-first', 'Empty sidebar-first region is not displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that visibility can be properly toggled.
|
||||
*/
|
||||
public function testBlockToggleVisibility() {
|
||||
$block_name = 'system_powered_by_block';
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
// Enable a standard block.
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$edit = [
|
||||
'id' => strtolower($this->randomMachineName(8)),
|
||||
'region' => 'sidebar_first',
|
||||
'settings[label]' => $title,
|
||||
];
|
||||
$block_id = $edit['id'];
|
||||
// Set the block to be shown only to authenticated users.
|
||||
$edit['visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']'] = TRUE;
|
||||
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
|
||||
$this->clickLink('Configure');
|
||||
$this->assertFieldChecked('edit-visibility-user-role-roles-authenticated');
|
||||
|
||||
$edit = [
|
||||
'visibility[user_role][roles][' . RoleInterface::AUTHENTICATED_ID . ']' => FALSE,
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save block');
|
||||
$this->clickLink('Configure');
|
||||
$this->assertNoFieldChecked('edit-visibility-user-role-roles-authenticated');
|
||||
|
||||
// Ensure that no visibility is configured.
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$block = Block::load($block_id);
|
||||
$visibility_config = $block->getVisibilityConditions()->getConfiguration();
|
||||
$this->assertIdentical([], $visibility_config);
|
||||
$this->assertIdentical([], $block->get('visibility'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block visibility when leaving "pages" textarea empty.
|
||||
*/
|
||||
public function testBlockVisibilityListedEmpty() {
|
||||
$block_name = 'system_powered_by_block';
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
// Enable a standard block.
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$edit = [
|
||||
'id' => strtolower($this->randomMachineName(8)),
|
||||
'region' => 'sidebar_first',
|
||||
'settings[label]' => $title,
|
||||
'visibility[request_path][negate]' => TRUE,
|
||||
];
|
||||
// Set the block to be hidden on any user path, and to be shown only to
|
||||
// authenticated users.
|
||||
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
|
||||
$this->assertText('The block configuration has been saved.', 'Block was saved');
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($title, 'Block was not displayed according to block visibility rules.');
|
||||
|
||||
$this->drupalGet('USER');
|
||||
$this->assertNoText($title, 'Block was not displayed according to block visibility rules regardless of path case.');
|
||||
|
||||
// Confirm that the block is not displayed to anonymous users.
|
||||
$this->drupalLogout();
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText($title, 'Block was not displayed to anonymous users on the front page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding a block from the library page with a weight query string.
|
||||
*/
|
||||
public function testAddBlockFromLibraryWithWeight() {
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
// Test one positive, zero, and one negative weight.
|
||||
foreach (['7', '0', '-9'] as $weight) {
|
||||
$options = [
|
||||
'query' => [
|
||||
'region' => 'sidebar_first',
|
||||
'weight' => $weight,
|
||||
],
|
||||
];
|
||||
$this->drupalGet(Url::fromRoute('block.admin_library', ['theme' => $default_theme], $options));
|
||||
|
||||
$block_name = 'system_powered_by_block';
|
||||
$add_url = Url::fromRoute('block.admin_add', [
|
||||
'plugin_id' => $block_name,
|
||||
'theme' => $default_theme
|
||||
]);
|
||||
$links = $this->xpath('//a[contains(@href, :href)]', [':href' => $add_url->toString()]);
|
||||
$this->assertEqual(1, count($links), 'Found one matching link.');
|
||||
$this->assertEqual(t('Place block'), (string) $links[0], 'Found the expected link text.');
|
||||
|
||||
list($path, $query_string) = explode('?', $links[0]['href'], 2);
|
||||
parse_str($query_string, $query_parts);
|
||||
$this->assertEqual($weight, $query_parts['weight'], 'Found the expected weight query string.');
|
||||
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
$block_id = strtolower($this->randomMachineName(8));
|
||||
$edit = [
|
||||
'id' => $block_id,
|
||||
'settings[label]' => $title,
|
||||
];
|
||||
// Create the block using the link parsed from the library page.
|
||||
$this->drupalPostForm($this->getAbsoluteUrl($links[0]['href']), $edit, t('Save block'));
|
||||
|
||||
// Ensure that the block was created with the expected weight.
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$block = Block::load($block_id);
|
||||
$this->assertEqual($weight, $block->getWeight(), 'Found the block with expected weight.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test configuring and moving a module-define block to specific regions.
|
||||
*/
|
||||
public function testBlock() {
|
||||
// Place page title block to test error messages.
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
|
||||
// Disable the block.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLink('Disable');
|
||||
|
||||
// Select the 'Powered by Drupal' block to be configured and moved.
|
||||
$block = [];
|
||||
$block['id'] = 'system_powered_by_block';
|
||||
$block['settings[label]'] = $this->randomMachineName(8);
|
||||
$block['settings[label_display]'] = TRUE;
|
||||
$block['theme'] = $this->config('system.theme')->get('default');
|
||||
$block['region'] = 'header';
|
||||
|
||||
// Set block title to confirm that interface works and override any custom titles.
|
||||
$this->drupalPostForm('admin/structure/block/add/' . $block['id'] . '/' . $block['theme'], ['settings[label]' => $block['settings[label]'], 'settings[label_display]' => $block['settings[label_display]'], 'id' => $block['id'], 'region' => $block['region']], t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'), 'Block title set.');
|
||||
// Check to see if the block was created by checking its configuration.
|
||||
$instance = Block::load($block['id']);
|
||||
|
||||
$this->assertEqual($instance->label(), $block['settings[label]'], 'Stored block title found.');
|
||||
|
||||
// Check whether the block can be moved to all available regions.
|
||||
foreach ($this->regions as $region) {
|
||||
$this->moveBlockToRegion($block, $region);
|
||||
}
|
||||
|
||||
// Disable the block.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLink('Disable');
|
||||
|
||||
// Confirm that the block is now listed as disabled.
|
||||
$this->assertText(t('The block settings have been updated.'), 'Block successfully moved to disabled region.');
|
||||
|
||||
// Confirm that the block instance title and markup are not displayed.
|
||||
$this->drupalGet('node');
|
||||
$this->assertNoText(t($block['settings[label]']));
|
||||
// Check for <div id="block-my-block-instance-name"> if the machine name
|
||||
// is my_block_instance_name.
|
||||
$xpath = $this->buildXPathQuery('//div[@id=:id]/*', [':id' => 'block-' . str_replace('_', '-', strtolower($block['id']))]);
|
||||
$this->assertNoFieldByXPath($xpath, FALSE, 'Block found in no regions.');
|
||||
|
||||
// Test deleting the block from the edit form.
|
||||
$this->drupalGet('admin/structure/block/manage/' . $block['id']);
|
||||
$this->clickLink(t('Remove block'));
|
||||
$this->assertRaw(t('Are you sure you want to remove the block @name?', ['@name' => $block['settings[label]']]));
|
||||
$this->drupalPostForm(NULL, [], t('Remove'));
|
||||
$this->assertRaw(t('The block %name has been removed.', ['%name' => $block['settings[label]']]));
|
||||
|
||||
// Test deleting a block via "Configure block" link.
|
||||
$block = $this->drupalPlaceBlock('system_powered_by_block');
|
||||
$this->drupalGet('admin/structure/block/manage/' . $block->id(), ['query' => ['destination' => 'admin']]);
|
||||
$this->clickLink(t('Remove block'));
|
||||
$this->assertRaw(t('Are you sure you want to remove the block @name?', ['@name' => $block->label()]));
|
||||
$this->drupalPostForm(NULL, [], t('Remove'));
|
||||
$this->assertRaw(t('The block %name has been removed.', ['%name' => $block->label()]));
|
||||
$this->assertUrl('admin');
|
||||
$this->assertNoRaw($block->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the block form has a theme selector when not passed via the URL.
|
||||
*/
|
||||
public function testBlockThemeSelector() {
|
||||
// Install all themes.
|
||||
\Drupal::service('theme_handler')->install(['bartik', 'seven', 'stark']);
|
||||
$theme_settings = $this->config('system.theme');
|
||||
foreach (['bartik', 'seven', 'stark'] as $theme) {
|
||||
$this->drupalGet('admin/structure/block/list/' . $theme);
|
||||
$this->assertTitle(t('Block layout') . ' | Drupal');
|
||||
// Select the 'Powered by Drupal' block to be placed.
|
||||
$block = [];
|
||||
$block['id'] = strtolower($this->randomMachineName());
|
||||
$block['theme'] = $theme;
|
||||
$block['region'] = 'content';
|
||||
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block', $block, t('Save block'));
|
||||
$this->assertText(t('The block configuration has been saved.'));
|
||||
$this->assertUrl('admin/structure/block/list/' . $theme . '?block-placement=' . Html::getClass($block['id']));
|
||||
|
||||
// Set the default theme and ensure the block is placed.
|
||||
$theme_settings->set('default', $theme)->save();
|
||||
$this->drupalGet('');
|
||||
$elements = $this->xpath('//div[@id = :id]', [':id' => Html::getUniqueId('block-' . $block['id'])]);
|
||||
$this->assertTrue(!empty($elements), 'The block was found.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block display of theme titles.
|
||||
*/
|
||||
public function testThemeName() {
|
||||
// Enable the help block.
|
||||
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
// Explicitly set the default and admin themes.
|
||||
$theme = 'block_test_specialchars_theme';
|
||||
\Drupal::service('theme_handler')->install([$theme]);
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertEscaped('<"Cat" & \'Mouse\'>');
|
||||
$this->drupalGet('admin/structure/block/list/block_test_specialchars_theme');
|
||||
$this->assertEscaped('Demonstrate block regions (<"Cat" & \'Mouse\'>)');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block title display settings.
|
||||
*/
|
||||
public function testHideBlockTitle() {
|
||||
$block_name = 'system_powered_by_block';
|
||||
// Create a random title for the block.
|
||||
$title = $this->randomMachineName(8);
|
||||
$id = strtolower($this->randomMachineName(8));
|
||||
// Enable a standard block.
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$edit = [
|
||||
'id' => $id,
|
||||
'region' => 'sidebar_first',
|
||||
'settings[label]' => $title,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/block/add/' . $block_name . '/' . $default_theme, $edit, t('Save block'));
|
||||
$this->assertText('The block configuration has been saved.', 'Block was saved');
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertNoText($title, 'Block title was not displayed by default.');
|
||||
|
||||
$edit = [
|
||||
'settings[label_display]' => TRUE,
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/block/manage/' . $id, $edit, t('Save block'));
|
||||
$this->assertText('The block configuration has been saved.', 'Block was saved');
|
||||
|
||||
$this->drupalGet('admin/structure/block/manage/' . $id);
|
||||
$this->assertFieldChecked('edit-settings-label-display', 'The display_block option has the correct default value on the configuration form.');
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->assertText($title, 'Block title was displayed when enabled.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a block to a given region via the UI and confirms the result.
|
||||
*
|
||||
* @param array $block
|
||||
* An array of information about the block, including the following keys:
|
||||
* - module: The module providing the block.
|
||||
* - title: The title of the block.
|
||||
* - delta: The block's delta key.
|
||||
* @param string $region
|
||||
* The machine name of the theme region to move the block to, for example
|
||||
* 'header' or 'sidebar_first'.
|
||||
*/
|
||||
public function moveBlockToRegion(array $block, $region) {
|
||||
// Set the created block to a specific region.
|
||||
$block += ['theme' => $this->config('system.theme')->get('default')];
|
||||
$edit = [];
|
||||
$edit['blocks[' . $block['id'] . '][region]'] = $region;
|
||||
$this->drupalPostForm('admin/structure/block', $edit, t('Save blocks'));
|
||||
|
||||
// Confirm that the block was moved to the proper region.
|
||||
$this->assertText(t('The block settings have been updated.'), format_string('Block successfully moved to %region_name region.', [ '%region_name' => $region]));
|
||||
|
||||
// Confirm that the block is being displayed.
|
||||
$this->drupalGet('');
|
||||
$this->assertText(t($block['settings[label]']), 'Block successfully being displayed on the page.');
|
||||
|
||||
// Confirm that the custom block was found at the proper region.
|
||||
$xpath = $this->buildXPathQuery('//div[@class=:region-class]//div[@id=:block-id]/*', [
|
||||
':region-class' => 'region region-' . Html::getClass($region),
|
||||
':block-id' => 'block-' . str_replace('_', '-', strtolower($block['id'])),
|
||||
]);
|
||||
$this->assertFieldByXPath($xpath, NULL, t('Block found in %region_name region.', ['%region_name' => Html::getClass($region)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that cache tags are properly set and bubbled up to the page cache.
|
||||
*
|
||||
* Verify that invalidation of these cache tags works:
|
||||
* - "block:<block ID>"
|
||||
* - "block_plugin:<block plugin ID>"
|
||||
*/
|
||||
public function testBlockCacheTags() {
|
||||
// The page cache only works for anonymous users.
|
||||
$this->drupalLogout();
|
||||
|
||||
// Enable page caching.
|
||||
$config = $this->config('system.performance');
|
||||
$config->set('cache.page.max_age', 300);
|
||||
$config->save();
|
||||
|
||||
// Place the "Powered by Drupal" block.
|
||||
$block = $this->drupalPlaceBlock('system_powered_by_block', ['id' => 'powered']);
|
||||
|
||||
// Prime the page cache.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags in
|
||||
// both the page and block caches.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
|
||||
$cid = implode(':', $cid_parts);
|
||||
$cache_entry = \Drupal::cache('render')->get($cid);
|
||||
$expected_cache_tags = [
|
||||
'config:block_list',
|
||||
'block_view',
|
||||
'config:block.block.powered',
|
||||
'config:user.role.anonymous',
|
||||
'http_response',
|
||||
'rendered',
|
||||
];
|
||||
sort($expected_cache_tags);
|
||||
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:' . implode(':', $keys));
|
||||
$expected_cache_tags = [
|
||||
'block_view',
|
||||
'config:block.block.powered',
|
||||
'rendered',
|
||||
];
|
||||
sort($expected_cache_tags);
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
|
||||
// The "Powered by Drupal" block is modified; verify a cache miss.
|
||||
$block->setRegion('content');
|
||||
$block->save();
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
|
||||
// Now we should have a cache hit again.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
|
||||
// Place the "Powered by Drupal" block another time; verify a cache miss.
|
||||
$block_2 = $this->drupalPlaceBlock('system_powered_by_block', ['id' => 'powered-2']);
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
|
||||
// Verify a cache hit, but also the presence of the correct cache tags.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
$cid_parts = [\Drupal::url('<front>', [], ['absolute' => TRUE]), 'html'];
|
||||
$cid = implode(':', $cid_parts);
|
||||
$cache_entry = \Drupal::cache('render')->get($cid);
|
||||
$expected_cache_tags = [
|
||||
'config:block_list',
|
||||
'block_view',
|
||||
'config:block.block.powered',
|
||||
'config:block.block.powered-2',
|
||||
'config:user.role.anonymous',
|
||||
'http_response',
|
||||
'rendered',
|
||||
];
|
||||
sort($expected_cache_tags);
|
||||
$this->assertEqual($cache_entry->tags, $expected_cache_tags);
|
||||
$expected_cache_tags = [
|
||||
'block_view',
|
||||
'config:block.block.powered',
|
||||
'rendered',
|
||||
];
|
||||
sort($expected_cache_tags);
|
||||
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered:' . implode(':', $keys));
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
$expected_cache_tags = [
|
||||
'block_view',
|
||||
'config:block.block.powered-2',
|
||||
'rendered',
|
||||
];
|
||||
sort($expected_cache_tags);
|
||||
$keys = \Drupal::service('cache_contexts_manager')->convertTokensToKeys(['languages:language_interface', 'theme', 'user.permissions'])->getKeys();
|
||||
$cache_entry = \Drupal::cache('render')->get('entity_view:block:powered-2:' . implode(':', $keys));
|
||||
$this->assertIdentical($cache_entry->tags, $expected_cache_tags);
|
||||
|
||||
// Now we should have a cache hit again.
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'HIT');
|
||||
|
||||
// Delete the "Powered by Drupal" blocks; verify a cache miss.
|
||||
entity_delete_multiple('block', ['powered', 'powered-2']);
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertEqual($this->drupalGetHeader('X-Drupal-Cache'), 'MISS');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a link exists to block layout from the appearance form.
|
||||
*/
|
||||
public function testThemeAdminLink() {
|
||||
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
|
||||
$theme_admin = $this->drupalCreateUser([
|
||||
'administer blocks',
|
||||
'administer themes',
|
||||
'access administration pages',
|
||||
]);
|
||||
$this->drupalLogin($theme_admin);
|
||||
$this->drupalGet('admin/appearance');
|
||||
$this->assertText('You can place blocks for each theme on the block layout page');
|
||||
$this->assertLinkByHref('admin/structure/block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that uninstalling a theme removes its block configuration.
|
||||
*/
|
||||
public function testUninstallTheme() {
|
||||
/** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
|
||||
$theme_handler = \Drupal::service('theme_handler');
|
||||
|
||||
$theme_handler->install(['seven']);
|
||||
$this->config('system.theme')->set('default', 'seven')->save();
|
||||
$block = $this->drupalPlaceBlock('system_powered_by_block', ['theme' => 'seven', 'region' => 'help']);
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertText('Powered by Drupal');
|
||||
|
||||
$this->config('system.theme')->set('default', 'classy')->save();
|
||||
$theme_handler->uninstall(['seven']);
|
||||
|
||||
// Ensure that the block configuration does not exist anymore.
|
||||
$this->assertIdentical(NULL, Block::load($block->id()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block access.
|
||||
*/
|
||||
public function testBlockAccess() {
|
||||
$this->drupalPlaceBlock('test_access', ['region' => 'help']);
|
||||
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertNoText('Hello test world');
|
||||
|
||||
\Drupal::state()->set('test_block_access', TRUE);
|
||||
$this->drupalGet('<front>');
|
||||
$this->assertText('Hello test world');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests block_user_role_delete.
|
||||
*/
|
||||
public function testBlockUserRoleDelete() {
|
||||
$role1 = Role::create(['id' => 'test_role1', 'name' => $this->randomString()]);
|
||||
$role1->save();
|
||||
|
||||
$role2 = Role::create(['id' => 'test_role2', 'name' => $this->randomString()]);
|
||||
$role2->save();
|
||||
|
||||
$block = Block::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'plugin' => 'system_powered_by_block',
|
||||
]);
|
||||
|
||||
$block->setVisibilityConfig('user_role', [
|
||||
'roles' => [
|
||||
$role1->id() => $role1->id(),
|
||||
$role2->id() => $role2->id(),
|
||||
],
|
||||
]);
|
||||
|
||||
$block->save();
|
||||
|
||||
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
|
||||
$role1->id() => $role1->id(),
|
||||
$role2->id() => $role2->id()
|
||||
]);
|
||||
|
||||
$role1->delete();
|
||||
|
||||
$block = Block::load($block->id());
|
||||
$this->assertEqual($block->getVisibility()['user_role']['roles'], [
|
||||
$role2->id() => $role2->id()
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,11 +2,18 @@
|
|||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
@trigger_error(__NAMESPACE__ . '\BlockTestBase is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\block\Functional\BlockTestBase, see https://www.drupal.org/node/2901823.', E_USER_DEPRECATED);
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Provides setup and helper methods for block module tests.
|
||||
*
|
||||
* @deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0.
|
||||
* Use \Drupal\Tests\block\Functional\BlockTestBase.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2901823
|
||||
*/
|
||||
abstract class BlockTestBase extends WebTestBase {
|
||||
|
||||
|
|
|
@ -1,329 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests that the block configuration UI exists and stores data correctly.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockUiTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_test', 'help', 'condition_test'];
|
||||
|
||||
protected $regions;
|
||||
|
||||
/**
|
||||
* The submitted block values used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $blockValues;
|
||||
|
||||
/**
|
||||
* The block entities used by this test.
|
||||
*
|
||||
* @var \Drupal\block\BlockInterface[]
|
||||
*/
|
||||
protected $blocks;
|
||||
|
||||
/**
|
||||
* An administrative user to configure the test environment.
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create and log in an administrative user.
|
||||
$this->adminUser = $this->drupalCreateUser([
|
||||
'administer blocks',
|
||||
'access administration pages',
|
||||
]);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
// Enable some test blocks.
|
||||
$this->blockValues = [
|
||||
[
|
||||
'label' => 'Tools',
|
||||
'tr' => '5',
|
||||
'plugin_id' => 'system_menu_block:tools',
|
||||
'settings' => ['region' => 'sidebar_second', 'id' => 'tools'],
|
||||
'test_weight' => '-1',
|
||||
],
|
||||
[
|
||||
'label' => 'Powered by Drupal',
|
||||
'tr' => '16',
|
||||
'plugin_id' => 'system_powered_by_block',
|
||||
'settings' => ['region' => 'footer', 'id' => 'powered'],
|
||||
'test_weight' => '0',
|
||||
],
|
||||
];
|
||||
$this->blocks = [];
|
||||
foreach ($this->blockValues as $values) {
|
||||
$this->blocks[] = $this->drupalPlaceBlock($values['plugin_id'], $values['settings']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block demo page exists and functions correctly.
|
||||
*/
|
||||
public function testBlockDemoUiPage() {
|
||||
$this->drupalPlaceBlock('help_block', ['region' => 'help']);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLink(t('Demonstrate block regions (@theme)', ['@theme' => 'Classy']));
|
||||
$elements = $this->xpath('//div[contains(@class, "region-highlighted")]/div[contains(@class, "block-region") and contains(text(), :title)]', [':title' => 'Highlighted']);
|
||||
$this->assertTrue(!empty($elements), 'Block demo regions are shown.');
|
||||
|
||||
\Drupal::service('theme_handler')->install(['test_theme']);
|
||||
$this->drupalGet('admin/structure/block/demo/test_theme');
|
||||
$this->assertEscaped('<strong>Test theme</strong>');
|
||||
|
||||
\Drupal::service('theme_handler')->install(['stable']);
|
||||
$this->drupalGet('admin/structure/block/demo/stable');
|
||||
$this->assertResponse(404, 'Hidden themes that are not the default theme are not supported by the block demo screen');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test block admin page exists and functions correctly.
|
||||
*/
|
||||
public function testBlockAdminUiPage() {
|
||||
// Visit the blocks admin ui.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
// Look for the blocks table.
|
||||
$blocks_table = $this->xpath("//table[@id='blocks']");
|
||||
$this->assertTrue(!empty($blocks_table), 'The blocks table is being rendered.');
|
||||
// Look for test blocks in the table.
|
||||
foreach ($this->blockValues as $delta => $values) {
|
||||
$block = $this->blocks[$delta];
|
||||
$label = $block->label();
|
||||
$element = $this->xpath('//*[@id="blocks"]/tbody/tr[' . $values['tr'] . ']/td[1]/text()');
|
||||
$this->assertTrue((string) $element[0] == $label, 'The "' . $label . '" block title is set inside the ' . $values['settings']['region'] . ' region.');
|
||||
// Look for a test block region select form element.
|
||||
$this->assertField('blocks[' . $values['settings']['id'] . '][region]', 'The block "' . $values['label'] . '" has a region assignment field.');
|
||||
// Move the test block to the header region.
|
||||
$edit['blocks[' . $values['settings']['id'] . '][region]'] = 'header';
|
||||
// Look for a test block weight select form element.
|
||||
$this->assertField('blocks[' . $values['settings']['id'] . '][weight]', 'The block "' . $values['label'] . '" has a weight assignment field.');
|
||||
// Change the test block's weight.
|
||||
$edit['blocks[' . $values['settings']['id'] . '][weight]'] = $values['test_weight'];
|
||||
}
|
||||
$this->drupalPostForm('admin/structure/block', $edit, t('Save blocks'));
|
||||
foreach ($this->blockValues as $values) {
|
||||
// Check if the region and weight settings changes have persisted.
|
||||
$this->assertOptionSelected(
|
||||
'edit-blocks-' . $values['settings']['id'] . '-region',
|
||||
'header',
|
||||
'The block "' . $label . '" has the correct region assignment (header).'
|
||||
);
|
||||
$this->assertOptionSelected(
|
||||
'edit-blocks-' . $values['settings']['id'] . '-weight',
|
||||
$values['test_weight'],
|
||||
'The block "' . $label . '" has the correct weight assignment (' . $values['test_weight'] . ').'
|
||||
);
|
||||
}
|
||||
|
||||
// Add a block with a machine name the same as a region name.
|
||||
$this->drupalPlaceBlock('system_powered_by_block', ['region' => 'header', 'id' => 'header']);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$element = $this->xpath('//tr[contains(@class, :class)]', [':class' => 'region-title-header']);
|
||||
$this->assertTrue(!empty($element));
|
||||
|
||||
// Ensure hidden themes do not appear in the UI. Enable another non base
|
||||
// theme and place the local tasks block.
|
||||
$this->assertTrue(\Drupal::service('theme_handler')->themeExists('classy'), 'The classy base theme is enabled');
|
||||
$this->drupalPlaceBlock('local_tasks_block', ['region' => 'header']);
|
||||
\Drupal::service('theme_installer')->install(['stable', 'stark']);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$theme_handler = \Drupal::service('theme_handler');
|
||||
$this->assertLink($theme_handler->getName('classy'));
|
||||
$this->assertLink($theme_handler->getName('stark'));
|
||||
$this->assertNoLink($theme_handler->getName('stable'));
|
||||
|
||||
$this->drupalGet('admin/structure/block/list/stable');
|
||||
$this->assertResponse(404, 'Placing blocks through UI is not possible for a hidden base theme.');
|
||||
|
||||
\Drupal::configFactory()->getEditable('system.theme')->set('admin', 'stable')->save();
|
||||
\Drupal::service('router.builder')->rebuildIfNeeded();
|
||||
$this->drupalPlaceBlock('local_tasks_block', ['region' => 'header', 'theme' => 'stable']);
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->assertLink($theme_handler->getName('stable'));
|
||||
$this->drupalGet('admin/structure/block/list/stable');
|
||||
$this->assertResponse(200, 'Placing blocks through UI is possible for a hidden base theme that is the admin theme.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block categories on the listing page.
|
||||
*/
|
||||
public function testCandidateBlockList() {
|
||||
$arguments = [
|
||||
':title' => 'Display message',
|
||||
':category' => 'Block test',
|
||||
':href' => 'admin/structure/block/add/test_block_instantiation/classy',
|
||||
];
|
||||
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The test block appears in the category for its module.');
|
||||
|
||||
// Trigger the custom category addition in block_test_block_alter().
|
||||
$this->container->get('state')->set('block_test_info_alter', TRUE);
|
||||
$this->container->get('plugin.manager.block')->clearCachedDefinitions();
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$arguments[':category'] = 'Custom category';
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The test block appears in a custom category controlled by block_test_block_alter().');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of unsatisfied context-aware blocks.
|
||||
*/
|
||||
public function testContextAwareUnsatisfiedBlocks() {
|
||||
$arguments = [
|
||||
':category' => 'Block test',
|
||||
':href' => 'admin/structure/block/add/test_context_aware_unsatisfied/classy',
|
||||
':text' => 'Test context-aware unsatisfied block',
|
||||
];
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath('//tr[.//td/div[text()=:text] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]', $arguments);
|
||||
$this->assertTrue(empty($elements), 'The context-aware test block does not appear.');
|
||||
|
||||
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware_unsatisfied');
|
||||
$this->assertTrue(!empty($definition), 'The context-aware test block does not exist.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of context-aware blocks.
|
||||
*/
|
||||
public function testContextAwareBlocks() {
|
||||
$expected_text = '<div id="test_context_aware--username">' . \Drupal::currentUser()->getUsername() . '</div>';
|
||||
$this->drupalGet('');
|
||||
$this->assertNoText('Test context-aware block');
|
||||
$this->assertNoRaw($expected_text);
|
||||
|
||||
$block_url = 'admin/structure/block/add/test_context_aware/classy';
|
||||
$arguments = [
|
||||
':title' => 'Test context-aware block',
|
||||
':category' => 'Block test',
|
||||
':href' => $block_url,
|
||||
];
|
||||
$pattern = '//tr[.//td/div[text()=:title] and .//td[text()=:category] and .//td//a[contains(@href, :href)]]';
|
||||
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The context-aware test block appears.');
|
||||
$definition = \Drupal::service('plugin.manager.block')->getDefinition('test_context_aware');
|
||||
$this->assertTrue(!empty($definition), 'The context-aware test block exists.');
|
||||
$edit = [
|
||||
'region' => 'content',
|
||||
'settings[context_mapping][user]' => '@block_test.multiple_static_context:userB',
|
||||
];
|
||||
$this->drupalPostForm($block_url, $edit, 'Save block');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText('Test context-aware block');
|
||||
$this->assertText('User context found.');
|
||||
$this->assertRaw($expected_text);
|
||||
|
||||
// Test context mapping allows empty selection for optional contexts.
|
||||
$this->drupalGet('admin/structure/block/manage/testcontextawareblock');
|
||||
$edit = [
|
||||
'settings[context_mapping][user]' => '',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, 'Save block');
|
||||
$this->drupalGet('');
|
||||
$this->assertText('No context mapping selected.');
|
||||
$this->assertNoText('User context found.');
|
||||
|
||||
// Tests that conditions with missing context are not displayed.
|
||||
$this->drupalGet('admin/structure/block/manage/testcontextawareblock');
|
||||
$this->assertNoRaw('No existing type');
|
||||
$this->assertNoFieldByXPath('//*[@name="visibility[condition_test_no_existing_type][negate]"]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the BlockForm populates machine name correctly.
|
||||
*/
|
||||
public function testMachineNameSuggestion() {
|
||||
$url = 'admin/structure/block/add/test_block_instantiation/classy';
|
||||
$this->drupalGet($url);
|
||||
$this->assertFieldByName('id', 'displaymessage', 'Block form uses raw machine name suggestion when no instance already exists.');
|
||||
$edit = ['region' => 'content'];
|
||||
$this->drupalPostForm($url, $edit, 'Save block');
|
||||
$this->assertText('The block configuration has been saved.');
|
||||
|
||||
// Now, check to make sure the form starts by autoincrementing correctly.
|
||||
$this->drupalGet($url);
|
||||
$this->assertFieldByName('id', 'displaymessage_2', 'Block form appends _2 to plugin-suggested machine name when an instance already exists.');
|
||||
$this->drupalPostForm($url, $edit, 'Save block');
|
||||
$this->assertText('The block configuration has been saved.');
|
||||
|
||||
// And verify that it continues working beyond just the first two.
|
||||
$this->drupalGet($url);
|
||||
$this->assertFieldByName('id', 'displaymessage_3', 'Block form appends _3 to plugin-suggested machine name when two instances already exist.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the block placement indicator.
|
||||
*/
|
||||
public function testBlockPlacementIndicator() {
|
||||
// Select the 'Powered by Drupal' block to be placed.
|
||||
$block = [];
|
||||
$block['id'] = strtolower($this->randomMachineName());
|
||||
$block['theme'] = 'classy';
|
||||
$block['region'] = 'content';
|
||||
|
||||
// After adding a block, it will indicate which block was just added.
|
||||
$this->drupalPostForm('admin/structure/block/add/system_powered_by_block', $block, t('Save block'));
|
||||
$this->assertUrl('admin/structure/block/list/classy?block-placement=' . Html::getClass($block['id']));
|
||||
|
||||
// Resaving the block page will remove the block indicator.
|
||||
$this->drupalPostForm(NULL, [], t('Save blocks'));
|
||||
$this->assertUrl('admin/structure/block/list/classy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if validation errors are passed plugin form to the parent form.
|
||||
*/
|
||||
public function testBlockValidateErrors() {
|
||||
$this->drupalPostForm('admin/structure/block/add/test_settings_validation/classy', ['region' => 'content', 'settings[digits]' => 'abc'], t('Save block'));
|
||||
|
||||
$arguments = [':message' => 'Only digits are allowed'];
|
||||
$pattern = '//div[contains(@class,"messages messages--error")]/div[contains(text()[2],:message)]';
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue($elements, 'Plugin error message found in parent form.');
|
||||
|
||||
$error_class_pattern = '//div[contains(@class,"form-item-settings-digits")]/input[contains(@class,"error")]';
|
||||
$error_class = $this->xpath($error_class_pattern);
|
||||
$this->assertTrue($error_class, 'Plugin error class found in parent form.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the enable/disable routes are protected from CSRF.
|
||||
*/
|
||||
public function testRouteProtection() {
|
||||
// Get the first block generated in our setUp method.
|
||||
/** @var \Drupal\block\BlockInterface $block */
|
||||
$block = reset($this->blocks);
|
||||
// Ensure that the enable and disable routes are protected.
|
||||
$this->drupalGet('admin/structure/block/manage/' . $block->id() . '/disable');
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('admin/structure/block/manage/' . $block->id() . '/enable');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\system\Entity\Menu;
|
||||
use Drupal\views\Entity\View;
|
||||
|
||||
/**
|
||||
* Tests that the block module properly escapes block descriptions.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class BlockXssTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'block_content', 'menu_ui', 'views'];
|
||||
|
||||
/**
|
||||
* Tests that nothing is escaped other than the blocks explicitly tested.
|
||||
*/
|
||||
public function testNoUnexpectedEscaping() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertNoEscaped('<');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS in title.
|
||||
*/
|
||||
public function testXssInTitle() {
|
||||
$this->container->get('module_installer')->install(['block_test']);
|
||||
$this->drupalPlaceBlock('test_xss_title', ['label' => '<script>alert("XSS label");</script>']);
|
||||
|
||||
\Drupal::state()->set('block_test.content', $this->randomMachineName());
|
||||
$this->drupalGet('');
|
||||
$this->assertNoRaw('<script>alert("XSS label");</script>', 'The block title was properly sanitized when rendered.');
|
||||
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$this->drupalGet('admin/structure/block/list/' . $default_theme);
|
||||
$this->assertNoRaw("<script>alert('XSS subject');</script>", 'The block title was properly sanitized in Block Plugin UI Admin page.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS in category.
|
||||
*/
|
||||
public function testXssInCategory() {
|
||||
$this->container->get('module_installer')->install(['block_test']);
|
||||
$this->drupalPlaceBlock('test_xss_title');
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks', 'access administration pages']));
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertNoRaw("<script>alert('XSS category');</script>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests various modules that provide blocks for XSS.
|
||||
*/
|
||||
public function testBlockXss() {
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
$this->doViewTest();
|
||||
$this->doMenuTest();
|
||||
$this->doBlockContentTest();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertNoRaw('&lt;', 'The page does not have double escaped HTML tags.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS coming from View block labels.
|
||||
*/
|
||||
protected function doViewTest() {
|
||||
// Create a View without a custom label for its block Display. The
|
||||
// admin_label of the block then becomes just the View's label.
|
||||
$view = View::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => '<script>alert("view1");</script>',
|
||||
]);
|
||||
$view->addDisplay('block');
|
||||
$view->save();
|
||||
|
||||
// Create a View with a custom label for its block Display. The
|
||||
// admin_label of the block then becomes the View's label combined with
|
||||
// the Display's label.
|
||||
$view = View::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => '<script>alert("view2");</script>',
|
||||
]);
|
||||
$view->addDisplay('block', 'Fish & chips');
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
|
||||
// \Drupal\views\Plugin\Derivative\ViewsBlock::getDerivativeDefinitions()
|
||||
// has a different code path for an admin label based only on the View
|
||||
// label versus one based on both the View label and the Display label.
|
||||
// Ensure that this test is covering both code paths by asserting the
|
||||
// absence of a ":" for the first View and the presence of a ":" for the
|
||||
// second one. Note that the second assertion is redundant with the one
|
||||
// further down which also checks for the Display label, but is included
|
||||
// here for clarity.
|
||||
$this->assertNoEscaped('<script>alert("view1");</script>:');
|
||||
$this->assertEscaped('<script>alert("view2");</script>:');
|
||||
|
||||
// Assert that the blocks have their admin labels escaped and
|
||||
// don't appear anywhere unescaped.
|
||||
$this->assertEscaped('<script>alert("view1");</script>');
|
||||
$this->assertNoRaw('<script>alert("view1");</script>');
|
||||
$this->assertEscaped('<script>alert("view2");</script>: Fish & chips');
|
||||
$this->assertNoRaw('<script>alert("view2");</script>');
|
||||
$this->assertNoRaw('Fish & chips');
|
||||
|
||||
// Assert the Display label doesn't appear anywhere double escaped.
|
||||
$this->assertNoRaw('Fish & chips');
|
||||
$this->assertNoRaw('Fish &amp; chips');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS coming from Menu block labels.
|
||||
*/
|
||||
protected function doMenuTest() {
|
||||
Menu::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'label' => '<script>alert("menu");</script>',
|
||||
])->save();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
|
||||
$this->assertEscaped('<script>alert("menu");</script>');
|
||||
$this->assertNoRaw('<script>alert("menu");</script>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests XSS coming from Block Content block info.
|
||||
*/
|
||||
protected function doBlockContentTest() {
|
||||
BlockContentType::create([
|
||||
'id' => 'basic',
|
||||
'label' => 'basic',
|
||||
'revision' => TRUE,
|
||||
])->save();
|
||||
BlockContent::create([
|
||||
'type' => 'basic',
|
||||
'info' => '<script>alert("block_content");</script>',
|
||||
])->save();
|
||||
|
||||
$this->drupalGet(Url::fromRoute('block.admin_display'));
|
||||
$this->clickLinkPartialName('Place block');
|
||||
|
||||
$this->assertEscaped('<script>alert("block_content");</script>');
|
||||
$this->assertNoRaw('<script>alert("block_content");</script>');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the block administration page for a non-default theme.
|
||||
*
|
||||
* @group block
|
||||
*/
|
||||
class NonDefaultBlockAdminTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test non-default theme admin.
|
||||
*/
|
||||
public function testNonDefaultBlockAdmin() {
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks', 'administer themes']);
|
||||
$this->drupalLogin($admin_user);
|
||||
$new_theme = 'bartik';
|
||||
\Drupal::service('theme_handler')->install([$new_theme]);
|
||||
$this->drupalGet('admin/structure/block/list/' . $new_theme);
|
||||
$this->assertText('Bartik(' . t('active tab') . ')', 'Tab for non-default theme found.');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests the upgrade path for block with conditions missing context.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2811519
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockConditionMissingSchemaUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* This test does not have a failed update but the configuration has missing
|
||||
* schema so can not do the full post update testing offered by
|
||||
* UpdatePathTestBase.
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @see \Drupal\system\Tests\Update\UpdatePathTestBase::runUpdates()
|
||||
*/
|
||||
protected $checkFailedUpdates = FALSE;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_test', 'language'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../tests/fixtures/update/drupal-8.block-test-enabled-missing-schema.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that block context mapping is updated properly.
|
||||
*/
|
||||
public function testUpdateHookN() {
|
||||
$this->runUpdates();
|
||||
$this->drupalGet('<front>');
|
||||
// If the block is fixed by block_post_update_fix_negate_in_conditions()
|
||||
// then it will be visible.
|
||||
$this->assertText('Test missing schema on conditions');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests\Update;
|
||||
|
||||
/**
|
||||
* Runs BlockContextMappingUpdateTest with a dump filled with content.
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockContextMappingUpdateFilledTest extends BlockContextMappingUpdateTest {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
parent::setDatabaseDumpFiles();
|
||||
$this->databaseDumpFiles[0] = __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.filled.standard.php.gz';
|
||||
}
|
||||
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests\Update;
|
||||
|
||||
use Drupal\block\Entity\Block;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests the upgrade path for block context mapping renames.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2354889
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockContextMappingUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_test', 'language'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-context-manager-2354889.php',
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.language-enabled.php',
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.block-test-enabled.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that block context mapping is updated properly.
|
||||
*/
|
||||
public function testUpdateHookN() {
|
||||
$this->runUpdates();
|
||||
$this->assertRaw('Encountered an unknown context mapping key coming probably from a contributed or custom module: One or more mappings could not be updated. Please manually review your visibility settings for the following blocks, which are disabled now:<ul><li>User login (Visibility: Baloney spam)</li></ul>');
|
||||
|
||||
// Disable maintenance mode.
|
||||
\Drupal::state()->set('system.maintenance_mode', FALSE);
|
||||
|
||||
// We finished updating so we can log in the user now.
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
// The block that we are testing has the following visibility rules:
|
||||
// - only visible on node pages
|
||||
// - only visible to authenticated users.
|
||||
$block_title = 'Test for 2354889';
|
||||
|
||||
// Create two nodes, a page and an article.
|
||||
$page = Node::create([
|
||||
'type' => 'page',
|
||||
'title' => 'Page node',
|
||||
]);
|
||||
$page->save();
|
||||
|
||||
$article = Node::create([
|
||||
'type' => 'article',
|
||||
'title' => 'Article node',
|
||||
]);
|
||||
$article->save();
|
||||
|
||||
// Check that the block appears only on Page nodes for authenticated users.
|
||||
$this->drupalGet('node/' . $page->id());
|
||||
$this->assertRaw($block_title, 'Test block is visible on a Page node as an authenticated user.');
|
||||
|
||||
$this->drupalGet('node/' . $article->id());
|
||||
$this->assertNoRaw($block_title, 'Test block is not visible on a Article node as an authenticated user.');
|
||||
|
||||
$this->drupalLogout();
|
||||
|
||||
// Check that the block does not appear on any page for anonymous users.
|
||||
$this->drupalGet('node/' . $page->id());
|
||||
$this->assertNoRaw($block_title, 'Test block is not visible on a Page node as an anonymous user.');
|
||||
|
||||
$this->drupalGet('node/' . $article->id());
|
||||
$this->assertNoRaw($block_title, 'Test block is not visible on a Article node as an anonymous user.');
|
||||
|
||||
// Ensure that all the context mappings got updated properly.
|
||||
$block = Block::load('testfor2354889');
|
||||
$visibility = $block->get('visibility');
|
||||
$this->assertEqual('@node.node_route_context:node', $visibility['node_type']['context_mapping']['node']);
|
||||
$this->assertEqual('@user.current_user_context:current_user', $visibility['user_role']['context_mapping']['user']);
|
||||
$this->assertEqual('@language.current_language_context:language_interface', $visibility['language']['context_mapping']['language']);
|
||||
|
||||
// Check that a block with invalid context is being disabled and that it can
|
||||
// still be edited afterward.
|
||||
$disabled_block = Block::load('thirdtestfor2354889');
|
||||
$this->assertFalse($disabled_block->status(), 'Block with invalid context is disabled');
|
||||
|
||||
$this->assertEqual(['thirdtestfor2354889' => ['missing_context_ids' => ['baloney_spam' => ['node_type']], 'status' => TRUE]], \Drupal::keyValue('update_backup')->get('block_update_8001'));
|
||||
|
||||
$disabled_block_visibility = $disabled_block->get('visibility');
|
||||
$this->assertTrue(!isset($disabled_block_visibility['node_type']), 'The problematic visibility condition has been removed.');
|
||||
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks']);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
$this->drupalGet('admin/structure/block/manage/thirdtestfor2354889');
|
||||
$this->assertResponse('200');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests\Update;
|
||||
|
||||
use Drupal\system\Tests\Update\UpdatePathTestBase;
|
||||
|
||||
/**
|
||||
* Tests the upgrade path for removal of disabled region.
|
||||
*
|
||||
* @see https://www.drupal.org/node/2513534
|
||||
*
|
||||
* @group Update
|
||||
*/
|
||||
class BlockRemoveDisabledRegionUpdateTest extends UpdatePathTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = ['block_test', 'language'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setDatabaseDumpFiles() {
|
||||
$this->databaseDumpFiles = [
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
|
||||
__DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.update-test-block-disabled-2513534.php',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that block context mapping is updated properly.
|
||||
*/
|
||||
public function testUpdateHookN() {
|
||||
$this->runUpdates();
|
||||
|
||||
// Disable maintenance mode.
|
||||
\Drupal::state()->set('system.maintenance_mode', FALSE);
|
||||
|
||||
// We finished updating so we can login the user now.
|
||||
$this->drupalLogin($this->rootUser);
|
||||
|
||||
// Verify that a disabled block is in the default region.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]",
|
||||
[':block' => 'edit-blocks-pagetitle-1', ':status' => 'block-disabled', ':region' => 'header']);
|
||||
$this->assertTrue(!empty($element));
|
||||
|
||||
// Verify that an enabled block is now disabled and in the default region.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$element = $this->xpath("//tr[contains(@data-drupal-selector, :block) and contains(@class, :status)]//select/option[@selected and @value=:region]",
|
||||
[':block' => 'edit-blocks-pagetitle-2', ':status' => 'block-disabled', ':region' => 'header']);
|
||||
$this->assertTrue(!empty($element));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,373 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\block\Tests\Views;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
|
||||
use Drupal\views\Entity\View;
|
||||
use Drupal\views\Views;
|
||||
use Drupal\views\Tests\ViewTestBase;
|
||||
use Drupal\views\Tests\ViewTestData;
|
||||
use Drupal\Core\Template\Attribute;
|
||||
|
||||
/**
|
||||
* Tests the block display plugin.
|
||||
*
|
||||
* @group block
|
||||
* @see \Drupal\block\Plugin\views\display\Block
|
||||
*/
|
||||
class DisplayBlockTest extends ViewTestBase {
|
||||
|
||||
use AssertPageCacheContextsAndTagsTrait;
|
||||
|
||||
/**
|
||||
* Modules to install.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'block_test_views', 'test_page_test', 'contextual', 'views_ui'];
|
||||
|
||||
/**
|
||||
* Views used by this test.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $testViews = ['test_view_block', 'test_view_block2'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
ViewTestData::createTestViews(get_class($this), ['block_test_views']);
|
||||
$this->enableViewsTestModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests default and custom block categories.
|
||||
*/
|
||||
public function testBlockCategory() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views', 'administer blocks']));
|
||||
|
||||
// Create a new view in the UI.
|
||||
$edit = [];
|
||||
$edit['label'] = $this->randomString();
|
||||
$edit['id'] = strtolower($this->randomMachineName());
|
||||
$edit['show[wizard_key]'] = 'standard:views_test_data';
|
||||
$edit['description'] = $this->randomString();
|
||||
$edit['block[create]'] = TRUE;
|
||||
$edit['block[style][row_plugin]'] = 'fields';
|
||||
$this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit'));
|
||||
|
||||
$pattern = '//tr[.//td[text()=:category] and .//td//a[contains(@href, :href)]]';
|
||||
|
||||
// Test that the block was given a default category corresponding to its
|
||||
// base table.
|
||||
$arguments = [
|
||||
':href' => \Drupal::Url('block.admin_add', [
|
||||
'plugin_id' => 'views_block:' . $edit['id'] . '-block_1',
|
||||
'theme' => 'classy',
|
||||
]),
|
||||
':category' => t('Lists (Views)'),
|
||||
];
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The test block appears in the category for its base table.');
|
||||
|
||||
// Duplicate the block before changing the category.
|
||||
$this->drupalPostForm('admin/structure/views/view/' . $edit['id'] . '/edit/block_1', [], t('Duplicate @display_title', ['@display_title' => 'Block']));
|
||||
$this->assertUrl('admin/structure/views/view/' . $edit['id'] . '/edit/block_2');
|
||||
|
||||
// Change the block category to a random string.
|
||||
$this->drupalGet('admin/structure/views/view/' . $edit['id'] . '/edit/block_1');
|
||||
$link = $this->xpath('//a[@id="views-block-1-block-category" and normalize-space(text())=:category]', $arguments);
|
||||
$this->assertTrue(!empty($link));
|
||||
$this->clickLink(t('Lists (Views)'));
|
||||
$category = $this->randomString();
|
||||
$this->drupalPostForm(NULL, ['block_category' => $category], t('Apply'));
|
||||
|
||||
// Duplicate the block after changing the category.
|
||||
$this->drupalPostForm(NULL, [], t('Duplicate @display_title', ['@display_title' => 'Block']));
|
||||
$this->assertUrl('admin/structure/views/view/' . $edit['id'] . '/edit/block_3');
|
||||
|
||||
$this->drupalPostForm(NULL, [], t('Save'));
|
||||
|
||||
// Test that the blocks are listed under the correct categories.
|
||||
$arguments[':category'] = $category;
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The test block appears in the custom category.');
|
||||
|
||||
$arguments = [
|
||||
':href' => \Drupal::Url('block.admin_add', [
|
||||
'plugin_id' => 'views_block:' . $edit['id'] . '-block_2',
|
||||
'theme' => 'classy',
|
||||
]),
|
||||
':category' => t('Lists (Views)'),
|
||||
];
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The first duplicated test block remains in the original category.');
|
||||
|
||||
$arguments = [
|
||||
':href' => \Drupal::Url('block.admin_add', [
|
||||
'plugin_id' => 'views_block:' . $edit['id'] . '-block_3',
|
||||
'theme' => 'classy',
|
||||
]),
|
||||
':category' => $category,
|
||||
];
|
||||
$elements = $this->xpath($pattern, $arguments);
|
||||
$this->assertTrue(!empty($elements), 'The second duplicated test block appears in the custom category.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests removing a block display.
|
||||
*/
|
||||
public function testDeleteBlockDisplay() {
|
||||
// To test all combinations possible we first place create two instances
|
||||
// of the block display of the first view.
|
||||
$block_1 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1']);
|
||||
$block_2 = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:2']);
|
||||
|
||||
// Then we add one instance of blocks for each of the two displays of the
|
||||
// second view.
|
||||
$block_3 = $this->drupalPlaceBlock('views_block:test_view_block2-block_1', ['label' => 'test_view_block2-block_1']);
|
||||
$block_4 = $this->drupalPlaceBlock('views_block:test_view_block2-block_2', ['label' => 'test_view_block2-block_2']);
|
||||
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertBlockAppears($block_1);
|
||||
$this->assertBlockAppears($block_2);
|
||||
$this->assertBlockAppears($block_3);
|
||||
$this->assertBlockAppears($block_4);
|
||||
|
||||
$block_storage = $this->container->get('entity_type.manager')->getStorage('block');
|
||||
|
||||
// Remove the block display, so both block entities from the first view
|
||||
// should both disappear.
|
||||
$view = Views::getView('test_view_block');
|
||||
$view->initDisplay();
|
||||
$view->displayHandlers->remove('block_1');
|
||||
$view->storage->save();
|
||||
|
||||
$this->assertFalse($block_storage->load($block_1->id()), 'The block for this display was removed.');
|
||||
$this->assertFalse($block_storage->load($block_2->id()), 'The block for this display was removed.');
|
||||
$this->assertTrue($block_storage->load($block_3->id()), 'A block from another view was unaffected.');
|
||||
$this->assertTrue($block_storage->load($block_4->id()), 'A block from another view was unaffected.');
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertNoBlockAppears($block_1);
|
||||
$this->assertNoBlockAppears($block_2);
|
||||
$this->assertBlockAppears($block_3);
|
||||
$this->assertBlockAppears($block_4);
|
||||
|
||||
// Remove the first block display of the second view and ensure the block
|
||||
// instance of the second block display still exists.
|
||||
$view = Views::getView('test_view_block2');
|
||||
$view->initDisplay();
|
||||
$view->displayHandlers->remove('block_1');
|
||||
$view->storage->save();
|
||||
|
||||
$this->assertFalse($block_storage->load($block_3->id()), 'The block for this display was removed.');
|
||||
$this->assertTrue($block_storage->load($block_4->id()), 'A block from another display on the same view was unaffected.');
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertNoBlockAppears($block_3);
|
||||
$this->assertBlockAppears($block_4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the block form for a Views block.
|
||||
*/
|
||||
public function testViewsBlockForm() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer blocks']));
|
||||
$default_theme = $this->config('system.theme')->get('default');
|
||||
$this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme);
|
||||
$elements = $this->xpath('//input[@name="label"]');
|
||||
$this->assertTrue(empty($elements), 'The label field is not found for Views blocks.');
|
||||
// Test that that machine name field is hidden from display and has been
|
||||
// saved as expected from the default value.
|
||||
$this->assertNoFieldById('edit-machine-name', 'views_block__test_view_block_1', 'The machine name is hidden on the views block form.');
|
||||
|
||||
// Save the block.
|
||||
$edit = ['region' => 'content'];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save block'));
|
||||
$storage = $this->container->get('entity_type.manager')->getStorage('block');
|
||||
$block = $storage->load('views_block__test_view_block_block_1');
|
||||
// This will only return a result if our new block has been created with the
|
||||
// expected machine name.
|
||||
$this->assertTrue(!empty($block), 'The expected block was loaded.');
|
||||
|
||||
for ($i = 2; $i <= 3; $i++) {
|
||||
// Place the same block again and make sure we have a new ID.
|
||||
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
|
||||
$block = $storage->load('views_block__test_view_block_block_1_' . $i);
|
||||
// This will only return a result if our new block has been created with the
|
||||
// expected machine name.
|
||||
$this->assertTrue(!empty($block), 'The expected block was loaded.');
|
||||
}
|
||||
|
||||
// Tests the override capability of items per page.
|
||||
$this->drupalGet('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme);
|
||||
$edit = ['region' => 'content'];
|
||||
$edit['settings[override][items_per_page]'] = 10;
|
||||
|
||||
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
|
||||
|
||||
$block = $storage->load('views_block__test_view_block_block_1_4');
|
||||
$config = $block->getPlugin()->getConfiguration();
|
||||
$this->assertEqual(10, $config['items_per_page'], "'Items per page' is properly saved.");
|
||||
|
||||
$edit['settings[override][items_per_page]'] = 5;
|
||||
$this->drupalPostForm('admin/structure/block/manage/views_block__test_view_block_block_1_4', $edit, t('Save block'));
|
||||
|
||||
$block = $storage->load('views_block__test_view_block_block_1_4');
|
||||
|
||||
$config = $block->getPlugin()->getConfiguration();
|
||||
$this->assertEqual(5, $config['items_per_page'], "'Items per page' is properly saved.");
|
||||
|
||||
// Tests the override of the label capability.
|
||||
$edit = ['region' => 'content'];
|
||||
$edit['settings[views_label_checkbox]'] = 1;
|
||||
$edit['settings[views_label]'] = 'Custom title';
|
||||
$this->drupalPostForm('admin/structure/block/add/views_block:test_view_block-block_1/' . $default_theme, $edit, t('Save block'));
|
||||
|
||||
$block = $storage->load('views_block__test_view_block_block_1_5');
|
||||
$config = $block->getPlugin()->getConfiguration();
|
||||
$this->assertEqual('Custom title', $config['views_label'], "'Label' is properly saved.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the actual rendering of the views block.
|
||||
*/
|
||||
public function testBlockRendering() {
|
||||
// Create a block and set a custom title.
|
||||
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1', 'views_label' => 'Custom title']);
|
||||
$this->drupalGet('');
|
||||
|
||||
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
|
||||
$this->assertEqual((string) $result[0], 'Custom title');
|
||||
|
||||
// Don't override the title anymore.
|
||||
$plugin = $block->getPlugin();
|
||||
$plugin->setConfigurationValue('views_label', '');
|
||||
$block->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
|
||||
$this->assertEqual((string) $result[0], 'test_view_block');
|
||||
|
||||
// Hide the title.
|
||||
$block->getPlugin()->setConfigurationValue('label_display', FALSE);
|
||||
$block->save();
|
||||
|
||||
$this->drupalGet('');
|
||||
$result = $this->xpath('//div[contains(@class, "region-sidebar-first")]/div[contains(@class, "block-views")]/h2');
|
||||
$this->assertTrue(empty($result), 'The title is not visible.');
|
||||
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:system.site', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the various testcases of empty block rendering.
|
||||
*/
|
||||
public function testBlockEmptyRendering() {
|
||||
$url = new Url('test_page_test.test_page');
|
||||
// Remove all views_test_data entries.
|
||||
\Drupal::database()->truncate('views_test_data')->execute();
|
||||
/** @var \Drupal\views\ViewEntityInterface $view */
|
||||
$view = View::load('test_view_block');
|
||||
$view->invalidateCaches();
|
||||
|
||||
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1', ['label' => 'test_view_block-block_1:1', 'views_label' => 'Custom title']);
|
||||
$this->drupalGet('');
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['block_hide_empty'] = TRUE;
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
// Ensure that the view cachability metadata is propagated even, for an
|
||||
// empty block.
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Add a header displayed on empty result.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['header'] = FALSE;
|
||||
$display['display_options']['header']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test header',
|
||||
'empty' => TRUE,
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block' , 'http_response', 'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Hide the header on empty results.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['header'] = FALSE;
|
||||
$display['display_options']['header']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test header',
|
||||
'empty' => FALSE,
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(0, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
|
||||
// Add an empty text.
|
||||
$display = &$view->getDisplay('block_1');
|
||||
$display['display_options']['defaults']['empty'] = FALSE;
|
||||
$display['display_options']['empty']['example'] = [
|
||||
'field' => 'area_text_custom',
|
||||
'id' => 'area_text_custom',
|
||||
'table' => 'views',
|
||||
'plugin_id' => 'text_custom',
|
||||
'content' => 'test empty',
|
||||
];
|
||||
$view->save();
|
||||
|
||||
$this->drupalGet($url);
|
||||
$this->assertEqual(1, count($this->xpath('//div[contains(@class, "block-views-blocktest-view-block-block-1")]')));
|
||||
$this->assertCacheTags(array_merge($block->getCacheTags(), ['block_view', 'config:block_list', 'config:views.view.test_view_block', 'http_response', 'rendered']));
|
||||
$this->assertCacheContexts(['url.query_args:_wrapper_format']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the contextual links on a Views block.
|
||||
*/
|
||||
public function testBlockContextualLinks() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer views', 'access contextual links', 'administer blocks']));
|
||||
$block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
|
||||
$cached_block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
|
||||
$this->drupalGet('test-page');
|
||||
|
||||
$id = 'block:block=' . $block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
|
||||
$cached_id = 'block:block=' . $cached_block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
|
||||
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
|
||||
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $id]));
|
||||
$this->assertRaw('<div' . new Attribute(['data-contextual-id' => $cached_id]) . '></div>', format_string('Contextual link placeholder with id @id exists.', ['@id' => $cached_id]));
|
||||
|
||||
// Get server-rendered contextual links.
|
||||
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:renderContextualLinks()
|
||||
$post = ['ids[0]' => $id, 'ids[1]' => $cached_id];
|
||||
$response = $this->drupalPostWithFormat('contextual/render', 'json', $post, ['query' => ['destination' => 'test-page']]);
|
||||
$this->assertResponse(200);
|
||||
$json = Json::decode($response);
|
||||
$this->assertIdentical($json[$id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
|
||||
$this->assertIdentical($json[$cached_id], '<ul class="contextual-links"><li class="block-configure"><a href="' . base_path() . 'admin/structure/block/manage/' . $cached_block->id() . '">Configure block</a></li><li class="entityviewedit-form"><a href="' . base_path() . 'admin/structure/views/view/test_view_block/edit/block_1">Edit view</a></li></ul>');
|
||||
}
|
||||
|
||||
}
|
Reference in a new issue