Move into nested docroot

This commit is contained in:
Rob Davies 2017-02-13 15:31:17 +00:00
parent 83a0d3a149
commit c8b70abde9
13405 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,7 @@
# Clashes with default configuration provided by the config_test module.
id: dotted.default
label: 'Config install fail'
weight: 0
protected_property: Default
# Intentionally commented out to verify default status behavior.
# status: 1

View file

@ -0,0 +1,2 @@
# Clashes with default configuration provided by the config_test module.
label: 'Je suis'

View file

@ -0,0 +1,10 @@
name: 'Test theme for configuration clash detection'
type: theme
description: 'Test theme for configuration clash detection'
version: VERSION
base theme: classy
core: 8.x
regions:
content: Content
left: Left
right: Right

View file

@ -0,0 +1,9 @@
# This should contain a copy of the configuration from the
# config_collection_install_test module.
name: 'Config collection clash test module'
type: module
package: Testing
version: VERSION
core: 8.x
dependencies:
- config_collection_install_test

View file

@ -0,0 +1,7 @@
config_collection_install_test.test:
type: config_object
label: 'Collection test'
mapping:
collection:
type: string
label: 'Collection'

View file

@ -0,0 +1,5 @@
name: 'Configuration events test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,6 @@
services:
config_events_test.event_subscriber:
class: Drupal\config_collection_install_test\EventSubscriber
arguments: ['@state']
tags:
- { name: event_subscriber }

View file

@ -0,0 +1,50 @@
<?php
namespace Drupal\config_collection_install_test;
use Drupal\Core\Config\ConfigCollectionInfo;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\State\StateInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EventSubscriber implements EventSubscriberInterface {
/**
* The state key value store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Constructs the Event Subscriber object.
*
* @param \Drupal\Core\State\StateInterface $state
* The state key value store.
*/
public function __construct(StateInterface $state) {
$this->state = $state;
}
/**
* Reacts to the ConfigEvents::COLLECTION_INFO event.
*
* @param \Drupal\Core\Config\ConfigCollectionInfo $collection_info
* The configuration collection info event.
*/
public function addCollections(ConfigCollectionInfo $collection_info) {
$collections = $this->state->get('config_collection_install_test.collection_names', array());
foreach ($collections as $collection) {
$collection_info->addCollection($collection);
}
}
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
$events[ConfigEvents::COLLECTION_INFO][] = array('addCollections');
return $events;
}
}

View file

@ -0,0 +1,5 @@
name: 'Configuration entity static cache test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,31 @@
<?php
/**
* @file
* Provides configuration entity static cache test helpers.
*/
use Drupal\Component\Utility\Random;
/**
* Implements hook_ENTITY_TYPE_load() for 'static_cache_test_config_test'.
*/
function config_entity_static_cache_test_config_test_load($entities) {
static $random;
if (!$random) {
$random = new Random();
}
foreach ($entities as $entity) {
// Add a random stamp for every load(), so that during tests, we can tell
// if an entity was retrieved from cache (unchanged stamp) or reloaded.
$entity->_loadStamp = $random->string(8, TRUE);
}
}
/**
* Implements hook_entity_type_alter().
*/
function config_entity_static_cache_test_entity_type_alter(array &$entity_types) {
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
$entity_types['config_test']->set('static_cache', TRUE);
}

View file

@ -0,0 +1,46 @@
<?php
namespace Drupal\config_entity_static_cache_test;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Tests module overrides for configuration.
*/
class ConfigOverrider implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
return array(
'config_test.dynamic.test_1' => array(
'label' => 'Overridden label',
)
);
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'config_entity_static_cache_test';
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
}

View file

@ -0,0 +1,7 @@
config_events_test.test:
type: config_object
label: 'Configuration events test'
mapping:
key:
type: string
label: 'Value'

View file

@ -0,0 +1,5 @@
name: 'Configuration events test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,6 @@
services:
config_events_test.event_subscriber:
class: Drupal\config_events_test\EventSubscriber
arguments: ['@state']
tags:
- { name: event_subscriber }

View file

@ -0,0 +1,58 @@
<?php
namespace Drupal\config_events_test;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\State\StateInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class EventSubscriber implements EventSubscriberInterface {
/**
* The state key value store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Constructs the Event Subscriber object.
*
* @param \Drupal\Core\State\StateInterface $state
* The state key value store.
*/
public function __construct(StateInterface $state) {
$this->state = $state;
}
/**
* Reacts to config event.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
* The configuration event.
* @param string $name
* The event name.
*/
public function configEventRecorder(ConfigCrudEvent $event, $name) {
$config = $event->getConfig();
$this->state->set('config_events_test.event', array(
'event_name' => $name,
'current_config_data' => $config->get(),
'original_config_data' => $config->getOriginal(),
'raw_config_data' => $config->getRawData()
));
}
/**
* {@inheritdoc}
*/
static function getSubscribedEvents() {
$events[ConfigEvents::SAVE][] = array('configEventRecorder');
$events[ConfigEvents::DELETE][] = array('configEventRecorder');
$events[ConfigEvents::RENAME][] = array('configEventRecorder');
return $events;
}
}

View file

@ -0,0 +1,5 @@
name: 'Configuration import test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,25 @@
<?php
/**
* @file
* Provides configuration import test helpers.
*/
/**
* Implements hook_config_import_steps_alter().
*/
function config_import_test_config_import_steps_alter(&$sync_steps) {
$sync_steps[] = '_config_import_test_config_import_steps_alter';
}
/**
* Implements configuration synchronization step added by an alter for testing.
*
* @param array $context
* The batch context.
*/
function _config_import_test_config_import_steps_alter(&$context) {
$GLOBALS['hook_config_test']['config_import_steps_alter'] = TRUE;
$context['finished'] = 1;
return;
}

View file

@ -0,0 +1,6 @@
services:
config_import_test.event_subscriber:
class: Drupal\config_import_test\EventSubscriber
tags:
- { name: event_subscriber }
arguments: ['@state']

View file

