diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d9da94f64fe66ca48148a0c50873f7b274a6ee74..8beb4445464eb2b29c48c28305f23075ab5c42c9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,8 +28,8 @@ include: # OPT_IN_TEST_NEXT_MAJOR: '1' # _CURL_TEMPLATES_REF: 'main' variables: - SKIP_PHPUNIT: 1 - _PHPUNIT_CONCURRENT: 1 + SKIP_PHPUNIT: '0' + _PHPUNIT_CONCURRENT: '1' _CSPELL_IGNORE_PATHS: 'modules/js_example/templates/accordion.html.twig, **/*.svg' phpunit: diff --git a/examples.module b/examples.module index 4fe20a8910e3617a97f2980c40aaf2c48c6b2dc4..8f8a8cd2a6f11e31408d184da7da85e25a48a8d8 100644 --- a/examples.module +++ b/examples.module @@ -122,6 +122,7 @@ function _examples_toolbar_routes() { 'block_example' => 'block_example.description', 'cache_example' => 'cache_example.description', 'config_entity_example' => 'entity.robot.list', + 'config_simple_example' => 'config_simple_example.description', 'content_entity_example' => 'entity.content_entity_example_contact.collection', 'cron_example' => 'cron_example.description', 'dbtng_example' => 'dbtng_example.generate_entry_list', diff --git a/modules/config_simple_example/config/install/config_simple_example.settings.yml b/modules/config_simple_example/config/install/config_simple_example.settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..9f13574e1da2afda1d80fea63990820d2616c1a0 --- /dev/null +++ b/modules/config_simple_example/config/install/config_simple_example.settings.yml @@ -0,0 +1 @@ +message: 'Awesome settings' diff --git a/modules/config_simple_example/config/schema/config_simple_example.schema.yml b/modules/config_simple_example/config/schema/config_simple_example.schema.yml new file mode 100644 index 0000000000000000000000000000000000000000..9c8491c8243fc19032c4cbfcf9bc24cf6bc56a83 --- /dev/null +++ b/modules/config_simple_example/config/schema/config_simple_example.schema.yml @@ -0,0 +1,16 @@ +config_simple_example.settings: + # A config_object is a configuration object which can store fields. + # You have to map all field types the object stores: string, boolean, etc. + # The "text" field type is special because it's translatable by default. + # Checkout how to define schema and all available data types in: + # https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-schemametadata + # Direct link to cheat sheet: + # https://www.drupal.org/files/ConfigSchemaCheatSheet2.0.pdf + # Use Configuration Inspector to validate schema files: + # https://drupal.org/project/config_inspector + type: config_object + label: 'Example config' + mapping: + message: + type: text + label: 'Message' diff --git a/modules/config_simple_example/config_simple_example.config_translation.yml b/modules/config_simple_example/config_simple_example.config_translation.yml new file mode 100644 index 0000000000000000000000000000000000000000..726854a510bef4e0280fb753d200922985cb26be --- /dev/null +++ b/modules/config_simple_example/config_simple_example.config_translation.yml @@ -0,0 +1,7 @@ +config_simple_example.settings: + title: 'Config Simple Example Translatable config' + # Route for the translatable configuration form. + base_route_name: config_simple_example.settings + # The name of all yml files that have to be translatable. + names: + - config_simple_example.settings diff --git a/modules/config_simple_example/config_simple_example.info.yml b/modules/config_simple_example/config_simple_example.info.yml new file mode 100644 index 0000000000000000000000000000000000000000..87756fbaa539d11b78eb9902de1c31294004b367 --- /dev/null +++ b/modules/config_simple_example/config_simple_example.info.yml @@ -0,0 +1,8 @@ +name: 'Config Simple Example' +type: module +description: 'Demonstrates how to create a custom translatable config form.' +package: Example modules +core_version_requirement: ^10.3 +dependencies: + - config_translation:config_translation + - examples:examples diff --git a/modules/config_simple_example/config_simple_example.links.menu.yml b/modules/config_simple_example/config_simple_example.links.menu.yml new file mode 100644 index 0000000000000000000000000000000000000000..8a1bf80dfb3cefa0c8c2c7bf5052574144d59dd4 --- /dev/null +++ b/modules/config_simple_example/config_simple_example.links.menu.yml @@ -0,0 +1,11 @@ +config_simple_example.description: + title: 'Config Simple Example' + description: 'Custom translatable config form' + route_name: config_simple_example.description + expanded: TRUE +config_simple_example.settings: + title: 'Config Simple Example Settings' + route_name: config_simple_example.settings + parent: config_simple_example.description + description: '' + weight: -15 diff --git a/modules/config_simple_example/config_simple_example.links.task.yml b/modules/config_simple_example/config_simple_example.links.task.yml new file mode 100644 index 0000000000000000000000000000000000000000..8ecf7356d7989c902daf162544d04be26cff0943 --- /dev/null +++ b/modules/config_simple_example/config_simple_example.links.task.yml @@ -0,0 +1,8 @@ +# This file is necessary so the configuration form translation tab is shown. +config_simple_example.settings: + # Route of the form. + route_name: config_simple_example.settings + title: 'Config Simple Example Settings' + # Route of the form. + base_route: config_simple_example.settings + weight: 0 diff --git a/modules/config_simple_example/config_simple_example.module b/modules/config_simple_example/config_simple_example.module new file mode 100644 index 0000000000000000000000000000000000000000..79c96c25f5500d80bf0cee632e3c86e91646b8c7 --- /dev/null +++ b/modules/config_simple_example/config_simple_example.module @@ -0,0 +1,23 @@ +<?php + +/** + * @file + * Demonstrates how to create a translatable custom configuration form. + */ + +/** + * @defgroup config_simple_example Example: Config Simple + * @ingroup examples + * @{ + * Implement a Config Entity. + * + * This module demonstrates implementing a Simple Translatable Config Form. + * + * This is an example of a simple translatable configuration form, the kind you + * might create to store configuration data. This form can store different data + * for each site enabled language. + */ + +/** + * @} End of "defgroup config_simple_example". + */ diff --git a/modules/config_simple_example/config_simple_example.routing.yml b/modules/config_simple_example/config_simple_example.routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..a4b0befaafb26695ccc9ffd3dd1498610e4590d2 --- /dev/null +++ b/modules/config_simple_example/config_simple_example.routing.yml @@ -0,0 +1,14 @@ +config_simple_example.description: + path: '/examples/config_simple_example' + defaults: + _controller: '\Drupal\config_simple_example\Controller\ConfigSimpleController::description' + _title: 'Config Simple Example' + requirements: + _permission: 'access content' +config_simple_example.settings: + path: '/admin/config/form-api-example/config-simple-form' + defaults: + _form: '\Drupal\config_simple_example\Form\ConfigSimpleExampleSettingsForm' + _title: 'Config Simple Example' + requirements: + _permission: 'administer site configuration' diff --git a/modules/config_simple_example/src/Controller/ConfigSimpleController.php b/modules/config_simple_example/src/Controller/ConfigSimpleController.php new file mode 100644 index 0000000000000000000000000000000000000000..10ad0a00803b82b6fbd15518d94d5c8ce79b9a8f --- /dev/null +++ b/modules/config_simple_example/src/Controller/ConfigSimpleController.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\config_simple_example\Controller; + +use Drupal\Core\Controller\ControllerBase; +use Drupal\examples\Utility\DescriptionTemplateTrait; + +/** + * Controller routines for Config Simple Example routes. + */ +class ConfigSimpleController extends ControllerBase { + + use DescriptionTemplateTrait; + + /** + * {@inheritdoc} + */ + protected function getModuleName() { + return 'config_simple_example'; + } + +} diff --git a/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php b/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php new file mode 100644 index 0000000000000000000000000000000000000000..260d345605369c9af5da87c787f25232a73de66a --- /dev/null +++ b/modules/config_simple_example/src/Form/ConfigSimpleExampleSettingsForm.php @@ -0,0 +1,57 @@ +<?php + +namespace Drupal\config_simple_example\Form; + +use Drupal\Core\Form\ConfigFormBase; +use Drupal\Core\Form\FormStateInterface; + +/** + * Configure example settings for this site. + */ +class ConfigSimpleExampleSettingsForm extends ConfigFormBase { + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'config_simple_example_settings'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames() { + return [ + 'config_simple_example.settings', + ]; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $config = $this->config('config_simple_example.settings'); + + $form['message'] = [ + '#type' => 'textarea', + '#title' => $this->t('Message'), + '#default_value' => $config->get('message'), + ]; + + return parent::buildForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + // Retrieve the configuration. + $this->config('config_simple_example.settings') + // Set the submitted configuration setting. + ->set('message', $form_state->getValue('message')) + ->save(); + + parent::submitForm($form, $form_state); + } + +} diff --git a/modules/config_simple_example/templates/description.html.twig b/modules/config_simple_example/templates/description.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..f9d1a683590d3f7fcfa731bc2dea323f7d7f868f --- /dev/null +++ b/modules/config_simple_example/templates/description.html.twig @@ -0,0 +1,17 @@ +{# + +Description text for the Config Simple Example. + +#} + +{% set config_simple_form = path('config_simple_example.settings') %} + +{% trans %} + +<p>The Config Simple Example module defines a simple translatable config + form. You need "Administer site configuration" permission to test it. + You will need at least two language enabled to test the translation + of the configuration.</p> +<p><a href={{ config_simple_form }}>Config Simple Form</a></p> + +{% endtrans %} diff --git a/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php b/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dd88de1b48d58f9a8710567722683881a88b9de7 --- /dev/null +++ b/modules/config_simple_example/tests/src/Functional/ConfigExampleTest.php @@ -0,0 +1,118 @@ +<?php + +namespace Drupal\Tests\form_api_example\Functional; + +use Drupal\Core\Url; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Tests\examples\Functional\ExamplesBrowserTestBase; + +/** + * Ensure that the form_api_example forms work properly. + * + * @group config_simple_example + * @group examples + * + * @ingroup form_api_example + */ +class ConfigExampleTest extends ExamplesBrowserTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * Our module dependencies. + * + * @var string[] + */ + protected static $modules = [ + 'language', + 'locale', + 'config_simple_example', + ]; + + /** + * The installation profile to use with this test. + * + * @var string + */ + protected $profile = 'minimal'; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + // We need more language than default English. + $language = ConfigurableLanguage::createFromLangcode('es'); + $language->save(); + } + + /** + * Aggregate all the tests. + * + * Since this is a functional test, and we don't expect to need isolation + * between these form tests, we'll aggregate them here for speed's sake. That + * way the testing system doesn't have to rebuild a new Drupal for us for each + * test. + */ + public function testFunctional() { + // Please fail this one first. + $this->doTestMainPage(); + $this->doTestConfigSimpleForm(); + } + + /** + * Test the main page. + */ + public function doTestMainPage() { + $assert = $this->assertSession(); + $example_page = Url::fromRoute('config_simple_example.description'); + $this->drupalGet($example_page); + + $assert->pageTextContains('The Config Simple Example module defines a simple translatable config form.'); + $assert->linkExists('Config Simple Form'); + } + + /** + * Test the config simple form. + */ + public function doTestConfigSimpleForm() { + $assert = $this->assertSession(); + $config_page = Url::fromRoute('config_simple_example.settings'); + $this->drupalGet($config_page); + + $assert->fieldEnabled('edit-message'); + $assert->buttonExists('edit-submit'); + + // Ensure the 'Save configuration' action performs the save. + $this->drupalGet($config_page); + $edit = [ + 'message' => 'Message in EN', + ]; + $this->submitForm($edit, 'Save configuration'); + $assert->pageTextContains('Message in EN'); + + // Go to Spanish version. + $es_lang_object = \Drupal::languageManager()->getLanguage('es'); + $config_page_es = Url::fromRoute('config_simple_example.settings', [], ['language' => $es_lang_object]); + $this->drupalGet($config_page_es); + + $assert->fieldEnabled('edit-message'); + $assert->buttonExists('edit-submit'); + + // Ensure the 'Save configuration' action performs the save. + $this->drupalGet($config_page); + $edit = [ + 'message' => 'Message in ES', + ]; + $this->submitForm($edit, 'Save configuration'); + $assert->pageTextContains('Message in ES'); + + // Go back to original English version. + $this->drupalGet($config_page); + $assert->pageTextContains('Message in EN'); + } + +}