diff --git a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php index 2f250ba..279ef0f 100644 --- a/core/lib/Drupal/Core/Condition/ConditionPluginBase.php +++ b/core/lib/Drupal/Core/Condition/ConditionPluginBase.php @@ -37,7 +37,7 @@ public function buildConfigurationForm(array $form, array &$form_state) { $form['negate'] = array( '#type' => 'checkbox', '#title' => $this->t('Negate the condition.'), - '#default_value' => isset($this->configuration['negate']) ? $this->configuration['negate'] : FALSE, + '#default_value' => $this->configuration['negate'], ); return $form; } @@ -83,7 +83,9 @@ public function setConfiguration(array $configuration) { * {@inheritdoc} */ public function defaultConfiguration() { - return array(); + return array( + 'negate' => FALSE, + ); } /** diff --git a/core/modules/block/block.module b/core/modules/block/block.module index ceffa1f..db363dd 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -12,22 +12,6 @@ use Symfony\Component\HttpFoundation\Request; /** - * Shows this block on every page except the listed pages. - */ -const BLOCK_VISIBILITY_NOTLISTED = 0; - -/** - * Shows this block on only the listed pages. - */ -const BLOCK_VISIBILITY_LISTED = 1; - -/** - * Shows this block if the associated PHP code returns TRUE. - */ -const BLOCK_VISIBILITY_PHP = 2; - - -/** * Implements hook_help(). */ function block_help($route_name, Request $request) { @@ -391,10 +375,12 @@ function template_preprocess_block(&$variables) { */ function block_user_role_delete($role) { foreach (entity_load_multiple('block') as $block) { - $visibility = $block->get('visibility'); + /** @var $block \Drupal\block\BlockInterface */ + $visibility_conditions = $block->getPlugin()->getVisibilityConditions(); + $visibility = $visibility_conditions->getConfiguration(); if (isset($visibility['roles']['roles'][$role->id()])) { unset($visibility['roles']['roles'][$role->id()]); - $block->set('visibility', $visibility); + $visibility_conditions->setConfiguration($visibility); $block->save(); } } @@ -421,10 +407,12 @@ function block_menu_delete(Menu $menu) { function block_language_entity_delete(Language $language) { // Remove the block visibility settings for the deleted language. foreach (entity_load_multiple('block') as $block) { - $visibility = $block->get('visibility'); + /** @var $block \Drupal\block\BlockInterface */ + $visibility_conditions = $block->getPlugin()->getVisibilityConditions(); + $visibility = $visibility_conditions->getConfiguration(); if (isset($visibility['language']['langcodes'][$language->id()])) { unset($visibility['language']['langcodes'][$language->id()]); - $block->set('visibility', $visibility); + $visibility_conditions->setConfiguration($visibility); $block->save(); } } diff --git a/core/modules/block/src/BlockAccessController.php b/core/modules/block/src/BlockAccessController.php index 3bd9fb3..0089470 100644 --- a/core/modules/block/src/BlockAccessController.php +++ b/core/modules/block/src/BlockAccessController.php @@ -8,53 +8,19 @@ namespace Drupal\block; use Drupal\Core\Entity\EntityAccessController; -use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Session\AccountInterface; -use Drupal\Core\Path\AliasManagerInterface; -use Drupal\Component\Utility\Unicode; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides a Block access controller. */ -class BlockAccessController extends EntityAccessController implements EntityControllerInterface { - - /** - * The node grant storage. - * - * @var \Drupal\Core\Path\AliasManagerInterface - */ - protected $aliasManager; - - /** - * Constructs a BlockAccessController object. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type definition. - * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager - * The alias manager. - */ - public function __construct(EntityTypeInterface $entity_type, AliasManagerInterface $alias_manager) { - parent::__construct($entity_type); - $this->aliasManager = $alias_manager; - } - - /** - * {@inheritdoc} - */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static( - $entity_type, - $container->get('path.alias_manager') - ); - } +class BlockAccessController extends EntityAccessController { /** * {@inheritdoc} */ protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) { + /** @var $entity \Drupal\block\BlockInterface */ if ($operation != 'view') { return parent::checkAccess($entity, $operation, $langcode, $account); } @@ -64,65 +30,8 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return FALSE; } - // User role access handling. - // If a block has no roles associated, it is displayed for every role. - // For blocks with roles associated, if none of the user's roles matches - // the settings from this block, access is denied. - $visibility = $entity->get('visibility'); - if (!empty($visibility['role']['roles']) && !array_intersect(array_filter($visibility['role']['roles']), $account->getRoles())) { - // No match. - return FALSE; - } - - // Page path handling. - // Limited visibility blocks must list at least one page. - if (!empty($visibility['path']['visibility']) && $visibility['path']['visibility'] == BLOCK_VISIBILITY_LISTED && empty($visibility['path']['pages'])) { - return FALSE; - } - - // Match path if necessary. - if (!empty($visibility['path']['pages'])) { - // Assume there are no matches until one is found. - $page_match = FALSE; - - // Convert path to lowercase. This allows comparison of the same path - // with different case. Ex: /Page, /page, /PAGE. - $pages = drupal_strtolower($visibility['path']['pages']); - if ($visibility['path']['visibility'] < BLOCK_VISIBILITY_PHP) { - // Compare the lowercase path alias (if any) and internal path. - $path = current_path(); - $path_alias = Unicode::strtolower($this->aliasManager->getAliasByPath($path)); - $page_match = drupal_match_path($path_alias, $pages) || (($path != $path_alias) && drupal_match_path($path, $pages)); - // When $block->visibility has a value of 0 - // (BLOCK_VISIBILITY_NOTLISTED), the block is displayed on all pages - // except those listed in $block->pages. When set to 1 - // (BLOCK_VISIBILITY_LISTED), it is displayed only on those pages - // listed in $block->pages. - $page_match = !($visibility['path']['visibility'] xor $page_match); - } - - // If there are page visibility restrictions and this page does not - // match, deny access. - if (!$page_match) { - return FALSE; - } - } - - // Language visibility settings. - if (!empty($visibility['language']['langcodes']) && array_filter($visibility['language']['langcodes'])) { - if (empty($visibility['language']['langcodes'][\Drupal::languageManager()->getCurrentLanguage($visibility['language']['language_type'])->id])) { - return FALSE; - } - } - - // If the plugin denies access, then deny access. Apply plugin access checks - // last, because it's almost certainly cheaper to first apply Block's own - // visibility checks. - if (!$entity->getPlugin()->access($account)) { - return FALSE; - } - - return TRUE; + // Delegate to the plugin. + return $entity->getPlugin()->access($account); } } diff --git a/core/modules/block/src/BlockBase.php b/core/modules/block/src/BlockBase.php index 6e96d98..d4b5ee1 100644 --- a/core/modules/block/src/BlockBase.php +++ b/core/modules/block/src/BlockBase.php @@ -76,7 +76,7 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition */ public function getConfiguration() { return array( - 'visibility' => $this->getConditions()->getConfiguration(), + 'visibility' => $this->getVisibilityConditions()->getConfiguration(), ) + $this->configuration; } @@ -150,7 +150,7 @@ public function calculateDependencies() { * {@inheritdoc} */ public function access(AccountInterface $account) { - if ($this->resolveConditions($this->getConditions(), 'and', $this->getConditionContexts()) === FALSE) { + if ($this->resolveConditions($this->getVisibilityConditions(), 'and', $this->getConditionContexts()) === FALSE) { return FALSE; } return $this->blockAccess($account); @@ -171,6 +171,14 @@ protected function getConditionContexts() { $context->setContextValue(User::load(\Drupal::currentUser()->id())); $contexts['user'] = $context; + $language = \Drupal::languageManager()->getCurrentLanguage(); + $context = new Context(array( + 'type' => 'language', + 'label' => $this->t('Current language'), + )); + $context->setContextValue($language); + $contexts['language'] = $context; + // @todo Use RouteMatch after https://drupal.org/node/2238217. $request = \Drupal::request(); if ($request->attributes->has(RouteObjectInterface::ROUTE_OBJECT) && $route_contexts = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)->getOption('parameters')) { @@ -284,18 +292,15 @@ public function buildConfigurationForm(array $form, array &$form_state) { $form['cache']['contexts']['#description'] .= ' ' . t('This block is always varied by the following contexts: %required-context-list.', array('%required-context-list' => $required_context_list)); } + // @todo Use vertical tabs here. $form['visibility'] = array( - '#type' => 'vertical_tabs', + '#type' => 'fieldgroup', '#title' => $this->t('Visibility'), ); - foreach ($this->getConditions() as $condition_id => $condition) { - $form['visibility'][$condition_id] = array( - '#type' => 'details', - '#title' => $condition->getPluginDefinition()['label'], - '#group' => 'visibility', - ); - $form['visibility'][$condition_id]['form'] = $condition->buildConfigurationForm(array(), $form_state); - $form['visibility'][$condition_id]['form']['#process'][] = array($this, 'processVisibilityForm'); + foreach ($this->getVisibilityConditions() as $condition_id => $condition) { + $form['visibility'][$condition_id] = $condition->buildConfigurationForm(array(), $form_state); + $form['visibility'][$condition_id]['#type'] = 'details'; + $form['visibility'][$condition_id]['#title'] = $condition->getPluginDefinition()['label']; } // Add plugin-specific settings for this block type. $form += $this->blockForm($form, $form_state); @@ -303,15 +308,6 @@ public function buildConfigurationForm(array $form, array &$form_state) { } /** - * @todo. - */ - public function processVisibilityForm($element) { - // Remove the 'form' from parents. - array_pop($element['#parents']); - return $element; - } - - /** * {@inheritdoc} */ public function blockForm($form, &$form_state) { @@ -330,7 +326,7 @@ public function validateConfigurationForm(array &$form, array &$form_state) { // Transform the #type = checkboxes value to a numerically indexed array. $form_state['values']['cache']['contexts'] = array_values(array_filter($form_state['values']['cache']['contexts'])); - foreach ($this->getConditions() as $condition_id => $condition) { + foreach ($this->getVisibilityConditions() as $condition_id => $condition) { // Allow the condition to validate the form. $condition_values = array( 'values' => &$form_state['values']['visibility'][$condition_id], @@ -362,7 +358,7 @@ public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['label_display'] = $form_state['values']['label_display']; $this->configuration['provider'] = $form_state['values']['provider']; $this->configuration['cache'] = $form_state['values']['cache']; - foreach ($this->getConditions() as $condition_id => $condition) { + foreach ($this->getVisibilityConditions() as $condition_id => $condition) { // Allow the condition to submit the form. $condition_values = array( 'values' => &$form_state['values']['visibility'][$condition_id], @@ -458,12 +454,9 @@ public function isCacheable() { } /** - * Gets conditions for this block. - * - * @return \Drupal\Core\Condition\ConditionInterface[]|\Drupal\Core\Condition\ConditionPluginBag - * An array of configured condition plugins. + * {@inheritdoc} */ - public function getConditions() { + public function getVisibilityConditions() { if (!isset($this->conditionBag)) { $this->conditionBag = new ConditionPluginBag($this->conditionPluginManager(), $this->configuration['visibility']); } @@ -471,28 +464,18 @@ public function getConditions() { } /** - * Gets a condition plugin instance. - * - * @param string $instance_id - * The condition plugin instance ID. - * - * @return \Drupal\Core\Condition\ConditionInterface - * A condition plugin. + * {@inheritdoc} */ - public function getCondition($instance_id) { - return $this->getConditions()->get($instance_id); + public function getVisibilityCondition($instance_id) { + return $this->getVisibilityConditions()->get($instance_id); } /** - * Sets the condition configuration. - * - * @param string $instance_id - * The condition instance ID. - * @param array $config - * The condition configuration. + * {@inheritdoc} */ - public function setConditionConfig($instance_id, $config) { - $this->getConditions()->setInstanceConfiguration($instance_id, $config); + public function setVisibilityConfig($instance_id, array $configuration) { + $this->getVisibilityConditions()->setInstanceConfiguration($instance_id, $configuration); + return $this; } /** diff --git a/core/modules/block/src/BlockForm.php b/core/modules/block/src/BlockForm.php index 866f1b8..af8641c 100644 --- a/core/modules/block/src/BlockForm.php +++ b/core/modules/block/src/BlockForm.php @@ -10,9 +10,6 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Language\LanguageInterface; -use Drupal\Core\Language\LanguageManagerInterface; -use Drupal\language\ConfigurableLanguageManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -35,23 +32,13 @@ class BlockForm extends EntityForm { protected $storage; /** - * The language manager. - * - * @var \Drupal\Core\Language\LanguageManagerInterface - */ - protected $languageManager; - - /** * Constructs a BlockForm object. * * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. - * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager - * The language manager. */ - public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager) { + public function __construct(EntityManagerInterface $entity_manager) { $this->storage = $entity_manager->getStorage('block'); - $this->languageManager = $language_manager; } /** @@ -59,8 +46,7 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana */ public static function create(ContainerInterface $container) { return new static( - $container->get('entity.manager'), - $container->get('language_manager') + $container->get('entity.manager') ); } @@ -94,122 +80,6 @@ public function form(array $form, array &$form_state) { '#disabled' => !$entity->isNew(), ); - // Visibility settings. - $form['visibility'] = array( - '#type' => 'vertical_tabs', - '#title' => $this->t('Visibility settings'), - '#attached' => array( - 'library' => array( - 'block/drupal.block', - ), - ), - '#tree' => TRUE, - '#weight' => 10, - '#parents' => array('visibility'), - ); - - // Per-path visibility. - $form['visibility']['path'] = array( - '#type' => 'details', - '#title' => $this->t('Pages'), - '#group' => 'visibility', - '#weight' => 0, - ); - - // @todo remove this access check and inject it in some other way. In fact - // this entire visibility settings section probably needs a separate user - // interface in the near future. - $visibility = $entity->get('visibility'); - $access = $this->currentUser()->hasPermission('use PHP for settings'); - if (!empty($visibility['path']['visibility']) && $visibility['path']['visibility'] == BLOCK_VISIBILITY_PHP && !$access) { - $form['visibility']['path']['visibility'] = array( - '#type' => 'value', - '#value' => BLOCK_VISIBILITY_PHP, - ); - $form['visibility']['path']['pages'] = array( - '#type' => 'value', - '#value' => !empty($visibility['path']['pages']) ? $visibility['path']['pages'] : '', - ); - } - else { - $options = array( - BLOCK_VISIBILITY_NOTLISTED => $this->t('All pages except those listed'), - BLOCK_VISIBILITY_LISTED => $this->t('Only the listed pages'), - ); - $description = $this->t("Specify pages by using their paths. Enter one path per line. The '*' character is a wildcard. Example paths are %user for the current user's page and %user-wildcard for every user page. %front is the front page.", array('%user' => 'user', '%user-wildcard' => 'user/*', '%front' => '')); - - $form['visibility']['path']['visibility'] = array( - '#type' => 'radios', - '#title' => $this->t('Show block on specific pages'), - '#options' => $options, - '#default_value' => !empty($visibility['path']['visibility']) ? $visibility['path']['visibility'] : BLOCK_VISIBILITY_NOTLISTED, - ); - $form['visibility']['path']['pages'] = array( - '#type' => 'textarea', - '#title' => '' . $this->t('Pages') . '', - '#default_value' => !empty($visibility['path']['pages']) ? $visibility['path']['pages'] : '', - '#description' => $description, - ); - } - - // Configure the block visibility per language. - if ($this->languageManager->isMultilingual() && $this->languageManager instanceof ConfigurableLanguageManagerInterface) { - $language_types = $this->languageManager->getLanguageTypes(); - - // Fetch languages. - $languages = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL); - $langcodes_options = array(); - foreach ($languages as $language) { - // @todo $language->name is not wrapped with t(), it should be replaced - // by CMI translation implementation. - $langcodes_options[$language->id] = $language->name; - } - $form['visibility']['language'] = array( - '#type' => 'details', - '#title' => $this->t('Languages'), - '#group' => 'visibility', - '#weight' => 5, - ); - // If there are multiple configurable language types, let the user pick - // which one should be applied to this visibility setting. This way users - // can limit blocks by interface language or content language for example. - $info = $this->languageManager->getDefinedLanguageTypesInfo(); - $language_type_options = array(); - foreach ($language_types as $type_key) { - $language_type_options[$type_key] = $info[$type_key]['name']; - } - $form['visibility']['language']['language_type'] = array( - '#type' => 'radios', - '#title' => $this->t('Language type'), - '#options' => $language_type_options, - '#default_value' => !empty($visibility['language']['language_type']) ? $visibility['language']['language_type'] : reset($language_types), - '#access' => count($language_type_options) > 1, - ); - $form['visibility']['language']['langcodes'] = array( - '#type' => 'checkboxes', - '#title' => $this->t('Show this block only for specific languages'), - '#default_value' => !empty($visibility['language']['langcodes']) ? $visibility['language']['langcodes'] : array(), - '#options' => $langcodes_options, - '#description' => $this->t('Show this block only for the selected language(s). If you select no languages, the block will be visible in all languages.'), - ); - } - - // Per-role visibility. - $role_options = array_map('check_plain', user_role_names()); - $form['visibility']['role'] = array( - '#type' => 'details', - '#title' => $this->t('Roles'), - '#group' => 'visibility', - '#weight' => 10, - ); - $form['visibility']['role']['roles'] = array( - '#type' => 'checkboxes', - '#title' => $this->t('Show block for specific roles'), - '#default_value' => !empty($visibility['role']['roles']) ? $visibility['role']['roles'] : array(), - '#options' => $role_options, - '#description' => $this->t('Show this block only for the selected role(s). If you select no roles, the block will be visible to all users.'), - ); - // Theme settings. if ($entity->get('theme')) { $form['theme'] = array( @@ -276,8 +146,6 @@ protected function actions(array $form, array &$form_state) { public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); - // Remove empty lines from the role visibility list. - $form_state['values']['visibility']['role']['roles'] = array_filter($form_state['values']['visibility']['role']['roles']); // The Block Entity form puts all block plugin form elements in the // settings form element, so just pass that to the block for validation. $settings = array( @@ -324,21 +192,6 @@ public function submit(array $form, array &$form_state) { } /** - * {@inheritdoc} - */ - public function buildEntity(array $form, array &$form_state) { - $entity = parent::buildEntity($form, $form_state); - - // visibility__active_tab is Form API state and not configuration. - // @todo Fix vertical tabs. - $visibility = $entity->get('visibility'); - unset($visibility['visibility__active_tab']); - $entity->set('visibility', $visibility); - - return $entity; - } - - /** * Generates a unique machine name for a block. * * @param \Drupal\block\BlockInterface $block diff --git a/core/modules/block/src/BlockPluginInterface.php b/core/modules/block/src/BlockPluginInterface.php index f45ecc5..58ecc8c 100644 --- a/core/modules/block/src/BlockPluginInterface.php +++ b/core/modules/block/src/BlockPluginInterface.php @@ -140,4 +140,35 @@ public function blockSubmit($form, &$form_state); */ public function getMachineNameSuggestion(); + /** + * Gets conditions for this block. + * + * @return \Drupal\Core\Condition\ConditionInterface[]|\Drupal\Core\Condition\ConditionPluginBag + * An array of configured condition plugins. + */ + public function getVisibilityConditions(); + + /** + * Gets a visibility condition plugin instance. + * + * @param string $instance_id + * The condition plugin instance ID. + * + * @return \Drupal\Core\Condition\ConditionInterface + * A condition plugin. + */ + public function getVisibilityCondition($instance_id); + + /** + * Sets the visibility condition configuration. + * + * @param string $instance_id + * The condition instance ID. + * @param array $configuration + * The condition configuration. + * + * @return $this + */ + public function setVisibilityConfig($instance_id, array $configuration); + } diff --git a/core/modules/block/src/Entity/Block.php b/core/modules/block/src/Entity/Block.php index de6c971..d11347a 100644 --- a/core/modules/block/src/Entity/Block.php +++ b/core/modules/block/src/Entity/Block.php @@ -87,13 +87,6 @@ class Block extends ConfigEntityBase implements BlockInterface, EntityWithPlugin protected $pluginBag; /** - * The visibility settings. - * - * @var array - */ - protected $visibility; - - /** * {@inheritdoc} */ public function getPlugin() { @@ -145,7 +138,6 @@ public function toArray() { 'weight', 'plugin', 'settings', - 'visibility', ); foreach ($names as $name) { $properties[$name] = $this->get($name); diff --git a/core/modules/block/src/Tests/BlockInterfaceTest.php b/core/modules/block/src/Tests/BlockInterfaceTest.php index 525251e..35df3e8 100644 --- a/core/modules/block/src/Tests/BlockInterfaceTest.php +++ b/core/modules/block/src/Tests/BlockInterfaceTest.php @@ -48,10 +48,12 @@ public function testBlockInterface() { 'request_path' => array( 'id' => 'request_path', 'pages' => '', + 'negate' => FALSE, ), 'user_role' => array( 'id' => 'user_role', 'roles' => array(), + 'negate' => FALSE, ), ), 'id' => 'test_block_instantiation', diff --git a/core/modules/block/src/Tests/BlockLanguageTest.php b/core/modules/block/src/Tests/BlockLanguageTest.php index 246e92c..a3a1837 100644 --- a/core/modules/block/src/Tests/BlockLanguageTest.php +++ b/core/modules/block/src/Tests/BlockLanguageTest.php @@ -57,11 +57,11 @@ public function testLanguageBlockVisibility() { $default_theme = \Drupal::config('system.theme')->get('default'); $this->drupalGet('admin/structure/block/add/system_powered_by_block' . '/' . $default_theme); - $this->assertField('visibility[language][langcodes][en]', 'Language visibility field is visible.'); + $this->assertField('settings[visibility][language][langcodes][en]', 'Language visibility field is visible.'); // Enable a standard block and set the visibility setting for one language. $edit = array( - 'visibility[language][langcodes][en]' => TRUE, + 'settings[visibility][language][langcodes][en]' => TRUE, 'id' => strtolower($this->randomName(8)), 'region' => 'sidebar_first', ); @@ -100,7 +100,7 @@ public function testLanguageBlockVisibilityLanguageDelete() { $block = $this->drupalPlaceBlock('system_powered_by_block', $edit); // Check that we have the language in config after saving the setting. - $visibility = $block->get('visibility'); + $visibility = $block->getPlugin()->getVisibilityConditions()->getConfiguration(); $language = $visibility['language']['langcodes']['fr']; $this->assertTrue('fr' === $language, 'Language is set in the block configuration.'); @@ -110,7 +110,7 @@ public function testLanguageBlockVisibilityLanguageDelete() { // Check that the language is no longer stored in the configuration after // it is deleted. $block = entity_load('block', $block->id()); - $visibility = $block->get('visibility'); + $visibility = $block->getPlugin()->getVisibilityConditions()->getConfiguration(); $this->assertTrue(empty($visibility['language']['langcodes']['fr']), 'Language is no longer not set in the block configuration after deleting the block.'); } diff --git a/core/modules/block/src/Tests/BlockStorageUnitTest.php b/core/modules/block/src/Tests/BlockStorageUnitTest.php index 106e220..60cbf94 100644 --- a/core/modules/block/src/Tests/BlockStorageUnitTest.php +++ b/core/modules/block/src/Tests/BlockStorageUnitTest.php @@ -103,6 +103,7 @@ protected function createTests() { 'request_path' => array( 'id' => 'request_path', 'pages' => '', + 'negate' => FALSE, ), ), 'id' => 'test_html', @@ -114,7 +115,6 @@ protected function createTests() { 'contexts' => array(), ), ), - 'visibility' => NULL, ); $this->assertIdentical($actual_properties, $expected_properties); diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php index 882863d..741fab1 100644 --- a/core/modules/block/src/Tests/BlockTest.php +++ b/core/modules/block/src/Tests/BlockTest.php @@ -40,8 +40,9 @@ function testBlockVisibility() { ); // Set the block to be hidden on any user path, and to be shown only to // authenticated users. - $edit['visibility[path][pages]'] = 'user*'; - $edit['visibility[role][roles][' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE; + $edit['settings[visibility][request_path][pages]'] = 'user*'; + $edit['settings[visibility][request_path][negate]'] = TRUE; + $edit['settings[visibility][user_role][roles][' . DRUPAL_AUTHENTICATED_RID . ']'] = TRUE; $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'); @@ -65,8 +66,7 @@ function testBlockVisibility() { } /** - * Test block visibility when using "pages" restriction but leaving - * "pages" textarea empty + * Test block visibility when leaving "pages" textarea empty. */ function testBlockVisibilityListedEmpty() { $block_name = 'system_powered_by_block'; @@ -78,7 +78,7 @@ function testBlockVisibilityListedEmpty() { 'id' => strtolower($this->randomName(8)), 'region' => 'sidebar_first', 'settings[label]' => $title, - 'visibility[path][visibility]' => BLOCK_VISIBILITY_LISTED, + 'settings[visibility][request_path][negate]' => TRUE, ); // Set the block to be hidden on any user path, and to be shown only to // authenticated users. diff --git a/core/modules/block/tests/modules/block_test/config/install/block.block.test_block.yml b/core/modules/block/tests/modules/block_test/config/install/block.block.test_block.yml index ee49c91..ea4a909 100644 --- a/core/modules/block/tests/modules/block_test/config/install/block.block.test_block.yml +++ b/core/modules/block/tests/modules/block_test/config/install/block.block.test_block.yml @@ -10,11 +10,6 @@ settings: request_path: id: request_path pages: '' - user_role: - id: user_role - roles: { } - node_type: - id: node_type label: 'Test HTML block' provider: block_test label_display: 'hidden' diff --git a/core/modules/block/tests/src/BlockBaseTest.php b/core/modules/block/tests/src/BlockBaseTest.php index 682fe09..6fddb58 100644 --- a/core/modules/block/tests/src/BlockBaseTest.php +++ b/core/modules/block/tests/src/BlockBaseTest.php @@ -86,19 +86,19 @@ public function testCondtionsBagInitialisation() { $plugin_manager = $this->getMock('Drupal\Core\Executable\ExecutableManagerInterface'); $block_base = new FakeBlock($plugin_manager, $config, 'test_block_instantiation', $definition); - $conditions_bag = $block_base->getConditions(); + $conditions_bag = $block_base->getVisibilityConditions(); $this->assertEquals(4, $conditions_bag->count(), "There are 4 condition plugins"); $instance_id = $this->randomName(); $pages = 'node/1'; $condition_config = array('id' => 'request_path', 'pages' => $pages); - $block_base->setConditionConfig($instance_id, $condition_config); + $block_base->setVisibilityConfig($instance_id, $condition_config); $plugin_manager->expects($this->once())->method('createInstance') ->withAnyParameters()->will($this->returnValue('test')); - $condition = $block_base->getCondition($instance_id); + $condition = $block_base->getVisibilityCondition($instance_id); $this->assertEquals('test', $condition, "The correct condition is returned."); } diff --git a/core/modules/language/config/schema/language.schema.yml b/core/modules/language/config/schema/language.schema.yml index a10dc3d..584a715 100644 --- a/core/modules/language/config/schema/language.schema.yml +++ b/core/modules/language/config/schema/language.schema.yml @@ -123,3 +123,11 @@ language.settings: language_show: type: boolean label: 'Show language selector on create and edit pages' + +condition.plugin.language: + type: condition.plugin + mapping: + langcodes: + type: sequence + sequence: + - type: string diff --git a/core/modules/language/src/Plugin/Condition/Language.php b/core/modules/language/src/Plugin/Condition/Language.php index 72f0e5f..ff64464 100644 --- a/core/modules/language/src/Plugin/Condition/Language.php +++ b/core/modules/language/src/Plugin/Condition/Language.php @@ -96,7 +96,7 @@ public function summary() { * {@inheritdoc} */ public function evaluate() { - if (empty($this->configuration['langcodes'])) { + if (empty($this->configuration['langcodes']) && !$this->configuration['negate']) { return TRUE; } diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 6174a13..a311051 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -937,71 +937,6 @@ function node_get_recent($number = 10) { } /** - * Implements hook_form_FORM_ID_alter() for block_form(). - * - * Adds node-type specific visibility options to block configuration form. - */ -function node_form_block_form_alter(&$form, &$form_state) { - $block = $form_state['controller']->getEntity(); - $visibility = $block->get('visibility'); - $form['visibility']['node_type'] = array( - '#type' => 'details', - '#title' => t('Content types'), - '#group' => 'visibility', - '#weight' => 5, - ); - $form['visibility']['node_type']['types'] = array( - '#type' => 'checkboxes', - '#title' => t('Show block for specific content types'), - '#default_value' => !empty($visibility['node_type']['types']) ? $visibility['node_type']['types'] : array(), - '#options' => node_type_get_names(), - '#description' => t('Show this block only on pages that display content of the given type(s). If you select no types, there will be no type-specific limitation.'), - ); -} - -/** - * Implements hook_block_access(). - * - * Checks the content type specific visibility settings and removes the block - * if the visibility conditions are not met. - */ -function node_block_access(Block $block, $operation, AccountInterface $account, $langcode) { - // Only affect access when viewing the block. - if ($operation != 'view') { - return; - } - $visibility = $block->get('visibility'); - if (!empty($visibility)) { - if (!empty($visibility['node_type']['types'])) { - $allowed_types = array_filter($visibility['node_type']['types']); - } - if (empty($allowed_types)) { - // There are no node types selected in visibility settings so there is - // nothing to do. - // @see node_form_block_form_alter() - return; - } - - // For blocks with node types associated, if the node type does not match - // the settings from this block, deny access to it. - $request = \Drupal::request(); - if ($node = $request->attributes->get('node')) { - // Page has node. - return in_array($node->bundle(), $allowed_types); - } - // This is a node creation page. - // $request->attributes->has('node_type') would also match administration - // configuration pages, which the previous URI path options did not. - if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'node.add') { - $node_type = $request->attributes->get('node_type'); - return in_array($node_type->id(), $allowed_types); - } - - return FALSE; - } -} - -/** * Page callback: Generates and prints an RSS feed. * * Generates an RSS feed from an array of node IDs, and prints it with an HTTP diff --git a/core/modules/node/src/Plugin/Condition/NodeType.php b/core/modules/node/src/Plugin/Condition/NodeType.php index f311827..95da12b 100644 --- a/core/modules/node/src/Plugin/Condition/NodeType.php +++ b/core/modules/node/src/Plugin/Condition/NodeType.php @@ -79,7 +79,7 @@ public function summary() { * {@inheritdoc} */ public function evaluate() { - if (empty($this->configuration['bundles'])) { + if (empty($this->configuration['bundles']) && !$this->configuration['negate']) { return TRUE; } $node = $this->getContextValue('node'); diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index bd3f8fd..7fb269d 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -427,11 +427,14 @@ protected function drupalPlaceBlock($plugin_id, array $settings = array()) { 'max_age' => 0, ), ); - foreach (array('region', 'id', 'theme', 'plugin', 'visibility', 'weight') as $key) { + foreach (array('region', 'id', 'theme', 'plugin', 'weight') as $key) { $values[$key] = $settings[$key]; // Remove extra values that do not belong in the settings array. unset($settings[$key]); } + foreach ($settings['visibility'] as $id => $visibility) { + $settings['visibility'][$id]['id'] = $id; + } $values['settings'] = $settings; $block = entity_create('block', $values); $block->save(); diff --git a/core/modules/system/src/Plugin/Condition/RequestPath.php b/core/modules/system/src/Plugin/Condition/RequestPath.php index 59936e7..2043b77 100644 --- a/core/modules/system/src/Plugin/Condition/RequestPath.php +++ b/core/modules/system/src/Plugin/Condition/RequestPath.php @@ -87,7 +87,7 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function defaultConfiguration() { - return array('pages' => ''); + return array('pages' => '') + parent::defaultConfiguration(); } /** diff --git a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php index f310b24..a22dfb2 100644 --- a/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php +++ b/core/modules/system/src/Tests/Cache/PageCacheTagsIntegrationTest.php @@ -67,8 +67,7 @@ function testPageCacheTags() { // Place a block, but only make it visible on full node page 2. $block = $this->drupalPlaceBlock('views_block:comments_recent-block_1', array( 'visibility' => array( - 'path' => array( - 'visibility' => BLOCK_VISIBILITY_LISTED, + 'request_path' => array( 'pages' => 'node/' . $node_2->id(), ), ) diff --git a/core/modules/user/src/Plugin/Condition/UserRole.php b/core/modules/user/src/Plugin/Condition/UserRole.php index 1557b07..c0383c7 100644 --- a/core/modules/user/src/Plugin/Condition/UserRole.php +++ b/core/modules/user/src/Plugin/Condition/UserRole.php @@ -45,7 +45,7 @@ public function buildConfigurationForm(array $form, array &$form_state) { public function defaultConfiguration() { return array( 'roles' => array(), - ); + ) + parent::defaultConfiguration(); } /** @@ -80,7 +80,7 @@ public function summary() { * {@inheritdoc} */ public function evaluate() { - if (empty($this->configuration['roles'])) { + if (empty($this->configuration['roles']) && !$this->configuration['negate']) { return TRUE; } $user = $this->getContextValue('user'); diff --git a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php index dd2d2e8..0475e23 100644 --- a/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php +++ b/core/modules/views/src/Tests/Plugin/BlockDependenciesTest.php @@ -109,11 +109,14 @@ protected function createBlock($plugin_id, array $settings = array()) { 'max_age' => 0, ), ); - foreach (array('region', 'id', 'theme', 'plugin', 'visibility', 'weight') as $key) { + foreach (array('region', 'id', 'theme', 'plugin', 'weight') as $key) { $values[$key] = $settings[$key]; // Remove extra values that do not belong in the settings array. unset($settings[$key]); } + foreach ($settings['visibility'] as $id => $visibility) { + $settings['visibility'][$id]['id'] = $id; + } $values['settings'] = $settings; $block = entity_create('block', $values); $block->save(); diff --git a/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php b/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php index 3384b0f..1a405d9 100644 --- a/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php +++ b/core/modules/views_ui/src/Tests/OverrideDisplaysTest.php @@ -120,9 +120,9 @@ function testWizardMixedDefaultOverriddenDisplays() { // presence/absence of the view's title in both the page and the block). $this->drupalPlaceBlock("views_block:{$view['id']}-block_1", array( 'visibility' => array( - 'path' => array( - 'visibility' => BLOCK_VISIBILITY_NOTLISTED, + 'request_path' => array( 'pages' => $view['page[path]'], + 'negate' => TRUE, ), ), ));