@ -0,0 +1,142 @@
<?php
namespace Drupal\config_import_test;
use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\ConfigImporterEvent;
use Drupal\Core\Config\Importer\MissingContentEvent;
use Drupal\Core\State\StateInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Config import subscriber for config import events.
*/
class EventSubscriber implements EventSubscriberInterface {
/**
* The key value store.
*
* @var \Drupal\Core\State\StateInterface
*/
protected $state;
/**
* Constructs the event subscriber.
*
* @param \Drupal\Core\State\StateInterface $state
* The key value store.
*/
public function __construct(StateInterface $state) {
$this->state = $state;
}
/**
* Validates the configuration to be imported.
*
* @param \Drupal\Core\Config\ConfigImporterEvent $event
* The Event to process.
*
* @throws \Drupal\Core\Config\ConfigNameException
*/
public function onConfigImporterValidate(ConfigImporterEvent $event) {
if ($this->state->get('config_import_test.config_import_validate_fail', FALSE)) {
// Log more than one error to test multiple validation errors.
$event->getConfigImporter()->logError('Config import validate error 1.');
$event->getConfigImporter()->logError('Config import validate error 2.');
}
}
/**
* Handles the missing content event.
*
* @param \Drupal\Core\Config\Importer\MissingContentEvent $event
* The missing content event.
*/
public function onConfigImporterMissingContentOne(MissingContentEvent $event) {
if ($this->state->get('config_import_test.config_import_missing_content', FALSE) && $this->state->get('config_import_test.config_import_missing_content_one', FALSE) === FALSE) {
$missing = $event->getMissingContent();
$uuid = key($missing);
$this->state->set('config_import_test.config_import_missing_content_one', key($missing));
$event->resolveMissingContent($uuid);
// Stopping propagation ensures that onConfigImporterMissingContentTwo
// will be fired on the next batch step.
$event->stopPropagation();
}
}
/**
* Handles the missing content event.
*
* @param \Drupal\Core\Config\Importer\MissingContentEvent $event
* The missing content event.
*/
public function onConfigImporterMissingContentTwo(MissingContentEvent $event) {
if ($this->state->get('config_import_test.config_import_missing_content', FALSE) && $this->state->get('config_import_test.config_import_missing_content_two', FALSE) === FALSE) {
$missing = $event->getMissingContent();
$uuid = key($missing);
$this->state->set('config_import_test.config_import_missing_content_two', key($missing));
$event->resolveMissingContent($uuid);
}
}
/**
* Reacts to a config save and records information in state for testing.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
*/
public function onConfigSave(ConfigCrudEvent $event) {
$config = $event->getConfig();
if ($config->getName() == 'action.settings') {
$values = $this->state->get('ConfigImportUITest.action.settings.recursion_limit', array());
$values[] = $config->get('recursion_limit');
$this->state->set('ConfigImportUITest.action.settings.recursion_limit', $values);
}
if ($config->getName() == 'core.extension') {
$installed = $this->state->get('ConfigImportUITest.core.extension.modules_installed', array());
$uninstalled = $this->state->get('ConfigImportUITest.core.extension.modules_uninstalled', array());
$original = $config->getOriginal('module');
$data = $config->get('module');
$install = array_diff_key($data, $original);
if (!empty($install)) {
$installed[] = key($install);
}
$uninstall = array_diff_key($original, $data);
if (!empty($uninstall)) {
$uninstalled[] = key($uninstall);
}
$this->state->set('ConfigImportUITest.core.extension.modules_installed', $installed);
$this->state->set('ConfigImportUITest.core.extension.modules_uninstalled', $uninstalled);
}
}
/**
* Reacts to a config delete and records information in state for testing.
*
* @param \Drupal\Core\Config\ConfigCrudEvent $event
*/
public function onConfigDelete(ConfigCrudEvent $event) {
$config = $event->getConfig();
if ($config->getName() == 'action.settings') {
$value = $this->state->get('ConfigImportUITest.action.settings.delete', 0);
$this->state->set('ConfigImportUITest.action.settings.delete', $value + 1);
}
}
/**
* Registers the methods in this class that should be listeners.
*
* @return array
* An array of event listener definitions.
*/
static function getSubscribedEvents() {
$events[ConfigEvents::SAVE][] = array('onConfigSave', 40);
$events[ConfigEvents::DELETE][] = array('onConfigDelete', 40);
$events[ConfigEvents::IMPORT_VALIDATE] = array('onConfigImporterValidate');
$events[ConfigEvents::IMPORT_MISSING_CONTENT] = array(array('onConfigImporterMissingContentOne'), array('onConfigImporterMissingContentTwo', -100));
return $events;
}
}

View file

@ -0,0 +1,11 @@
id: other_module_test_with_dependency
label: 'Other module test with dependency'
weight: 0
style: ''
status: true
langcode: en
protected_property: Default
dependencies:
enforced:
module:
- config_other_module_config_test

View file

@ -0,0 +1,5 @@
name: 'Config install dependency test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,17 @@
<?php
/**
* @file
* Provides hook implementations for testing purposes.
*/
use Drupal\Core\Entity\EntityInterface;
/**
* Implements hook_ENTITY_TYPE_create.
*/
function config_install_dependency_test_config_test_create(EntityInterface $entity) {
// Add an enforced dependency on this module so that we can test if this is
// possible during module installation.
$entity->setEnforcedDependencies(['module' => ['config_install_dependency_test']]);
}

View file

@ -0,0 +1,7 @@
# Clashes with default configuration provided by the config_test module.
id: dotted.default
label: 'Config install fail'
weight: 0
protected_property: Default
# Intentionally commented out to verify default status behavior.
# status: 1

View file

@ -0,0 +1,2 @@
# Clashes with default configuration provided by the config_test module.
label: 'Je suis'

View file

@ -0,0 +1,7 @@
name: 'Configuration install fail test'
type: module
package: Testing
version: VERSION
core: 8.x
dependencies:
- config_test

View file

@ -0,0 +1,2 @@
id: config_integration_test
label: 'Default integration config label'

View file

@ -0,0 +1,9 @@
# Schema for the configuration files of the Configuration Integration Test module.
config_integration_test.settings:
type: config_object
label: 'Configuration integration test settings'
mapping:
foo:
type: string
label: 'Foo'

View file

@ -0,0 +1,7 @@
name: 'ConfigTest integration'
type: module
package: 'Testing'
version: VERSION
core: 8.x
dependencies:
- config_test

View file

@ -0,0 +1,7 @@
id: other_module_test
label: 'Other module test'
weight: 0
style: ''
status: true
langcode: en
protected_property: Default

View file

@ -0,0 +1,11 @@
id: other_module_test_optional_entity_unmet
label: 'Other module test to test optional config installation'
weight: 0
style: ''
status: true
langcode: en
protected_property: Default
dependencies:
enforced:
config:
- config_test.dynamic.other_module_test_unmet

View file

@ -0,0 +1,11 @@
id: other_module_test_unmet
label: 'Other module test to test optional config installation'
weight: 0
style: ''
status: true
langcode: en
protected_property: Default
dependencies:
enforced:
module:
- config_install_dependency_test

View file

@ -0,0 +1,5 @@
config_other_module_config_test.weird_simple_config:
type: config_object
mapping:
foo:
type: string

View file

@ -0,0 +1,5 @@
name: 'Config other module config'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,24 @@
id: config_override_test
theme: classy
weight: 0
status: true
langcode: en
region: content
plugin: test_cache
settings:
label: 'Test HTML block'
provider: block_test
label_display: visible
status: true
info: ''
view_mode: default
dependencies:
module:
- block_test
theme:
- classy
visibility:
request_path:
id: request_path
pages: ''
negate: false

View file

@ -0,0 +1,9 @@
name: 'Configuration override integration test'
type: module
package: Testing
version: VERSION
core: 8.x
dependencies:
- block
- block_test

View file

