Skip to content
Snippets Groups Projects
Commit 578a7ba1 authored by catch's avatar catch
Browse files

Issue #2002174 by Wim Leers, xjm, fago, effulgentsia, catch, smustgrave: Allow...

Issue #2002174 by Wim Leers, xjm, fago, effulgentsia, catch, smustgrave: Allow vocabularies to be validated via the API, not just during form submissions

(cherry picked from commit 1be0f07e)
parent d95dc67e
Branches
Tags
28 merge requests!11958Issue #3490507 by alexpott, smustgrave: Fix bogus mocking in...,!11769Issue #3517987: Add option to contextual filters to encode slashes in query parameter.,!11185Issue #3477324 by andypost, alexpott: Fix usage of str_getcsv() and fgetcsv() for PHP 8.4,!10602Issue #3438769 by vinmayiswamy, antonnavi, michelle, amateescu: Sub workspace does not clear,!10301Issue #3469309 by mstrelan, smustgrave, moshe weitzman: Use one-time login...,!10187Issue #3487488 by dakwamine: ExtensionMimeTypeGuesser::guessMimeType must support file names with "0" (zero) like foo.0.zip,!9944Issue #3483353: Consider making the createCopy config action optionally fail...,!9929Issue #3445469 by pooja_sharma, smustgrave: Add additional test coverage for...,!9787Resolve issue 3479427 - bootstrap barrio issue under Windows,!9742Issue #3463908 by catch, quietone: Split OptionsFieldUiTest into two,!9526Issue #3458177 by mondrake, catch, quietone, godotislate, longwave, larowlan,...,!8738Issue #3424162 by camilledavis, dineshkumarbollu, smustgrave: Claro...,!8704Make greek characters available in ckeditor5,!8597Draft: Issue #3442259 by catch, quietone, dww: Reduce time of Migrate Upgrade tests...,!8533Issue #3446962 by kim.pepper: Remove incorrectly added...,!8517Issue #3443748 by NexusNovaz, smustgrave: Testcase creates false positive,!8325Update file Sort.php,!8095Expose document root on install,!7930Resolve #3427374 "Taxonomytid viewsargumentdefault plugin",!7627Issue #3439440 by nicxvan, Binoli Lalani, longwave: Remove country support from DateFormatter,!7445Issue #3440169: When using drupalGet(), provide an associative array for $headers,!7401#3271894 Fix documented StreamWrapperInterface return types for realpath() and dirname(),!7384Add constraints to system.advisories,!7078Issue #3320569 by Spokje, mondrake, smustgrave, longwave, quietone, Lendude,...,!6622Issue #2559833 by piggito, mohit_aghera, larowlan, guptahemant, vakulrai,...,!6502Draft: Resolve #2938524 "Plach testing issue",!38582585169-10.1.x,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key
Pipeline #104332 passed
Pipeline: drupal

