Skip to content

Commit d9ef959

Browse files
committed
feat: #3589846 Save-time validation enforcement, stamp infrastructure, and cron scanning
Squash of validity stamp foundation work: stamp table, ValidityStampWriter, save-time enforcement toggle, orphan cleanup, cron queue worker, and post-update hook for migration.
1 parent 41fae55 commit d9ef959

42 files changed

Lines changed: 6158 additions & 56 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cspell-project-words.txt‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ endlink
1111
expirable
1212
fieldable
1313
langcode
14+
langcodes
15+
onecol
1416
patternkit
17+
presaved
18+
varchar
1519
predelete
1620
prophesize
1721
revisionable
@@ -50,6 +54,8 @@ rulesets
5054
styleguides
5155
subpattern
5256
subschema
57+
upsert
58+
upserts
5359
wysiwygs
5460

5561
# CSS classes

‎.cspell.json‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
"version": "0.2",
33
"language": "en",
44
"words": [],
5+
"flagWords": [
6+
"blacklist",
7+
"blacklists",
8+
"blacklisted",
9+
"e-mail",
10+
"grey",
11+
"queuing",
12+
"whitelist",
13+
"whitelists",
14+
"whitelisted"
15+
],
516
"dictionaries": ["project-words", "php", "css", "html", "typescript"],
617
"dictionaryDefinitions": [
718
{

‎.ddev/commands/web/symlink-project‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env bash
22

3-
#ddev-generated
43
## Command provided by https://github.com/ddev/ddev-drupal-contrib
54
## Description: Symlink project files into the configured location (defaults to `web/modules/custom/[PROJECT_NAME]`)
65
## Usage: symlink-project [flags] [args]
@@ -25,3 +24,7 @@ fi
2524
export DRUPAL_PROJECT_FOLDER=${DDEV_DOCROOT}/${DRUPAL_PROJECTS_PATH}/${DDEV_SITENAME//-/_}
2625
php symlink_project.php
2726
rm -f symlink_project.php
27+
28+
# Remove stale .worktrees symlink created by symlink-project to prevent PHPUnit
29+
# from following it and loading stale class versions from worktrees.
30+
rm -f "${DRUPAL_PROJECT_FOLDER}/.worktrees"

‎config/install/patternkit.settings.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ patternkit_json_editor_disable_properties_buttons: false
88
patternkit_json_editor_disable_edit_json_button: true
99
patternkit_json_editor_cache_schemas: false
1010
entity_cache_tag_invalidation: false
11+
render_validation_on_save: true

‎config/schema/patternkit.schema.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ patternkit.settings:
3131
entity_cache_tag_invalidation:
3232
type: boolean
3333
label: 'Boolean determining whether Pattern entity cache tags are invalidated during Pattern updates.'
34+
render_validation_on_save:
35+
type: boolean
36+
label: 'Boolean determining whether invalid pattern configuration is blocked at save time.'
3437
patternkit_json_editor_wysiwyg:
3538
type: string
3639
label: 'String selecting the WYSIWYG tool to use in the JSON Editor.'

‎modules/patternkit_example/lib/patternkit/src/components/media_combined_embed/media_combined_embed.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
"$ref": "@patternkit/components/media_video_embed/media_video_embed"
2323
}
2424
},
25-
"required": ["name"],
25+
"required": [],
2626
"additionalProperties": false
2727
}

‎modules/patternkit_example/lib/patternkit/src/components/media_image_embed/media_image_embed.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
"format": "image-media"
2121
}
2222
},
23-
"required": ["name", "image"],
23+
"required": ["image"],
2424
"additionalProperties": false
2525
}

‎modules/patternkit_example/lib/patternkit/src/components/media_video_embed/media_video_embed.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
"format": "video-media"
2121
}
2222
},
23-
"required": ["name", "video"],
23+
"required": ["video"],
2424
"additionalProperties": false
2525
}