@ -0,0 +1,9 @@
services:
cache_context.config_override_integration_test:
class: Drupal\config_override_integration_test\Cache\ConfigOverrideIntegrationTestCacheContext
tags:
- { name: cache.context }
config_override_integration_test.config_override:
class: Drupal\config_override_integration_test\CacheabilityMetadataConfigOverride
tags:
- { name: config.factory.override }

View file

@ -0,0 +1,42 @@
<?php
namespace Drupal\config_override_integration_test\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
/**
* A cache context service intended for the config override integration test.
*
* Cache context ID: 'config_override_integration_test'.
*/
class ConfigOverrideIntegrationTestCacheContext implements CacheContextInterface {
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Config override integration test');
}
/**
* {@inheritdoc}
*/
public function getContext() {
// Default to the 'disabled' state.
$state = \Drupal::state()->get('config_override_integration_test.enabled', FALSE) ? 'yes' : 'no';
return 'config_override_integration_test.' . $state;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
// Since this depends on State this can change at any time and is not
// cacheable.
$metadata = new CacheableMetadata();
$metadata->setCacheMaxAge(0);
return $metadata;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace Drupal\config_override_integration_test;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Test implementation of a config override that provides cacheability metadata.
*/
class CacheabilityMetadataConfigOverride implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = [];
// Override the test block depending on the state set in the test.
$state = \Drupal::state()->get('config_override_integration_test.enabled', FALSE);
if (in_array('block.block.config_override_test', $names) && $state !== FALSE) {
$overrides = $overrides + [
'block.block.config_override_test' => [
'settings' => ['label' => 'Overridden block label'],
],
];
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'config_override_integration_test';
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
$metadata = new CacheableMetadata();
if ($name === 'block.block.config_override_test') {
$metadata
->setCacheContexts(['config_override_integration_test'])
->setCacheTags(['config_override_integration_test_tag']);
}
return $metadata;
}
}

View file

@ -0,0 +1,26 @@
langcode: en
status: true
dependencies:
module:
- block_content
theme:
- classy
id: call_to_action
theme: classy
region: content
weight: null
provider: null
plugin: 'block_content:d7c9d8ba-663f-41b4-8756-86bc55c44653'
settings:
id: 'block_content:d7c9d8ba-663f-41b4-8756-86bc55c44653'
label: 'Shop for cheap now!'
provider: block_content
label_display: visible
status: true
info: ''
view_mode: default
visibility:
request_path:
id: request_path
pages: ''
negate: false

View file

@ -0,0 +1,4 @@
threshold:
requirements_warning: 172800
requirements_error: 1209600

View file

@ -0,0 +1,9 @@
name: 'Configuration override test'
type: module
package: Testing
version: VERSION
core: 8.x
dependencies:
- block
- block_content

View file

@ -0,0 +1,17 @@
services:
cache_context.pirate_day:
class: Drupal\config_override_test\Cache\PirateDayCacheContext
tags:
- { name: cache.context }
config_override_test.overrider:
class: Drupal\config_override_test\ConfigOverrider
tags:
- { name: config.factory.override}
config_override_test.low_priority_overrider:
class: Drupal\config_override_test\ConfigOverriderLowPriority
tags:
- { name: config.factory.override, priority: -100 }
config_override_test.pirate_day_cacheability_metadata_override:
class: Drupal\config_override_test\PirateDayCacheabilityMetadataConfigOverride
tags:
- { name: config.factory.override }

View file

