ConfigWithTranslationTest.php 12.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
<?php

namespace Drupal\Tests\config_ignore\Functional;

use Drupal\Component\FileCache\FileCache;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\BrowserTestBase;
use Drush\TestTraits\DrushTestTrait;

/**
 * Tests config_ignore with translated configurations.
 *
13 14
 * This test is using Drush to perform the export/import operations in order to
 * test with a real config import/export tool.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 *
 * @group config_ignore
 */
class ConfigWithTranslationTest extends BrowserTestBase {

  use DrushTestTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'config_ignore',
    'config_translation',
    'language',
  ];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * {@inheritdoc}
   */
  protected function setUp() {
    parent::setUp();

    ConfigurableLanguage::createFromLangcode('ro')->save();

44
    // Add a translation to user.role.anonymous and user.role.authenticated.
45
    $this->translateConfig('user.role.anonymous', 'label', 'Utilizator anonim', 'ro');
46
    $this->translateConfig('user.role.authenticated', 'label', 'Utilizator autentificat', 'ro');
47 48 49 50 51 52 53 54

    // Export the default configuration.
    $this->drush('config:export', [], ['yes' => NULL]);

    // Check that configs (and translations) were exported in the sync store.
    $this->assertExportedValue('user.settings', 'anonymous', 'Anonymous');
    $this->assertExportedValue('user.role.anonymous', 'label', 'Anonymous user');
    $this->assertExportedValue('user.role.anonymous', 'label', 'Utilizator anonim', 'ro');
55 56 57 58
    $this->assertExportedValue('user.role.authenticated', 'label', 'Authenticated user');
    $this->assertExportedValue('user.role.authenticated', 'weight', 1);
    $this->assertExportedValue('user.role.authenticated', 'is_admin', FALSE);
    $this->assertExportedValue('user.role.authenticated', 'label', 'Utilizator autentificat', 'ro');
59

60 61 62 63 64 65
    // Ignore user.role.anonymous and two keys from user.role.authenticated.
    $this->config('config_ignore.settings')->set('ignored_config_entities', [
      'user.role.anonymous',
      'user.role.authenticated:weight',
      'user.role.authenticated:is_admin',
    ])->save();
66 67 68 69 70 71 72 73 74
  }

  /**
   * Tests config status.
   */
  public function testConfigStatus() {
    // Change configurations in the active store.
    $this->config('user.settings')->set('anonymous', 'Visitor')->save();
    $this->config('user.role.anonymous')->set('label', 'Visitor')->save();
75 76 77 78 79 80
    $this->config('user.role.authenticated')
      ->set('label', 'Authenticated')
      ->set('weight', 2)
      ->set('is_admin', TRUE)
      ->save();
    // Change translations of user.role.anonymous and user.role.authenticated.
81
    $this->translateConfig('user.role.anonymous', 'label', 'Vizitator', 'ro');
82
    $this->translateConfig('user.role.authenticated', 'label', 'Logat', 'ro');
83

84
    // Get config status.
85 86 87
    $this->drush('config:status', [], ['format' => 'json']);
    $diff = (array) $this->getOutputFromJSON();

88
    // Check that only config_ignore.settings and user.settings are shown.
89
    $this->assertCount(3, $diff);
90 91 92 93
    $this->assertArrayHasKey('config_ignore.settings', $diff);
    $this->assertSame(['name' => 'config_ignore.settings', 'state' => 'Different'], $diff['config_ignore.settings']);
    $this->assertArrayHasKey('user.settings', $diff);
    $this->assertSame(['name' => 'user.settings', 'state' => 'Different'], $diff['user.settings']);
94 95
    $this->assertArrayHasKey('user.role.authenticated', $diff);
    $this->assertSame(['name' => 'user.role.authenticated', 'state' => 'Different'], $diff['user.role.authenticated']);
96 97 98 99 100 101 102 103 104
  }

  /**
   * Tests config export.
   */
  public function testConfigExport() {
    // Change configurations in the active store.
    $this->config('user.settings')->set('anonymous', 'Visitor')->save();
    $this->config('user.role.anonymous')->set('label', 'Visitor')->save();
105 106 107 108 109 110
    $this->config('user.role.authenticated')
      ->set('label', 'Authenticated')
      ->set('weight', 2)
      ->set('is_admin', TRUE)
      ->save();
    // Change translations of user.role.anonymous and user.role.authenticated.
111
    $this->translateConfig('user.role.anonymous', 'label', 'Vizitator', 'ro');
112
    $this->translateConfig('user.role.authenticated', 'label', 'Logat', 'ro');
113 114 115 116 117 118 119 120

    // Export changes.
    $this->drush('config:export', [], ['yes' => NULL]);

    // Check that user.settings changes were exported.
    $this->assertExportedValue('user.settings', 'anonymous', 'Visitor');
    // Check that the main user.role.anonymous.yml file was not overridden.
    $this->assertExportedValue('user.role.anonymous', 'label', 'Anonymous user');
121
    // Check that the translated version was not overridden.
122
    $this->assertExportedValue('user.role.anonymous', 'label', 'Utilizator anonim', 'ro');
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
    // Check that user.role.authenticated changes were exported.
    $this->assertExportedValue('user.role.authenticated', 'label', 'Authenticated');
    $this->assertExportedValue('user.role.authenticated', 'weight', 1);
    $this->assertExportedValue('user.role.authenticated', 'is_admin', FALSE);
    // Check that the translated version has been exported too.
    $this->assertExportedValue('user.role.authenticated', 'label', 'Logat', 'ro');

    // Delete user.role.authenticated from sync storage in order to test again
    // when the destination is missed.
    $sync_storage = $this->getSyncStorage();
    $sync_storage->delete('user.role.authenticated');

    // Re-export changes.
    $this->drush('config:export', [], ['yes' => NULL]);

    $data = $sync_storage->read('user.role.authenticated');
    // Check that weight & is_admin keys were ignored on the new created config.
    $this->assertArrayNotHasKey('weight', $data);
    $this->assertArrayNotHasKey('is_admin', $data);
142 143 144 145 146 147
  }

  /**
   * Tests config import.
   */
  public function testConfigImport() {
148 149 150 151 152 153 154 155 156 157 158
    // Add the config_ignore.settings changes in the sync store. Remember that
    // the ignore patterns were added only in the active store, in ::setUp(),
    // but were never exported in sync. Otherwise the values will be reverted,
    // later, in the first config import.
    // @see self::setUp()
    $this->setConfigSyncValue('config_ignore.settings', 'ignored_config_entities', [
      'user.role.anonymous',
      'user.role.authenticated:weight',
      'user.role.authenticated:is_admin',
    ]);

159 160 161
    // Change configurations in the sync store.
    $this->setConfigSyncValue('user.settings', 'anonymous', 'Visitor');
    $this->setConfigSyncValue('user.role.anonymous', 'label', 'Visitor');
162 163 164 165
    $this->setConfigSyncValue('user.role.authenticated', 'label', 'Authenticated');
    $this->setConfigSyncValue('user.role.authenticated', 'weight', 2);
    $this->setConfigSyncValue('user.role.authenticated', 'is_admin', TRUE);
    // Change translations of user.role.anonymous and user.role.authenticated.
166
    $this->setConfigSyncValue('user.role.anonymous', 'label', 'Vizitator', 'ro');
167
    $this->setConfigSyncValue('user.role.authenticated', 'label', 'Logat', 'ro');
168 169 170 171 172 173 174

    // Check that user.settings was changed in the sync store.
    $this->assertExportedValue('user.settings', 'anonymous', 'Visitor');
    // Check that main user.role.anonymous.yml was changed in the sync store.
    $this->assertExportedValue('user.role.anonymous', 'label', 'Visitor');
    // Check that the translated override was changed in the sync store.
    $this->assertExportedValue('user.role.anonymous', 'label', 'Vizitator', 'ro');
175 176 177
    $this->assertExportedValue('user.role.authenticated', 'label', 'Authenticated');
    $this->assertExportedValue('user.role.authenticated', 'weight', 2);
    $this->assertExportedValue('user.role.authenticated', 'is_admin', TRUE);
178 179 180

    // Import changes.
    $this->drush('config:import', [], ['yes' => NULL]);
181 182 183
    // As the tests are running in the same request we manually clear the static
    // cache of the config objects.
    \Drupal::configFactory()->reset();
184 185 186 187 188

    // Check that user.settings has been overridden by import.
    $this->assertSame('Visitor', $this->config('user.settings')->get('anonymous'));
    // Check that user.role.anonymous has been preserved.
    $this->assertSame('Anonymous user', $this->config('user.role.anonymous')->get('label'));
189 190 191 192 193
    // Check that user.role.authenticated has been overridden by import.
    $this->assertSame('Authenticated', $this->config('user.role.authenticated')->get('label'));
    $this->assertEquals(1, $this->config('user.role.authenticated')->get('weight'));
    $this->assertFalse($this->config('user.role.authenticated')->get('is_admin'));

194
    // Check that the user.role.anonymous translation has been also preserved.
195 196 197 198 199
    $language_manager = \Drupal::languageManager();
    $original_language = $language_manager->getConfigOverrideLanguage();
    /** @var \Drupal\language\Config\LanguageConfigOverride $translated */
    $translated = $language_manager->getLanguageConfigOverride('ro', 'user.role.anonymous');
    $this->assertSame('Utilizator anonim', $translated->get('label'));
200 201
    $translated = $language_manager->getLanguageConfigOverride('ro', 'user.role.authenticated');
    $this->assertSame('Logat', $translated->get('label'));
202
    $language_manager->setConfigOverrideLanguage($original_language);
203 204 205 206 207 208 209 210 211 212 213 214 215

    /** @var \Drupal\Core\Config\StorageInterface $active_storage */
    $active_storage = \Drupal::service('config.storage');
    // Remove the config in order to test again when the destination is missed.
    $active_storage->delete('user.role.authenticated');

    // Re-import changes.
    $this->drush('config:import', [], ['yes' => NULL]);
    \Drupal::configFactory()->reset('user.role.authenticated');

    $this->assertSame('Authenticated', $this->config('user.role.authenticated')->get('label'));
    $this->assertEquals(1, $this->config('user.role.authenticated')->get('weight'));
    $this->assertFalse((bool) $this->config('user.role.authenticated')->get('is_admin'));
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
  }

  /**
   * Asserts that a given value for a given config exists in sync.
   *
   * @param string $config_name
   *   The config name.
   * @param string $key
   *   The key of the config value. It only supports top level keys.
   * @param mixed $value
   *   The value to be checked.
   * @param string|null $langcode
   *   (optional) If passed, the value will be checked in the $langcode language
   *   collection.
   */
  protected function assertExportedValue($config_name, $key, $value, $langcode = NULL) {
    // The file config storage is using file cache for performance reasons. As
    // the tests are running in the same request, the file static cache is not
    // cleared. We do this explicitly before making any assertions regarding
    // exported files.
    FileCache::reset();

    $sync_storage = $this->getSyncStorage($langcode);
    // Check that the destination file has not been deleted.
    $this->assertTrue($sync_storage->exists($config_name));
    // Check that the changed value has been exported.
    $data = $sync_storage->read($config_name);
    $this->assertSame($value, $data[$key]);
  }

  /**
   * Translates $config_name:$key into $langcode language.
   *
   * @param string $config_name
   *   The config name.
   * @param string $key
252
   *   The config key to be translated. It only supports top level keys.
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
   * @param string $value
   *   The translated value.
   * @param string $langcode
   *   The langcode.
   */
  protected function translateConfig($config_name, $key, $value, $langcode) {
    $language_manager = \Drupal::languageManager();
    $original_language = $language_manager->getConfigOverrideLanguage();
    /** @var \Drupal\language\Config\LanguageConfigOverride $translated */
    $translated = $language_manager->getLanguageConfigOverride($langcode, $config_name);
    $translated->set($key, $value)->save();
    $language_manager->setConfigOverrideLanguage($original_language);
  }

  /**
   * Sets a config value in the sync store.
   *
   * @param string $config_name
   *   The config name.
   * @param string $key
   *   The key of the config value to be set. It only supports top level keys.
   * @param mixed $value
   *   The value to be set.
   * @param string|null $langcode
   *   (optional) If passed, the value will be set in the $langcode language
   *   collection.
   */
  protected function setConfigSyncValue($config_name, $key, $value, $langcode = NULL) {
    $sync_storage = $this->getSyncStorage($langcode);
    $data = $sync_storage->read($config_name);
    $data[$key] = $value;
    $sync_storage->write($config_name, $data);
  }

  /**
   * Returns the config sync storage.
   *
   * @param string|null $langcode
291 292
   *   (optional) The language collection language code or NULL for the default
   *   collection.
293 294 295 296
   *
   * @return \Drupal\Core\Config\StorageInterface
   *   The config sync storage.
   */
297
  protected function getSyncStorage($langcode = NULL) {
298 299 300 301 302 303 304 305
    $sync_storage = \Drupal::service('config.storage.sync');
    if ($langcode) {
      $sync_storage = $sync_storage->createCollection("language.{$langcode}");
    }
    return $sync_storage;
  }

}