‎modules/patternkit_example/lib/patternkit/src/components/media_wrapper/media_wrapper.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
}
3030
}
3131
},
32-
"required": ["name"],
32+
"required": [],
3333
"additionalProperties": false
3434
}

‎patternkit.install‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,86 @@ function patternkit_uninstall(bool $is_syncing): void {
3333
// Cleanup the update results collection value if it exists.
3434
\Drupal::keyValue(LayoutUpdateBatchManager::RESULTS_COLLECTION)
3535
->deleteAll();
36+
37+
$schema = \Drupal::database()->schema();
38+
if ($schema->tableExists('patternkit_block_validity')) {
39+
$schema->dropTable('patternkit_block_validity');
40+
}
41+
}
42+
43+
/**
44+
* Implements hook_schema().
45+
*/
46+
function patternkit_schema(): array {
47+
$schema['patternkit_block_validity'] = [
48+
'description' => 'Validity stamps for patternkit_block translations (published content index).',
49+
'fields' => [
50+
'block_entity_id' => [
51+
'type' => 'int',
52+
'unsigned' => TRUE,
53+
'not null' => TRUE,
54+
'description' => 'The patternkit_block entity ID.',
55+
],
56+
'langcode' => [
57+
'type' => 'varchar_ascii',
58+
'length' => 12,
59+
'not null' => TRUE,
60+
'description' => 'The translation language code.',
61+
],
62+
'block_revision_id' => [
63+
'type' => 'int',
64+
'unsigned' => TRUE,
65+
'not null' => TRUE,
66+
'description' => 'The block revision ID at validation time.',
67+
],
68+
'pattern_revision_id' => [
69+
'type' => 'int',
70+
'unsigned' => TRUE,
71+
'not null' => TRUE,
72+
'description' => 'The pattern revision ID used when validating.',
73+
],
74+
'is_valid' => [
75+
'type' => 'int',
76+
'size' => 'tiny',
77+
'not null' => TRUE,
78+
'default' => 0,
79+
'description' => 'Whether content validated successfully.',
80+
],
81+
'has_tokens' => [
82+
'type' => 'int',
83+
'size' => 'tiny',
84+
'not null' => TRUE,
85+
'default' => 0,
86+
'description' => 'Whether token-shaped values were present at stamp time.',
87+
],
88+
'validated_at' => [
89+
'type' => 'int',
90+
'not null' => TRUE,
91+
'description' => 'Unix timestamp when validation ran.',
92+
],
93+
'stamp_source' => [
94+
'type' => 'varchar_ascii',
95+
'length' => 32,
96+
'not null' => TRUE,
97+
'default' => 'save',
98+
'description' => 'Origin of the stamp (save, cron_scan, etc.).',
99+
],
100+
'component_uuid' => [
101+
'type' => 'varchar_ascii',
102+
'length' => 128,
103+
'not null' => FALSE,
104+
'description' => 'Layout Builder SectionComponent UUID when known.',
105+
],
106+
],
107+
'primary key' => ['block_entity_id', 'langcode'],
108+
'indexes' => [
109+
'block_validity_is_valid' => ['is_valid'],
110+
'block_validity_pattern_revision' => ['pattern_revision_id'],
111+
'block_validity_component_uuid' => ['component_uuid'],
112+
],
113+
];
114+
115+
return $schema;
36116
}
37117

38118
/**
@@ -681,3 +761,15 @@ function patternkit_update_10310(): string {
681761
);
682762
return t('Restored reusable field storage for the 9.1.x migration window.');
683763
}
764+
765+
/**
766+
* Adds the patternkit_block_validity table for block validity stamps.
767+
*/
768+
function patternkit_update_10311(): void {
769+
$schema = patternkit_schema();
770+
$table = 'patternkit_block_validity';
771+
$database = \Drupal::database();
772+
if (!$database->schema()->tableExists($table)) {
773+
$database->schema()->createTable($table, $schema[$table]);
774+
}
775+
}

0 commit comments

Comments
 (0)