From 2b3122421719641729567b1c091c1a308652c18f Mon Sep 17 00:00:00 2001 From: Kedar Khaire Date: Wed, 14 Aug 2024 12:54:48 +0530 Subject: [PATCH] Adding patch for field core module (#1058) --- .github/workflows/php.yml | 2 +- .../src/Functional/DeveloperAppFieldTest.php | 180 ++++++++++++---- tests/src/Functional/DeveloperSyncTest.php | 203 +++++++++++++++--- 3 files changed, 313 insertions(+), 72 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 5348422f3..095b404ba 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -98,7 +98,7 @@ jobs: composer require wikimedia/composer-merge-plugin composer config --json extra.merge-plugin.require '["modules/contrib/apigee_edge/composer.json"]' composer config platform.php ${{ matrix.php-version }} - composer config --json extra.patches."drupal/core" '{ "Support entities that are neither content nor config entities": "https://www.drupal.org/files/issues/2020-12-02/3042467-50.patch", "Add a method to access the original property": "https://www.drupal.org/files/issues/2023-07-22/2839195-105.patch"}' + composer config --json extra.patches."drupal/core" '{ "TypeError: FieldTypePluginManager::createFieldItem() called in FieldStorageConfig.php": "https://www.drupal.org/files/issues/2024-05-27/field-typeerror-3450175-3.patch", "Support entities that are neither content nor config entities": "https://www.drupal.org/files/issues/2020-12-02/3042467-50.patch", "Add a method to access the original property": "https://www.drupal.org/files/issues/2023-07-22/2839195-105.patch"}' composer update --with-all-dependencies composer require --dev phpspec/prophecy-phpunit:^2 composer require --dev drupal/classy:^1.0 diff --git a/tests/src/Functional/DeveloperAppFieldTest.php b/tests/src/Functional/DeveloperAppFieldTest.php index a4748da16..58c546ce2 100644 --- a/tests/src/Functional/DeveloperAppFieldTest.php +++ b/tests/src/Functional/DeveloperAppFieldTest.php @@ -26,6 +26,8 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Url; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Symfony\Component\HttpFoundation\Response; @@ -70,6 +72,27 @@ class DeveloperAppFieldTest extends ApigeeEdgeFunctionalTestBase { */ protected $developerApp; + /** + * Array of list fields. + * + * @var array + */ + protected $listFields = []; + + /** + * Name of the option field. + * + * @var string + */ + protected $fieldName; + + /** + * Admin path to manage field storage settings. + * + * @var string + */ + protected $adminPath; + /** * {@inheritdoc} */ @@ -179,47 +202,6 @@ protected function fieldStorageFormattersTest() { ], 'encoded' => '0.1', ], - strtolower($this->randomMachineName()) => [ - 'type' => 'list_float', - 'settings' => [ - 'settings[allowed_values]' => implode(PHP_EOL, [ - round(M_PI, 10), - round(M_E, 10), - round(M_EULER, 10), - ]), - ], - 'data' => [ - ['value' => round(M_PI, 10)], - ], - 'encoded' => (string) round(M_PI, 10), - ], - strtolower($this->randomMachineName()) => [ - 'type' => 'list_integer', - 'settings' => [ - 'settings[allowed_values]' => implode(PHP_EOL, [1, 2, 3]), - ], - 'data' => [ - ['value' => 2], - ['value' => 3], - ], - 'encoded' => '2,3', - ], - strtolower($this->randomMachineName()) => [ - 'type' => 'list_string', - 'settings' => [ - 'settings[allowed_values]' => implode(PHP_EOL, [ - 'qwer', - 'asdf', - 'zxcv', - ]), - ], - 'data' => [ - ['value' => 'qwer'], - ['value' => 'asdf'], - ['value' => 'zxcv'], - ], - 'encoded' => 'qwer,asdf,zxcv', - ], strtolower($this->randomMachineName()) => [ 'type' => 'string', 'data' => [ @@ -257,6 +239,62 @@ protected function fieldStorageFormattersTest() { ], ]; + $this->listFields = [ + 'list_integer' => [ + 'name' => strtolower($this->randomMachineName()), + 'settings' => [ + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 0, + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => 1, + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'One', + ], + 'data' => [ + 0 => 'Zero', + 1 => 'One' + ], + 'encoded' => '0,1', + ], + 'list_string' => [ + 'name' => strtolower($this->randomMachineName()), + 'settings' => [ + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 'zero', + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => 'one', + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'One', + ], + 'data' => [ + 'zero' => 'Zero', + 'one' => 'One' + ], + 'encoded' => 'zero,one', + ], + 'list_float' => [ + 'name' => strtolower($this->randomMachineName()), + 'settings' => [ + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 0, + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => .5, + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'Point five', + 'field_storage[subform][settings][allowed_values][table][2][item][key]' => 2, + 'field_storage[subform][settings][allowed_values][table][2][item][label]' => 'Two', + ], + 'data' => [ + '0' => 'Zero', + '0.5' => 'Point five', + '2' => 'Two' + ], + 'encoded' => '0.5', + ] + ]; + + // Changes for field of types 'list' fields + // Using field configs to save the fields as issue is faced by FieldUiTestTrait. + foreach ($this->listFields as $list_type => $listData) { + $this->fieldName = 'field_' . $listData['name']; + $this->createOptionsField($list_type); + $this->assertAllowedValuesInput($listData['settings'], $listData['data'], ''); + } + // Add fields to developer app. $add_field_path = Url::fromRoute('apigee_edge.settings.developer_app')->toString(); foreach ($fields as $name => $data) { @@ -587,4 +625,64 @@ protected function assertFieldVisibleOnEntityDisplay(string $app_name, string $f } } + /** + * Helper function to create list field of a given type. + * + * @param string $type + * One of 'list_integer', 'list_float' or 'list_string'. + */ + protected function createOptionsField($type) { + // Create a field. + FieldStorageConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => 'developer_app', + 'type' => $type, + ])->save(); + FieldConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => 'developer_app', + 'bundle' => 'developer_app', + ])->save(); + + \Drupal::service('entity_display.repository') + ->getFormDisplay('developer_app', 'developer_app') + ->setComponent($this->fieldName) + ->save(); + + $this->adminPath = 'admin/config/apigee-edge/app-settings/developer-apps/fields/developer_app.developer_app.' . $this->fieldName; + } + + /** + * Tests an input array for the 'allowed values' form element. + * + * @param array $input + * The input array. + * @param array|string $result + * Either an expected resulting array in + * $field->getSetting('allowed_values'), or an expected error message. + * @param string $message + * Message to display. + * + * @internal + */ + public function assertAllowedValuesInput(array $input, $result, string $message): void { + $this->drupalGet($this->adminPath); + $page = $this->getSession()->getPage(); + $add_button = $page->findButton('Add another item'); + $add_button->click(); + $add_button->click(); + + $this->submitForm($input, 'Save'); + // Verify that the page does not have double escaped HTML tags. + $this->assertSession()->responseNotContains('<'); + + if (is_string($result)) { + $this->assertSession()->pageTextContains($result); + } + else { + $field_storage = FieldStorageConfig::loadByName('developer_app', $this->fieldName); + $this->assertSame($field_storage->getSetting('allowed_values'), $result, $message); + } + } + } diff --git a/tests/src/Functional/DeveloperSyncTest.php b/tests/src/Functional/DeveloperSyncTest.php index 662983603..9e6c14a83 100644 --- a/tests/src/Functional/DeveloperSyncTest.php +++ b/tests/src/Functional/DeveloperSyncTest.php @@ -24,6 +24,8 @@ use Drupal\apigee_edge\Plugin\ApigeeFieldStorageFormat\CSV; use Drupal\apigee_edge\Plugin\ApigeeFieldStorageFormat\JSON; use Drupal\Core\Url; +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\Tests\field_ui\Traits\FieldUiTestTrait; use Drupal\user\Entity\User; use Symfony\Component\Console\Input\ArgvInput; @@ -114,6 +116,13 @@ class DeveloperSyncTest extends ApigeeEdgeFunctionalTestBase { */ protected $fields = []; + /** + * Array of Drupal user list fields. + * + * @var array + */ + protected $listFields = []; + /** * Field name prefix. * @@ -128,6 +137,20 @@ class DeveloperSyncTest extends ApigeeEdgeFunctionalTestBase { */ protected $formatManager; + /** + * Name of the option field. + * + * @var string + */ + protected $fieldName; + + /** + * Admin path to manage field storage settings. + * + * @var string + */ + protected $adminPath; + /** * {@inheritdoc} */ @@ -159,6 +182,10 @@ protected function setUp(): void { $formatter = $this->formatManager->lookupPluginForFieldType($field_type); $this->edgeDevelopers[$mail]->setAttribute($data['name'], $formatter->encode($data['data'])); } + foreach ($this->listFields as $field_type => $data) { + $formatter = $this->formatManager->lookupPluginForFieldType($field_type); + $this->edgeDevelopers[$mail]->setAttribute($data['name'], $formatter->encode($data['odata'])); + } $this->edgeDevelopers[$mail]->setAttribute('invalid_email', 'invalid_email_address'); $this->edgeDevelopers[$mail]->save(); } @@ -171,6 +198,9 @@ protected function setUp(): void { foreach ($this->fields as $field_type => $data) { $user->set($this->fieldNamePrefix . $data['name'], $data['data']); } + foreach ($this->listFields as $field_type => $data) { + $user->set($this->fieldNamePrefix . $data['name'], $data['odata']); + } $user->save(); $this->drupalUsers[$user->getEmail()] = $user; } @@ -183,6 +213,9 @@ protected function setUp(): void { foreach ($this->fields as $field_type => $data) { $user->set($this->fieldNamePrefix . $data['name'], $data['data']); } + foreach ($this->listFields as $field_type => $data) { + $user->set($this->fieldNamePrefix . $data['name'], $data['odata']); + } // Set unlinked field on the user. $user->set($this->fieldNamePrefix . 'invalid_email', 'valid.email@example.com'); // Set valid email field on the user. @@ -195,6 +228,10 @@ protected function setUp(): void { $formatter = $this->formatManager->lookupPluginForFieldType($field_type); $this->modifiedEdgeDevelopers[$user->getEmail()]->setAttribute($data['name'], $formatter->encode($data['data_changed'])); } + foreach ($this->listFields as $field_type => $data) { + $formatter = $this->formatManager->lookupPluginForFieldType($field_type); + $this->modifiedEdgeDevelopers[$user->getEmail()]->setAttribute($data['name'], $formatter->encode($data['data_changed'])); + } // Change first name and last name. $this->modifiedEdgeDevelopers[$user->getEmail()]->setFirstName($this->randomGenerator->word(8)); @@ -213,6 +250,9 @@ protected function setUp(): void { foreach ($this->fields as $field_type => $data) { $user->set($this->fieldNamePrefix . $data['name'], $data['data']); } + foreach ($this->listFields as $field_type => $data) { + $user->set($this->fieldNamePrefix . $data['name'], $data['odata']); + } $user->save(); $this->modifiedDrupalUsers[$user->getEmail()] = $user; @@ -228,6 +268,9 @@ protected function setUp(): void { foreach ($this->fields as $field_type => $data) { $this->modifiedDrupalUsers[$user->getEmail()]->set($this->fieldNamePrefix . $data['name'], $data['data_changed']); } + foreach ($this->listFields as $field_type => $data) { + $this->modifiedDrupalUsers[$user->getEmail()]->set($this->fieldNamePrefix . $data['name'], $data['data_changed']); + } // Change first name, last name and username. $this->modifiedDrupalUsers[$user->getEmail()]->set('first_name', $this->randomGenerator->word(8)); @@ -320,64 +363,104 @@ protected function setUpUserFields() { ['value' => 1], ], ], - 'list_integer' => [ + 'string' => [ 'name' => strtolower($this->randomMachineName()), - 'settings' => [ - 'settings[allowed_values]' => implode(PHP_EOL, [1, 2, 3]), + 'data' => [ + ['value' => $text], ], + 'data_changed' => [ + ['value' => strrev($text)], + ], + ], + 'string_long' => [ + 'name' => strtolower($this->randomMachineName()), 'data' => [ - ['value' => 2], - ['value' => 3], + ['value' => $text], ], 'data_changed' => [ - ['value' => 1], - ['value' => 3], + ['value' => strrev($text)], ], ], - 'list_string' => [ + 'link' => [ + 'name' => strtolower($this->randomMachineName()), + 'data' => $link, + 'data_changed' => $link_changed, + ], + ]; + + $this->listFields = [ + 'list_integer' => [ 'name' => strtolower($this->randomMachineName()), 'settings' => [ - 'settings[allowed_values]' => implode(PHP_EOL, [ - 'qwer', - 'asdf', - 'zxcv', - ]), + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 0, + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => 1, + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'One', ], 'data' => [ - ['value' => 'qwer'], - ['value' => 'asdf'], - ['value' => 'zxcv'], + 0 => 'Zero', + 1 => 'One' + ], + 'odata' => [ + ['value' => 0], + ['value' => 1] ], 'data_changed' => [ - ['value' => 'qwer'], - ['value' => 'asdf'], + ['value' => 2] ], ], - 'string' => [ + 'list_string' => [ 'name' => strtolower($this->randomMachineName()), + 'settings' => [ + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 'zero', + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => 'one', + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'One', + ], 'data' => [ - ['value' => $text], + 'zero' => 'Zero', + 'one' => 'One' + ], + 'odata' => [ + ['value' => 'zero'], + ['value' => 'one'] ], 'data_changed' => [ - ['value' => strrev($text)], + ['value' => 'two'] ], ], - 'string_long' => [ + 'list_float' => [ 'name' => strtolower($this->randomMachineName()), + 'settings' => [ + 'field_storage[subform][settings][allowed_values][table][0][item][key]' => 0, + 'field_storage[subform][settings][allowed_values][table][0][item][label]' => 'Zero', + 'field_storage[subform][settings][allowed_values][table][1][item][key]' => .5, + 'field_storage[subform][settings][allowed_values][table][1][item][label]' => 'Point five', + 'field_storage[subform][settings][allowed_values][table][2][item][key]' => 2, + 'field_storage[subform][settings][allowed_values][table][2][item][label]' => 'Two', + ], 'data' => [ - ['value' => $text], + '0' => 'Zero', + '0.5' => 'Point five', + '2' => 'Two' + ], + 'odata' => [ + ['value' => 0.5] ], 'data_changed' => [ - ['value' => strrev($text)], + ['value' => 0.8] ], - ], - 'link' => [ - 'name' => strtolower($this->randomMachineName()), - 'data' => $link, - 'data_changed' => $link_changed, - ], + ] ]; + // Changes for field of types 'list' fields + // Using field configs to save the fields as issue is faced by FieldUiTestTrait. + foreach ($this->listFields as $list_type => $listData) { + $this->fieldName = 'field_' . $listData['name']; + $this->createOptionsField($list_type); + $this->assertAllowedValuesInput($listData['settings'], $listData['data'], ''); + } + foreach ($this->fields as $field_type => $data) { $this->fieldUIAddNewField( Url::fromRoute('entity.user.admin_form')->toString(), @@ -611,4 +694,64 @@ public function testCliDeveloperSync() { $this->verify(); } + /** + * Helper function to create list field of a given type. + * + * @param string $type + * One of 'list_integer', 'list_float' or 'list_string'. + */ + protected function createOptionsField($type) { + // Create a field. + FieldStorageConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => 'user', + 'type' => $type, + ])->save(); + FieldConfig::create([ + 'field_name' => $this->fieldName, + 'entity_type' => 'user', + 'bundle' => 'user', + ])->save(); + + \Drupal::service('entity_display.repository') + ->getFormDisplay('user', 'user') + ->setComponent($this->fieldName) + ->save(); + + $this->adminPath = 'admin/config/people/accounts/fields/user.user.' . $this->fieldName; + } + + /** + * Tests an input array for the 'allowed values' form element. + * + * @param array $input + * The input array. + * @param array|string $result + * Either an expected resulting array in + * $field->getSetting('allowed_values'), or an expected error message. + * @param string $message + * Message to display. + * + * @internal + */ + public function assertAllowedValuesInput(array $input, $result, string $message): void { + $this->drupalGet($this->adminPath); + $page = $this->getSession()->getPage(); + $add_button = $page->findButton('Add another item'); + $add_button->click(); + $add_button->click(); + + $this->submitForm($input, 'Save'); + // Verify that the page does not have double escaped HTML tags. + $this->assertSession()->responseNotContains('<'); + + if (is_string($result)) { + $this->assertSession()->pageTextContains($result); + } + else { + $field_storage = FieldStorageConfig::loadByName('user', $this->fieldName); + $this->assertSame($field_storage->getSetting('allowed_values'), $result, $message); + } + } + }