#104347

    Pipeline: drupal

    #104341

      Pipeline: drupal

      #104338

        +1
        Showing
        with 175 additions and 13 deletions
        ......@@ -1323,3 +1323,18 @@ function node_comment_delete($comment) {
        function node_config_translation_info_alter(&$info) {
        $info['node_type']['class'] = 'Drupal\node\ConfigTranslation\NodeTypeMapper';
        }
        /**
        * Implements hook_ENTITY_TYPE_presave().
        */
        function node_node_type_presave(NodeTypeInterface $node_type) {
        // Content types' `help` and `description` fields must be stored as NULL
        // at the config level if they are empty.
        // @see node_post_update_set_node_type_description_and_help_to_null()
        if (trim($node_type->getDescription()) === '') {
        $node_type->set('description', NULL);
        }
        if (trim($node_type->getHelp()) === '') {
        $node_type->set('help', NULL);
        }
        }
        ......@@ -14,15 +14,8 @@
        function node_post_update_set_node_type_description_and_help_to_null(array &$sandbox): void {
        \Drupal::classResolver(ConfigEntityUpdater::class)
        ->update($sandbox, 'node_type', function (NodeTypeInterface $node_type): bool {
        // Content types' `help` and `description` fields must be stored as NULL
        // at the config level if they are empty.
        if (trim($node_type->getDescription()) === '') {
        $node_type->set('description', NULL);
        }
        if (trim($node_type->getHelp()) === '') {
        $node_type->set('help', NULL);
        }
        return TRUE;
        // @see node_node_type_presave()
        return trim($node_type->getDescription()) === '' || trim($node_type->getHelp()) === '';
        });
        }
        ......
        ......@@ -22,6 +22,8 @@ taxonomy.settings:
        taxonomy.vocabulary.*:
        type: config_entity
        label: 'Vocabulary'
        constraints:
        FullyValidatable: ~
        mapping:
        name:
        type: required_label
        ......@@ -35,11 +37,18 @@ taxonomy.vocabulary.*:
        Length:
        max: 32
        description:
        type: label
        type: text
        label: 'Description'
        nullable: true
        constraints:
        NotBlank:
        allowNull: true
        weight:
        type: integer
        label: 'Weight'
        # A weight can be any integer, positive or negative.
        constraints:
        NotNull: []
        new_revision:
        type: boolean
        label: 'Whether a new revision should be created by default'
        ......
        ......@@ -80,9 +80,9 @@ class Vocabulary extends ConfigEntityBundleBase implements VocabularyInterface {
        /**
        * Description of the vocabulary.
        *
        * @var string
        * @var string|null
        */
        protected $description;
        protected $description = NULL;
        /**
        * The weight of this vocabulary in relation to other vocabularies.
        ......@@ -102,7 +102,7 @@ public function id() {
        * {@inheritdoc}
        */
        public function getDescription() {
        return $this->description;
        return $this->description ?? '';
        }
        /**
        ......
        <?php
        declare(strict_types=1);
        namespace Drupal\taxonomy\Plugin\migrate\destination;
        use Drupal\migrate\Plugin\migrate\destination\EntityConfigBase;
        use Drupal\migrate\Row;
        /**
        * @MigrateDestination(
        * id = "entity:taxonomy_vocabulary"
        * )
        */
        class EntityTaxonomyVocabulary extends EntityConfigBase {
        /**
        * {@inheritdoc}
        */
        public function getEntity(Row $row, array $old_destination_id_values) {
        /** @var \Drupal\taxonomy\VocabularyInterface $vocabulary */
        $vocabulary = parent::getEntity($row, $old_destination_id_values);
        // Config schema does not allow description to be empty.
        if (trim($vocabulary->getDescription()) === '') {
        $vocabulary->set('description', NULL);
        }
        return $vocabulary;
        }
        }
        ......@@ -42,6 +42,21 @@ public static function create(ContainerInterface $container) {
        );
        }
        /**
        * {@inheritdoc}
        */
        public function buildEntity(array $form, FormStateInterface $form_state) {
        /** @var \Drupal\taxonomy\VocabularyInterface $entity */
        $entity = parent::buildEntity($form, $form_state);
        // The description cannot be an empty string.
        if (trim($form_state->getValue('description')) === '') {
        $entity->set('description', NULL);
        }
        return $entity;
        }
        /**
        * {@inheritdoc}
        */
        ......
        ......@@ -11,6 +11,7 @@
        use Drupal\Core\Routing\RouteMatchInterface;
        use Drupal\Core\Url;
        use Drupal\taxonomy\Entity\Term;
        use Drupal\taxonomy\VocabularyInterface;
        /**
        * Implements hook_help().
        ......@@ -279,3 +280,15 @@ function taxonomy_taxonomy_term_delete(Term $term) {
        /**
        * @} End of "defgroup taxonomy_index".
        */
        /**
        * Implements hook_ENTITY_TYPE_presave().
        */
        function taxonomy_taxonomy_vocabulary_presave(VocabularyInterface $vocabulary) {
        // Vocabularies' `description` field must be stored as NULL at the config
        // level if it is empty.
        // @see taxonomy_post_update_set_vocabulary_description_to_null()
        if (trim($vocabulary->getDescription()) === '') {
        $vocabulary->set('description', NULL);
        }
        }
        ......@@ -6,6 +6,7 @@
        */
        use Drupal\Core\Config\Entity\ConfigEntityUpdater;
        use Drupal\taxonomy\VocabularyInterface;
        /**
        * Implements hook_removed_post_updates().
        ......@@ -31,3 +32,14 @@ function taxonomy_post_update_set_new_revision(&$sandbox = NULL) {
        return TRUE;
        });
        }
        /**
        * Converts empty `description` in vocabularies to NULL.
        */
        function taxonomy_post_update_set_vocabulary_description_to_null(array &$sandbox): void {
        \Drupal::classResolver(ConfigEntityUpdater::class)
        ->update($sandbox, 'taxonomy_vocabulary', function (VocabularyInterface $vocabulary): bool {
        // @see taxonomy_taxonomy_vocabulary_presave()
        return trim($vocabulary->getDescription()) === '';
        });
        }
        <?php
        /**
        * @file
        * Empties the description of the `tags` vocabulary.
        */
        use Drupal\Core\Database\Database;
        $connection = Database::getConnection();
        $data = $connection->select('config')
        ->condition('name', 'taxonomy.vocabulary.tags')
        ->fields('config', ['data'])
        ->execute()
        ->fetchField();
        $data = unserialize($data);
        $data['description'] = "\n";
        $connection->update('config')
        ->condition('name', 'taxonomy.vocabulary.tags')
        ->fields([
        'data' => serialize($data),
        ])
        ->execute();
        <?php
        declare(strict_types=1);
        namespace Drupal\Tests\taxonomy\Functional\Update;
        use Drupal\FunctionalTests\Update\UpdatePathTestBase;
        use Drupal\taxonomy\Entity\Vocabulary;
        /**
        * Tests the upgrade path for making vocabularies' description NULL.
        *
        * @group taxonomy
        * @see taxonomy_post_update_set_vocabulary_description_to_null()
        */
        class NullDescriptionTest extends UpdatePathTestBase {
        /**
        * {@inheritdoc}
        */
        protected function setDatabaseDumpFiles() {
        $this->databaseDumpFiles = [
        __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-9.4.0.filled.standard.php.gz',
        __DIR__ . '/../../../fixtures/update/remove-description-from-tags-vocabulary.php',
        ];
        }
        /**
        * Tests the upgrade path for updating empty description to NULL.
        */
        public function testRunUpdates(): void {
        $vocabulary = Vocabulary::load('tags');
        $this->assertInstanceOf(Vocabulary::class, $vocabulary);
        $this->assertSame("\n", $vocabulary->get('description'));
        $this->runUpdates();
        $vocabulary = Vocabulary::load('tags');
        $this->assertInstanceOf(Vocabulary::class, $vocabulary);
        $this->assertNull($vocabulary->get('description'));
        $this->assertSame('', $vocabulary->getDescription());
        }
        }
        ......@@ -12,6 +12,11 @@
        */
        class VocabularyValidationTest extends ConfigEntityValidationTestBase {
        /**
        * {@inheritdoc}
        */
        protected static array $propertiesWithOptionalValues = ['description'];
        /**
        * {@inheritdoc}
        */
        ......
        0% Loading or .
        You are about to add 0 people to the discussion. Proceed with caution.
        Please register or to comment