@ -0,0 +1,61 @@
<?php
namespace Drupal\config_override_test\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\Context\CacheContextInterface;
/**
* Defines the PirateDayCacheContext service that allows to cache the booty.
*
* Cache context ID: 'pirate_day'.
*/
class PirateDayCacheContext implements CacheContextInterface {
/**
* The length of Pirate Day. It lasts 24 hours.
*
* This is a simplified test implementation. In a real life Pirate Day module
* this data wouldn't be defined in a constant, but calculated in a static
* method. If it were Pirate Day it should return the number of seconds until
* midnight, and on all other days it should return the number of seconds
* until the start of the next Pirate Day.
*/
const PIRATE_DAY_MAX_AGE = 86400;
/**
* {@inheritdoc}
*/
public static function getLabel() {
return t('Pirate day');
}
/**
* {@inheritdoc}
*/
public function getContext() {
$is_pirate_day = static::isPirateDay() ? 'yarr' : 'nay';
return "pirate_day." . $is_pirate_day;
}
/**
* Returns whether or not it is Pirate Day.
*
* To ease testing this is determined with a global variable rather than using
* the traditional compass and sextant.
*
* @return bool
* Returns TRUE if it is Pirate Day today.
*/
public static function isPirateDay() {
return !empty($GLOBALS['it_is_pirate_day']);
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata() {
return new CacheableMetadata();
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace Drupal\config_override_test;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
/**
* Tests module overrides for configuration.
*/
class ConfigOverrider implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = array();
if (!empty($GLOBALS['config_test_run_module_overrides'])) {
if (in_array('system.site', $names)) {
$overrides = $overrides + array('system.site' => array('name' => 'ZOMG overridden site name'));
}
if (in_array('config_override_test.new', $names)) {
$overrides = $overrides + array('config_override_test.new' => array('module' => 'override'));
}
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'ConfigOverrider';
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\config_override_test;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Tests module overrides for configuration.
*/
class ConfigOverriderLowPriority implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = array();
if (!empty($GLOBALS['config_test_run_module_overrides'])) {
if (in_array('system.site', $names)) {
$overrides = array('system.site' =>
array(
'name' => 'Should not apply because of higher priority listener',
// This override should apply because it is not overridden by the
// higher priority listener.
'slogan' => 'Yay for overrides!',
)
);
}
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'ConfigOverriderLowPriority';
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
return new CacheableMetadata();
}
}

View file

@ -0,0 +1,77 @@
<?php
namespace Drupal\config_override_test;
use Drupal\config_override_test\Cache\PirateDayCacheContext;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;
/**
* Test implementation of a config override that provides cacheability metadata.
*/
class PirateDayCacheabilityMetadataConfigOverride implements ConfigFactoryOverrideInterface {
/**
* {@inheritdoc}
*/
public function loadOverrides($names) {
$overrides = [];
// Override the theme and the 'call_to_action' block on Pirate Day.
if (PirateDayCacheContext::isPirateDay()) {
if (in_array('system.theme', $names)) {
$overrides = $overrides + ['system.theme' => ['default' => 'pirate']];
}
if (in_array('block.block.call_to_action', $names)) {
$overrides = $overrides + [
'block.block.call_to_action' => [
'settings' => ['label' => 'Draw yer cutlasses!'],
],
];
}
}
return $overrides;
}
/**
* {@inheritdoc}
*/
public function getCacheSuffix() {
return 'PirateDayConfigOverrider';
}
/**
* {@inheritdoc}
*/
public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
return NULL;
}
/**
* {@inheritdoc}
*/
public function getCacheableMetadata($name) {
$metadata = new CacheableMetadata();
$metadata
->setCacheContexts(['pirate_day'])
->setCacheTags(['pirate-day-tag'])
->setCacheMaxAge(PirateDayCacheContext::PIRATE_DAY_MAX_AGE);
return $metadata;
}
/**
* Returns whether or not our overrides are potentially applicable.
*
* @param string $name
* The name of the config object that is being constructed.
*
* @return bool
* TRUE if the merchant ship will be boarded. FALSE if we drink rum instead.
*/
protected function isCacheabilityMetadataApplicable($name) {
return in_array($name, ['system.theme', 'block.block.call_to_action']);
}
}

View file

@ -0,0 +1,9 @@
label: 'Label string'
irrelevant: 123
indescribable:
abc: 789
def:
- 456
- 'abc'
xyz: 13.4
weight: 27

View file

@ -0,0 +1,4 @@
testitem: "Whatever structure there is in this file"
testlist:
- "the main file has no schema, so individual items"
- "will not have any schema information."

View file

@ -0,0 +1,30 @@
tests:
-
plugin_id: boolean
value: TRUE
-
plugin_id: boolean:derivative
value: TRUE
-
plugin_id: string
value: 'Foo'
-
plugin_id: string:derivative
value: 'Foo'
test_with_parents:
-
plugin_id: boolean
settings:
value: TRUE
-
plugin_id: boolean:derivative
settings:
value: TRUE
-
plugin_id: string
settings:
value: 'Foo'
-
plugin_id: string:derivative
settings:
value: 'Foo'

View file

@ -0,0 +1,2 @@
testid: 'Test id'
testdescription: 'Test description'

View file

@ -0,0 +1,2 @@
testid: 'Test id'
testdescription: 'Test description'

View file

@ -0,0 +1,12 @@
one_level:
target_key: key_1
testitem: 'text for entry_1'
two_levels:
target_key: key_2
wrapper:
testitem: 'text for entry_2'
three_levels:
target_key: key_3
wrapper_1:
wrapper_2:
testitem: 'text for entry_3'

View file

@ -0,0 +1,5 @@
testitem: 'Since this file at least has top level schema in config_test.schema.yml'
testlist:
- 'Direct string items are identified and other items are'
- 'recognized as undefined types.'
testnoschema: 12

View file

@ -0,0 +1,8 @@
id: third_party
label: Default
weight: 0
protected_property: Default
third_party_settings:
config_schema_test:
integer: 1
string: 'string'

View file

@ -0,0 +1,272 @@
# Schema for the configuration files of the Configuration Schema Test module.
config_schema_test.someschema:
type: config_object
label: 'Schema test data'
mapping:
testitem:
label: 'Test item'
testlist:
label: 'Test list'
config_schema_test.someschema.with_parents:
label: 'Schema test data with parenting'
type: config_object
mapping:
one_level:
label: 'Parenting one level up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
testitem:
type: config_schema_test.someschema.with_parents.[%parent.target_key]
two_levels:
label: 'Parenting two levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper:
label: 'Wrapper'
type: mapping
mapping:
testitem:
type: config_schema_test.someschema.with_parents.[%parent.%parent.target_key]
three_levels:
label: 'Parenting three levels up'
type: mapping
mapping:
target_key:
label: 'Key used in parent relation'
type: string
wrapper_1:
label: 'Wrapper 1'
type: mapping
mapping:
wrapper_2:
label: 'Wrapper 2'
type: mapping
mapping:
testitem:
type: config_schema_test.someschema.with_parents.[%parent.%parent.%parent.target_key]
config_schema_test.someschema.with_parents.key_1:
label: 'Test item nested one level'
type: string
config_schema_test.someschema.with_parents.key_2:
label: 'Test item nested two levels'
type: string
config_schema_test.someschema.with_parents.key_3:
label: 'Test item nested three levels'
type: string
config_schema_test.someschema.somemodule.*.*:
type: config_object
label: 'Schema multiple filesystem marker test'
mapping:
testid:
type: string
label: 'ID'
testdescription:
type: text
label: 'Description'
config_schema_test.wildcard_fallback.*:
type: config_object
label: 'Schema wildcard fallback test'
mapping:
testid:
type: string
label: 'ID'
testdescription:
type: text
label: 'Description'
config_schema_test.schema_data_types:
type: config_object
label: 'Config test schema'
mapping:
config_schema_test_integer:
type: config_schema_test_integer
config_schema_test_integer_empty_string:
type: config_schema_test_integer
integer:
type: integer
null_integer:
type: integer
float:
type: float
null_float:
type: float
string:
type: string
null_string:
type: string
empty_string:
type: string
boolean:
type: boolean
no_type:
label: 'No label'
mapping:
type: mapping
mapping:
string:
type: string
sequence:
type: sequence
sequence:
type: boolean
sequence_bc:
type: sequence
sequence:
- type: boolean
config_schema_test_integer:
type: integer
label: 'Config test integer'
config_schema_test.ignore:
type: config_object
label: 'Ignore test'
mapping:
label:
type: label
label: 'Label'
irrelevant:
type: ignore
label: 'Irrelevant'
indescribable:
type: ignore
label: 'Indescribable'
weight:
type: integer
label: 'Weight'
config_schema_test.plugin_types:
type: config_object
mapping:
tests:
type: sequence
sequence:
type: test.plugin_types.[plugin_id]
test_with_parents:
type: sequence
sequence:
type: mapping
mapping:
plugin_id:
type: string
settings:
type: test_with_parents.plugin_types.[%parent.plugin_id]
test.plugin_types:
type: mapping
mapping:
plugin_id:
type: string
test.plugin_types.boolean:
type: mapping
mapping:
plugin_id:
type: string
value:
type: boolean
test.plugin_types.boolean:*:
type: test.plugin_types.boolean
test_with_parents.plugin_types.boolean:
type: mapping
mapping:
value:
type: boolean
test_with_parents.plugin_types.boolean:*:
type: test_with_parents.plugin_types.boolean
test.plugin_types.*:
type: mapping
mapping:
plugin_id:
type: string
value:
type: string
test_with_parents.plugin_types.*:
type: mapping
mapping:
value:
type: string
config_schema_test.hook:
type: string
config_test.dynamic.*.third_party.config_schema_test:
type: mapping
mapping:
integer:
type: integer
string:
type: string
wrapping.config_schema_test.plugin_types:
type: config_object
mapping:
tests:
type: sequence
sequence:
- type: wrapping.test.plugin_types.[plugin_id]
wrapping.test.plugin_types.*:
type: test.plugin_types.[plugin_id]
mapping:
wrapper_value:
type: string
test.plugin_types.wrapper:*:
type: test.plugin_types
mapping:
internal_value:
type: string
wrapping.config_schema_test.double_brackets:
type: config_object
mapping:
tests:
type: sequence
sequence:
- type: wrapping.test.double_brackets.[another_key]
wrapping.test.double_brackets.*:
type: test.double_brackets.[foo].[bar]
mapping:
wrapper_value:
type: string
test.double_brackets.cat.dog:
type: test.double_brackets
mapping:
another_key:
type: string
foo:
type: string
bar:
type: string
test.double_brackets.turtle.horse:
type: test.double_brackets
mapping:
another_key:
type: integer
foo:
type: string
bar:
type: string
test.double_brackets.*:
type: mapping

View file

@ -0,0 +1,6 @@
name: 'Configuration schema test'
type: module
package: Testing
version: VERSION
core: 8.x
hidden: true

View file

@ -0,0 +1,23 @@
<?php
/**
* @file
* Tests configuration schema functionality.
*/
/**
* Implements hook_config_schema_info_alter().
*/
function config_schema_test_config_schema_info_alter(&$definitions) {
if (\Drupal::state()->get('config_schema_test_exception_add')) {
$definitions['config_schema_test.hook_added_defintion'] = $definitions['config_schema_test.hook'];
}
if (\Drupal::state()->get('config_schema_test_exception_remove')) {
unset($definitions['config_schema_test.hook']);
}
// Since code can not be unloaded only alter the definition if it exists.
if (isset($definitions['config_schema_test.hook'])) {
$definitions['config_schema_test.hook']['additional_metadata'] = 'new schema info';
}
}

View file

@ -0,0 +1,6 @@
id: dotted.default
label: Default
weight: 0
protected_property: Default
# Intentionally commented out to verify default status behavior.
# status: 1

View file

@ -0,0 +1,4 @@
id: isinstallable
label: Default
weight: 0
protected_property: Default

View file

@ -0,0 +1,2 @@
id: default
label: Default

View file

@ -0,0 +1,2 @@
foo: bar
404: herp

View file

@ -0,0 +1,10 @@
array: []
boolean: true
exp: 1.2e+34
float: 3.14159
float_as_integer: !!float 1
hex: 0xC
int: 99
octal: 0775
string: string
string_int: '1'

View file

@ -0,0 +1,6 @@
# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
id: override
label: Default
weight: 0
protected_property: Default
status: true

View file

@ -0,0 +1,10 @@
# See \Drupal\config\Tests\ConfigInstallProfileOverrideTest
# This configuration entity has dependencies which would be met.
id: override_unmet
label: Default
weight: 0
protected_property: Default
status: true
dependencies:
module:
- tour

View file

@ -0,0 +1,160 @@
# Schema for the configuration files of the Configuration Test module.
config_test_dynamic:
type: config_entity
mapping:
id:
type: string
label: 'ID'
label:
type: label
label: 'Label'
weight:
type: integer
label: 'Weight'
style:
type: string
label: 'style'
size:
type: string
label: 'Size'
size_value:
type: string
label: 'Size value'
protected_property:
type: string
label: 'Protected property'
config_test.dynamic.*:
type: config_test_dynamic
label: 'Config test dynamic settings'
config_test.dynamic.*.*:
type: config_test_dynamic
label: 'Config test dynamic settings'
config_test.dynamic.*.third_party.node:
type: mapping
mapping:
foo:
type: string
config_test.query.*:
type: config_entity
mapping:
id:
type: string
label: 'ID'
label:
type: label
label: 'Label'
array:
type: sequence
label: 'Array level 1'
sequence:
type: sequence
label: 'Array level 2'
sequence:
type: integer
label: 'Value'
number:
type: integer
label: 'number'
config_test.types:
type: config_object
label: 'Configuration type'
mapping:
array:
type: sequence
label: 'Array'
sequence:
type: string
label: 'Item'
boolean:
type: boolean
label: 'Boolean'
float:
type: float
label: 'Float'
float_as_integer:
type: float
label: 'Float'
exp:
type: float
label: 'Exponential'
hex:
type: integer
label: 'Hexadecimal'
int:
type: integer
label: 'Integer'
octal:
type: integer
label: 'Octal'
string:
type: string
label: 'String'
string_int:
type: string
label: 'String integer'
config_test.no_status.default:
type: config_object
label: 'Configuration no status default'
mapping:
id:
type: string
label: 'ID'
label:
type: label
label: 'Label'
config_test.system:
type: config_object
label: 'Configuration system'
mapping:
foo:
type: string
label: 'Foo'
baz:
type: string
label: 'Baz'
'404':
type: string
label: '404'
config_test.new:
type: config_object
label: 'Configuration test'
mapping:
key:
type: string
label: 'Test setting'
new_key:
type: string
label: 'Test setting'
uuid:
type: string
label: 'UUID'
config_test.old:
type: config_test.new
config_test.foo:
type: config_object
label: 'Configuration test'
mapping:
value:
type: mapping
label: 'Value'
mapping:
key:
type: string
label: 'Key'
label:
type: label
label: 'Label'
config_test.bar:
type: config_test.foo

View file

@ -0,0 +1,86 @@
<?php
/**
* @file
* Fake third-party hook implementations for ConfigTest entities.
*
* Testing the module/hook system is not the purpose of this test helper module.
* Therefore, this file implements hooks on behalf of config_test module for
* config_test entity hooks themselves.
*/
use Drupal\config_test\Entity\ConfigTest;
/**
* Implements hook_config_test_load().
*/
function config_test_config_test_load() {
$GLOBALS['hook_config_test']['load'] = __FUNCTION__;
}
/**
* Implements hook_ENTITY_TYPE_create() for 'config_test'.
*/
function config_test_config_test_create(ConfigTest $config_test) {
if (\Drupal::state()->get('config_test.prepopulate')) {
$config_test->set('foo', 'baz');
}
_config_test_update_is_syncing_store('create', $config_test);
}
/**
* Implements hook_config_test_presave().
*/
function config_test_config_test_presave(ConfigTest $config_test) {
$GLOBALS['hook_config_test']['presave'] = __FUNCTION__;
_config_test_update_is_syncing_store('presave', $config_test);
}
/**
* Implements hook_config_test_insert().
*/
function config_test_config_test_insert(ConfigTest $config_test) {
$GLOBALS['hook_config_test']['insert'] = __FUNCTION__;
_config_test_update_is_syncing_store('insert', $config_test);
}
/**
* Implements hook_config_test_update().
*/
function config_test_config_test_update(ConfigTest $config_test) {
$GLOBALS['hook_config_test']['update'] = __FUNCTION__;
_config_test_update_is_syncing_store('update', $config_test);
}
/**
* Implements hook_config_test_predelete().
*/
function config_test_config_test_predelete(ConfigTest $config_test) {
$GLOBALS['hook_config_test']['predelete'] = __FUNCTION__;
_config_test_update_is_syncing_store('predelete', $config_test);
}
/**
* Implements hook_config_test_delete().
*/
function config_test_config_test_delete(ConfigTest $config_test) {
$GLOBALS['hook_config_test']['delete'] = __FUNCTION__;
_config_test_update_is_syncing_store('delete', $config_test);
}
/**
* Helper function for testing hooks during configuration sync.
*
* @param string $hook
* The fired hook.
* @param \Drupal\config_test\Entity\ConfigTest $config_test
* The ConfigTest entity.
*/
function _config_test_update_is_syncing_store($hook, ConfigTest $config_test) {
$current_value = \Drupal::state()->get('config_test.store_isSyncing', FALSE);
if ($current_value !== FALSE) {
$current_value['global_state::' . $hook] = \Drupal::isConfigSyncing();
$current_value['entity_state::' . $hook] = $config_test->isSyncing();
\Drupal::state()->set('config_test.store_isSyncing', $current_value);
}
}

View file

@ -0,0 +1,5 @@
name: 'Configuration test'
type: module
package: Testing
version: VERSION
core: 8.x

View file

@ -0,0 +1,5 @@
config_test_entity_add_local_action:
route_name: config_test.entity_add
title: 'Add test configuration'
appears_on:
- entity.config_test.collection

View file

@ -0,0 +1,4 @@
entity.config_test.edit_form_tab:
route_name: entity.config_test.edit_form
title: 'Edit'
base_route: entity.config_test.edit_form

View file

@ -0,0 +1,42 @@
<?php
/**
* @file
* Provides Config module hook implementations for testing purposes.
*/
require_once dirname(__FILE__) . '/config_test.hooks.inc';
/**
* Implements hook_cache_flush().
*/
function config_test_cache_flush() {
// Set a global value we can check in test code.
$GLOBALS['hook_cache_flush'] = __FUNCTION__;
}
/**
* Implements hook_entity_type_alter().
*/
function config_test_entity_type_alter(array &$entity_types) {
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
// The 'translatable' entity key is not supposed to change over time. In this
// case we can safely do it because we set it once and we do not change it for
// all the duration of the test session.
$entity_types['config_test']->set('translatable', \Drupal::service('state')->get('config_test.translatable'));
// Create a clone of config_test that does not have a status.
$entity_types['config_test_no_status'] = clone $entity_types['config_test'];
$config_test_no_status = &$entity_types['config_test_no_status'];
$config_test_no_status->setLinkTemplate('edit-form', '/admin/structure/config_test/manage/{config_test_no_status}');
$config_test_no_status->setLinkTemplate('delete-form', '/admin/structure/config_test/manage/{config_test_no_status}/delete');
$keys = $config_test_no_status->getKeys();
unset($keys['status']);
$config_test_no_status->set('id', 'config_test_no_status');
$config_test_no_status->set('entity_keys', $keys);
$config_test_no_status->set('config_prefix', 'no_status');
if (\Drupal::service('state')->get('config_test.lookup_keys', FALSE)) {
$entity_types['config_test']->set('lookup_keys', ['uuid', 'style']);
}
}

View file

@ -0,0 +1,67 @@
entity.config_test.collection:
path: '/admin/structure/config_test'
defaults:
_entity_list: 'config_test'
_title: 'Test configuration'
requirements:
_permission: 'administer site configuration'
config_test.entity_add:
path: '/admin/structure/config_test/add'
defaults:
_entity_form: 'config_test'
requirements:
_permission: 'administer site configuration'
entity.config_test.edit_form:
path: '/admin/structure/config_test/manage/{config_test}'
defaults:
_entity_form: config_test
_title_callback: '\Drupal\config_test\ConfigTestController::editTitle'
requirements:
_permission: 'administer site configuration'
entity.config_test_no_status.edit_form:
path: '/admin/structure/config_test/manage/{config_test_no_status}'
defaults:
_entity_form: config_test_no_status
_title_callback: '\Drupal\config_test\ConfigTestController::editTitle'
requirements:
_permission: 'administer site configuration'
entity.config_test.enable:
path: '/admin/structure/config_test/manage/{config_test}/enable'
defaults:
_controller: '\Drupal\config_test\ConfigTestController::enable'
entity_type: 'config_test'
requirements:
_permission: 'administer site configuration'
entity.config_test.disable:
path: '/admin/structure/config_test/manage/{config_test}/disable'
defaults:
_controller: '\Drupal\config_test\ConfigTestController::disable'
entity_type: 'config_test'
requirements:
_permission: 'administer site configuration'
entity.config_test.delete_form:
path: '/admin/structure/config_test/manage/{config_test}/delete'
defaults:
_entity_form: 'config_test.delete'
requirements:
_permission: 'administer site configuration'
entity.config_test.delete_form_config_test_no_status:
path: '/admin/structure/config_test/manage/{config_test_no_status}/delete'
defaults:
_entity_form: 'config_test_no_status.delete'
requirements:
_permission: 'administer site configuration'
config_test.schema_listener:
path: '/config_test/schema_listener'
defaults:
_controller: '\Drupal\config_test\SchemaListenerController::test'
requirements:
_permission: 'administer site configuration'

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Entity\EntityAccessControlHandler;
use Drupal\Core\Entity\EntityInterface;
/**
* Defines the access control handler for the config_test entity type.
*
* @see \Drupal\config_test\Entity\ConfigTest
*/
class ConfigTestAccessControlHandler extends EntityAccessControlHandler {
/**
* {@inheritdoc}
*/
public function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
return AccessResult::allowed();
}
/**
* {@inheritdoc}
*/
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
return AccessResult::allowed();
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Controller\ControllerBase;
use Drupal\config_test\Entity\ConfigTest;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Route controller class for the config_test module.
*/
class ConfigTestController extends ControllerBase {
/**
* Route title callback.
*
* @param \Drupal\config_test\Entity\ConfigTest $config_test
* The ConfigTest object.
*
* @return string
* The title for the ConfigTest edit form.
*/
public function editTitle(ConfigTest $config_test) {
return $this->t('Edit %label', array('%label' => $config_test->label()));
}
/**
* Enables a ConfigTest object.
*
* @param \Drupal\config_test\ConfigTest $config_test
* The ConfigTest object to enable.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response to the config_test listing page.
*/
function enable(ConfigTest $config_test) {
$config_test->enable()->save();
return new RedirectResponse($config_test->url('collection', array('absolute' => TRUE)));
}
/**
* Disables a ConfigTest object.
*
* @param \Drupal\config_test\ConfigTest $config_test
* The ConfigTest object to disable.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response to the config_test listing page.
*/
function disable(ConfigTest $config_test) {
$config_test->disable()->save();
return new RedirectResponse($config_test->url('collection', array('absolute' => TRUE)));
}
}

View file

@ -0,0 +1,197 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Form controller for the test config edit forms.
*/
class ConfigTestForm extends EntityForm {
/**
* The entity query.
*
* @var \Drupal\Core\Entity\Query\QueryFactory
*/
protected $entityQuery;
/**
* Constructs a new ConfigTestForm.
*
* @param \Drupal\Core\Entity\Query\QueryFactory $entity_query
* The entity query.
*/
public function __construct(QueryFactory $entity_query) {
$this->entityQuery = $entity_query;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.query')
);
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$entity = $this->entity;
$form['label'] = array(
'#type' => 'textfield',
'#title' => 'Label',
'#default_value' => $entity->label(),
'#required' => TRUE,
);
$form['id'] = array(
'#type' => 'machine_name',
'#default_value' => $entity->id(),
'#required' => TRUE,
'#machine_name' => array(
'exists' => [$this, 'exists'],
'replace_pattern' => '[^a-z0-9_.]+',
),
);
$form['weight'] = array(
'#type' => 'weight',
'#title' => 'Weight',
'#default_value' => $entity->get('weight'),
);
$form['style'] = array(
'#type' => 'select',
'#title' => 'Image style',
'#options' => array(),
'#default_value' => $entity->get('style'),
'#access' => FALSE,
);
if ($this->moduleHandler->moduleExists('image')) {
$form['style']['#access'] = TRUE;
$form['style']['#options'] = image_style_options();
}
// The main premise of entity forms is that we get to work with an entity
// object at all times instead of checking submitted values from the form
// state.
$size = $entity->get('size');
$form['size_wrapper'] = array(
'#type' => 'container',
'#attributes' => array(
'id' => 'size-wrapper',
),
);
$form['size_wrapper']['size'] = array(
'#type' => 'select',
'#title' => 'Size',
'#options' => array(
'custom' => 'Custom',
),
'#empty_option' => '- None -',
'#default_value' => $size,
'#ajax' => array(
'callback' => '::updateSize',
'wrapper' => 'size-wrapper',
),
);
$form['size_wrapper']['size_submit'] = array(
'#type' => 'submit',
'#value' => t('Change size'),
'#attributes' => array(
'class' => array('js-hide'),
),
'#submit' => array(array(get_class($this), 'changeSize')),
);
$form['size_wrapper']['size_value'] = array(
'#type' => 'select',
'#title' => 'Custom size value',
'#options' => array(
'small' => 'Small',
'medium' => 'Medium',
'large' => 'Large',
),
'#default_value' => $entity->get('size_value'),
'#access' => !empty($size),
);
$form['langcode'] = array(
'#type' => 'language_select',
'#title' => t('Language'),
'#languages' => LanguageInterface::STATE_ALL,
'#default_value' => $entity->language()->getId(),
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => 'Save',
);
$form['actions']['delete'] = array(
'#type' => 'submit',
'#value' => 'Delete',
);
return $form;
}
/**
* Ajax callback for the size selection element.
*/
public static function updateSize(array $form, FormStateInterface $form_state) {
return $form['size_wrapper'];
}
/**
* Element submit handler for non-JS testing.
*/
public static function changeSize(array $form, FormStateInterface $form_state) {
$form_state->setRebuild();
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
$entity = $this->entity;
$status = $entity->save();
if ($status === SAVED_UPDATED) {
drupal_set_message(format_string('%label configuration has been updated.', array('%label' => $entity->label())));
}
else {
drupal_set_message(format_string('%label configuration has been created.', array('%label' => $entity->label())));
}
$form_state->setRedirectUrl($this->entity->urlInfo('collection'));
}
/**
* Determines if the entity already exists.
*
* @param string|int $entity_id
* The entity ID.
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return bool
* TRUE if the entity exists, FALSE otherwise.
*/
public function exists($entity_id, array $element, FormStateInterface $form_state) {
/** @var \Drupal\Core\Config\Entity\ConfigEntityInterface $entity */
$entity = $form_state->getFormObject()->getEntity();
return (bool) $this->entityQuery->get($entity->getEntityTypeId())
->condition($entity->getEntityType()->getKey('id'), $entity_id)
->execute();
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
/**
* Provides an interface defining a config_test entity.
*/
interface ConfigTestInterface extends ConfigEntityInterface {
}

View file

@ -0,0 +1,33 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
/**
* Defines a class to build a listing of ConfigTest entities.
*
* @see \Drupal\config_test\Entity\ConfigTest
*/
class ConfigTestListBuilder extends ConfigEntityListBuilder {
/**
* {@inheritdoc}
*/
public function buildHeader() {
$header['label'] = t('Label');
$header['id'] = t('Machine name');
return $header + parent::buildHeader();
}
/**
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
$row['label'] = $entity->label();
$row['id'] = $entity->id();
return $row + parent::buildRow($entity);
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Config\Entity\ConfigEntityStorage;
use Drupal\Core\Config\Config;
/**
* @todo.
*/
class ConfigTestStorage extends ConfigEntityStorage {
/**
* {@inheritdoc}
*/
public function importCreate($name, Config $new_config, Config $old_config) {
// Set a global value we can check in test code.
$GLOBALS['hook_config_import'] = __METHOD__;
return parent::importCreate($name, $new_config, $old_config);
}
/**
* {@inheritdoc}
*/
public function importUpdate($name, Config $new_config, Config $old_config) {
// Set a global value we can check in test code.
$GLOBALS['hook_config_import'] = __METHOD__;
return parent::importUpdate($name, $new_config, $old_config);
}
/**
* {@inheritdoc}
*/
public function importDelete($name, Config $new_config, Config $old_config) {
// Set a global value we can check in test code.
$GLOBALS['hook_config_import'] = __METHOD__;
return parent::importDelete($name, $new_config, $old_config);
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Drupal\config_test\Entity;
/**
* Defines the ConfigQueryTest configuration entity used by the query test.
*
* @ConfigEntityType(
* id = "config_query_test",
* label = @Translation("Test configuration for query"),
* handlers = {
* "storage" = "Drupal\config_test\ConfigTestStorage",
* "list_builder" = "Drupal\Core\Config\Entity\ConfigEntityListBuilder",
* "form" = {
* "default" = "Drupal\config_test\ConfigTestForm"
* }
* },
* config_prefix = "query",
* entity_keys = {
* "id" = "id",
* "label" = "label"
* }
* )
*
* @see \Drupal\system\Tests\Entity\ConfigEntityQueryTest
*/
class ConfigQueryTest extends ConfigTest {
/**
* A number used by the sort tests.
*
* @var int
*/
public $number;
/**
* An array used by the wildcard tests.
*
* @var array
*/
public $array = array();
}

View file

@ -0,0 +1,168 @@
<?php
namespace Drupal\config_test\Entity;
use Drupal\Core\Config\Entity\ConfigEntityBase;
use Drupal\config_test\ConfigTestInterface;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
/**
* Defines the ConfigTest configuration entity.
*
* @ConfigEntityType(
* id = "config_test",
* label = @Translation("Test configuration"),
* handlers = {
* "storage" = "Drupal\config_test\ConfigTestStorage",
* "list_builder" = "Drupal\config_test\ConfigTestListBuilder",
* "form" = {
* "default" = "Drupal\config_test\ConfigTestForm",
* "delete" = "Drupal\Core\Entity\EntityDeleteForm"
* },
* "access" = "Drupal\config_test\ConfigTestAccessControlHandler"
* },
* config_prefix = "dynamic",
* entity_keys = {
* "id" = "id",
* "label" = "label",
* "status" = "status"
* },
* links = {
* "edit-form" = "/admin/structure/config_test/manage/{config_test}",
* "delete-form" = "/admin/structure/config_test/manage/{config_test}/delete",
* "enable" = "/admin/structure/config_test/manage/{config_test}/enable",
* "disable" = "/admin/structure/config_test/manage/{config_test}/disable",
* "collection" = "/admin/structure/config_test",
* }
* )
*/
class ConfigTest extends ConfigEntityBase implements ConfigTestInterface {
/**
* The machine name for the configuration entity.
*
* @var string
*/
protected $id;
/**
* The human-readable name of the configuration entity.
*
* @var string
*/
public $label;
/**
* The weight of the configuration entity.
*
* @var int
*/
public $weight = 0;
/**
* The image style to use.
*
* @var string
*/
public $style;
/**
* A protected property of the configuration entity.
*
* @var string
*/
protected $protected_property;
/**
* {@inheritdoc}
*/
public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
\Drupal::state()->set('config_entity_sort', TRUE);
return parent::sort($a, $b);
}
/**
* {@inheritdoc}
*/
public function postSave(EntityStorageInterface $storage, $update = TRUE) {
// Used to test secondary writes during config sync.
if ($this->id() == 'primary') {
$secondary = $storage->create(array(
'id' => 'secondary',
'label' => 'Secondary Default',
));
$secondary->save();
}
if ($this->id() == 'deleter') {
$deletee = $storage->load('deletee');
$deletee->delete();
}
}
/**
* {@inheritdoc}
*/
public static function postDelete(EntityStorageInterface $storage, array $entities) {
parent::postDelete($storage, $entities);
foreach ($entities as $entity) {
if ($entity->id() == 'deleter') {
$deletee = $storage->load('deletee');
$deletee->delete();
}
}
}
/**
* {@inheritdoc}
*/
public function onDependencyRemoval(array $dependencies) {
// Record which entities have this method called on.
$called = \Drupal::state()->get('config_test.on_dependency_removal_called', []);
$called[] = $this->id();
\Drupal::state()->set('config_test.on_dependency_removal_called', $called);
$changed = parent::onDependencyRemoval($dependencies);
if (!isset($this->dependencies['enforced']['config'])) {
return $changed;
}
$fix_deps = \Drupal::state()->get('config_test.fix_dependencies', array());
foreach ($dependencies['config'] as $entity) {
if (in_array($entity->getConfigDependencyName(), $fix_deps)) {
$key = array_search($entity->getConfigDependencyName(), $this->dependencies['enforced']['config']);
if ($key !== FALSE) {
$changed = TRUE;
unset($this->dependencies['enforced']['config'][$key]);
}
}
}
// If any of the dependencies removed still exists, return FALSE.
if (array_intersect_key(array_flip($this->dependencies['enforced']['config']), $dependencies['config'])) {
return FALSE;
}
return $changed;
}
/**
* Sets the enforced dependencies.
*
* @param array $dependencies
* A config dependency array.
*
* @return $this
*
* @see \Drupal\Core\Config\Entity\ConfigDependencyManager
*/
public function setEnforcedDependencies(array $dependencies) {
$this->dependencies['enforced'] = $dependencies;
return $this;
}
/**
* {@inheritdoc}
*/
public function isInstallable() {
return $this->id != 'isinstallable' || \Drupal::state()->get('config_test.isinstallable');
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\Schema\SchemaIncompleteException;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Controller for testing \Drupal\Core\Config\Testing\ConfigSchemaChecker.
*/
class SchemaListenerController extends ControllerBase {
/**
* Constructs the SchemaListenerController object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The config factory.
*/
public function __construct(ConfigFactoryInterface $config_factory) {
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory')
);
}
/**
* Tests the WebTestBase tests can use strict schema checking.
*/
public function test() {
try {
$this->configFactory->getEditable('config_schema_test.schemaless')->set('foo', 'bar')->save();
}
catch (SchemaIncompleteException $e) {
return [
'#markup' => $e->getMessage(),
];
}
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace Drupal\config_test;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Extension\ExtensionDiscovery;
/**
* Tests configuration of profiles, modules and themes.
*
* A test configuration storage to read configuration from all profiles, modules
* and themes regardless of installation status or installed profile.
*/
class TestInstallStorage extends InstallStorage {
/**
* {@inheritdoc}
*/
protected function getAllFolders() {
if (!isset($this->folders)) {
$this->folders = $this->getCoreNames();
$listing = new ExtensionDiscovery(\Drupal::root());
$listing->setProfileDirectories(array());
$this->folders += $this->getComponentNames($listing->scan('profile'));
$this->folders += $this->getComponentNames($listing->scan('module'));
$this->folders += $this->getComponentNames($listing->scan('theme'));
}
return $this->folders;
}
}

View file

@ -0,0 +1,6 @@
id: dotted.english
label: Default
weight: 0
protected_property: Default
# Used for testing default language code on imported config entities.
# langcode: en

View file

@ -0,0 +1,5 @@
id: dotted.french
label: Default
weight: 0
protected_property: Default
langcode: fr

View file

@ -0,0 +1,7 @@
name: 'Configuration test languages'
type: module
package: Testing
version: VERSION
core: 8.x
dependencies:
- config_test

View file

@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\config\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\Role;
/**
* Tests draggable list builder.
*
* @group config
*/
class ConfigDraggableListBuilderTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
public static $modules = array('config_test');
/**
* Test draggable lists.
*/
public function testDraggableList() {
$this->drupalLogin($this->drupalCreateUser(array('administer permissions')));
// Create more than 50 roles.
for ($i = 0; $i < 51; $i++) {
$role = Role::create([
'id' => 'role_' . $i,
'label' => "Role $i",
]);
$role->save();
}
// Navigate to Roles page
$this->drupalGet('admin/people/roles');
// Test for the page title.
$this->assertSession()->titleEquals(t('Roles') . ' | Drupal');
// Count the number of rows in table.
$rows = $this->xpath('//form[@class="user-admin-roles-form"]/table/tbody/tr');
$this->assertGreaterThan(50, count($rows));
for ($i = 0; $i < 51; $i++) {
$this->assertSession()->pageTextContains("Role $i");
}
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\config\Unit\Menu;
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
/**
* Tests existence of config local tasks.
*
* @group config
*/
class ConfigLocalTasksTest extends LocalTaskIntegrationTestBase {
protected function setUp() {
$this->directoryList = array('config' => 'core/modules/config');
parent::setUp();
}
/**
* Tests config local tasks existence.
*
* @dataProvider getConfigAdminRoutes
*/
public function testConfigAdminLocalTasks($route, $expected) {
$this->assertLocalTasks($route, $expected);
}
/**
* Provides a list of routes to test.
*/
public function getConfigAdminRoutes() {
return array(
array('config.sync', array(array('config.sync', 'config.import', 'config.export'))),
array('config.import_full', array(array('config.sync', 'config.import', 'config.export'), array('config.import_full', 'config.import_single'))),
array('config.import_single', array(array('config.sync', 'config.import', 'config.export'), array('config.import_full', 'config.import_single'))),
array('config.export_full', array(array('config.sync', 'config.import', 'config.export'), array('config.export_full', 'config.export_single'))),
array('config.export_single', array(array('config.sync', 'config.import', 'config.export'), array('config.export_full', 'config.export_single'))),
);
}
}