@wordpress/block-library 8.20.1 → 8.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +12 -0
  3. package/build/block/index.js +2 -1
  4. package/build/block/index.js.map +1 -1
  5. package/build/code/edit.native.js +8 -2
  6. package/build/code/edit.native.js.map +1 -1
  7. package/build/cover/deprecated.js +110 -1
  8. package/build/cover/deprecated.js.map +1 -1
  9. package/build/cover/edit/index.js +9 -3
  10. package/build/cover/edit/index.js.map +1 -1
  11. package/build/cover/edit/inspector-controls.js +1 -2
  12. package/build/cover/edit/inspector-controls.js.map +1 -1
  13. package/build/cover/index.js +0 -3
  14. package/build/cover/index.js.map +1 -1
  15. package/build/cover/save.js +2 -1
  16. package/build/cover/save.js.map +1 -1
  17. package/build/cover/shared.js +1 -1
  18. package/build/cover/shared.js.map +1 -1
  19. package/build/footnotes/index.js +1 -0
  20. package/build/footnotes/index.js.map +1 -1
  21. package/build/form/edit.js +138 -0
  22. package/build/form/edit.js.map +1 -0
  23. package/build/form/index.js +92 -0
  24. package/build/form/index.js.map +1 -0
  25. package/build/form/init.js +13 -0
  26. package/build/form/init.js.map +1 -0
  27. package/build/form/save.js +28 -0
  28. package/build/form/save.js.map +1 -0
  29. package/build/form/utils.js +24 -0
  30. package/build/form/utils.js.map +1 -0
  31. package/build/form/variations.js +95 -0
  32. package/build/form/variations.js.map +1 -0
  33. package/build/form/view.js +42 -0
  34. package/build/form/view.js.map +1 -0
  35. package/build/form-input/edit.js +124 -0
  36. package/build/form-input/edit.js.map +1 -0
  37. package/build/form-input/index.js +105 -0
  38. package/build/form-input/index.js.map +1 -0
  39. package/build/form-input/init.js +13 -0
  40. package/build/form-input/init.js.map +1 -0
  41. package/build/form-input/save.js +87 -0
  42. package/build/form-input/save.js.map +1 -0
  43. package/build/form-input/variations.js +93 -0
  44. package/build/form-input/variations.js.map +1 -0
  45. package/build/form-submission-notification/edit.js +59 -0
  46. package/build/form-submission-notification/edit.js.map +1 -0
  47. package/build/form-submission-notification/index.js +56 -0
  48. package/build/form-submission-notification/index.js.map +1 -0
  49. package/build/form-submission-notification/init.js +13 -0
  50. package/build/form-submission-notification/init.js.map +1 -0
  51. package/build/form-submission-notification/save.js +33 -0
  52. package/build/form-submission-notification/save.js.map +1 -0
  53. package/build/form-submission-notification/variations.js +63 -0
  54. package/build/form-submission-notification/variations.js.map +1 -0
  55. package/build/form-submit-button/edit.js +32 -0
  56. package/build/form-submit-button/edit.js.map +1 -0
  57. package/build/form-submit-button/index.js +44 -0
  58. package/build/form-submit-button/index.js.map +1 -0
  59. package/build/form-submit-button/init.js +13 -0
  60. package/build/form-submit-button/init.js.map +1 -0
  61. package/build/form-submit-button/save.js +22 -0
  62. package/build/form-submit-button/save.js.map +1 -0
  63. package/build/group/index.js +0 -1
  64. package/build/group/index.js.map +1 -1
  65. package/build/heading/index.js +3 -2
  66. package/build/heading/index.js.map +1 -1
  67. package/build/image/image.js +4 -1
  68. package/build/image/image.js.map +1 -1
  69. package/build/image/view.js +82 -40
  70. package/build/image/view.js.map +1 -1
  71. package/build/index.js +10 -0
  72. package/build/index.js.map +1 -1
  73. package/build/latest-posts/edit.js +6 -2
  74. package/build/latest-posts/edit.js.map +1 -1
  75. package/build/list-item/hooks/use-merge.js +15 -15
  76. package/build/list-item/hooks/use-merge.js.map +1 -1
  77. package/build/lock-unlock.js +1 -1
  78. package/build/lock-unlock.js.map +1 -1
  79. package/build/missing/edit.native.js +14 -62
  80. package/build/missing/edit.native.js.map +1 -1
  81. package/build/navigation/edit/index.js +0 -1
  82. package/build/navigation/edit/index.js.map +1 -1
  83. package/build/navigation/index.js +2 -1
  84. package/build/navigation/index.js.map +1 -1
  85. package/build/navigation/view.js +27 -5
  86. package/build/navigation/view.js.map +1 -1
  87. package/build/page-list-item/edit.js +3 -1
  88. package/build/page-list-item/edit.js.map +1 -1
  89. package/build/paragraph/index.js +7 -0
  90. package/build/paragraph/index.js.map +1 -1
  91. package/build/pattern/index.js +2 -1
  92. package/build/pattern/index.js.map +1 -1
  93. package/build/template-part/index.js +2 -1
  94. package/build/template-part/index.js.map +1 -1
  95. package/build-module/block/index.js +2 -1
  96. package/build-module/block/index.js.map +1 -1
  97. package/build-module/code/edit.native.js +8 -2
  98. package/build-module/code/edit.native.js.map +1 -1
  99. package/build-module/cover/deprecated.js +110 -1
  100. package/build-module/cover/deprecated.js.map +1 -1
  101. package/build-module/cover/edit/index.js +9 -3
  102. package/build-module/cover/edit/index.js.map +1 -1
  103. package/build-module/cover/edit/inspector-controls.js +1 -2
  104. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  105. package/build-module/cover/index.js +0 -3
  106. package/build-module/cover/index.js.map +1 -1
  107. package/build-module/cover/save.js +2 -1
  108. package/build-module/cover/save.js.map +1 -1
  109. package/build-module/cover/shared.js +1 -1
  110. package/build-module/cover/shared.js.map +1 -1
  111. package/build-module/footnotes/index.js +1 -0
  112. package/build-module/footnotes/index.js.map +1 -1
  113. package/build-module/form/edit.js +130 -0
  114. package/build-module/form/edit.js.map +1 -0
  115. package/build-module/form/index.js +82 -0
  116. package/build-module/form/index.js.map +1 -0
  117. package/build-module/form/init.js +6 -0
  118. package/build-module/form/init.js.map +1 -0
  119. package/build-module/form/save.js +20 -0
  120. package/build-module/form/save.js.map +1 -0
  121. package/build-module/form/utils.js +15 -0
  122. package/build-module/form/utils.js.map +1 -0
  123. package/build-module/form/variations.js +86 -0
  124. package/build-module/form/variations.js.map +1 -0
  125. package/build-module/form/view.js +40 -0
  126. package/build-module/form/view.js.map +1 -0
  127. package/build-module/form-input/edit.js +115 -0
  128. package/build-module/form-input/edit.js.map +1 -0
  129. package/build-module/form-input/index.js +95 -0
  130. package/build-module/form-input/index.js.map +1 -0
  131. package/build-module/form-input/init.js +6 -0
  132. package/build-module/form-input/init.js.map +1 -0
  133. package/build-module/form-input/save.js +80 -0
  134. package/build-module/form-input/save.js.map +1 -0
  135. package/build-module/form-input/variations.js +85 -0
  136. package/build-module/form-input/variations.js.map +1 -0
  137. package/build-module/form-submission-notification/edit.js +50 -0
  138. package/build-module/form-submission-notification/edit.js.map +1 -0
  139. package/build-module/form-submission-notification/index.js +47 -0
  140. package/build-module/form-submission-notification/index.js.map +1 -0
  141. package/build-module/form-submission-notification/init.js +6 -0
  142. package/build-module/form-submission-notification/init.js.map +1 -0
  143. package/build-module/form-submission-notification/save.js +25 -0
  144. package/build-module/form-submission-notification/save.js.map +1 -0
  145. package/build-module/form-submission-notification/variations.js +55 -0
  146. package/build-module/form-submission-notification/variations.js.map +1 -0
  147. package/build-module/form-submit-button/edit.js +24 -0
  148. package/build-module/form-submit-button/edit.js.map +1 -0
  149. package/build-module/form-submit-button/index.js +34 -0
  150. package/build-module/form-submit-button/index.js.map +1 -0
  151. package/build-module/form-submit-button/init.js +6 -0
  152. package/build-module/form-submit-button/init.js.map +1 -0
  153. package/build-module/form-submit-button/save.js +14 -0
  154. package/build-module/form-submit-button/save.js.map +1 -0
  155. package/build-module/group/index.js +0 -1
  156. package/build-module/group/index.js.map +1 -1
  157. package/build-module/heading/index.js +3 -2
  158. package/build-module/heading/index.js.map +1 -1
  159. package/build-module/image/image.js +4 -1
  160. package/build-module/image/image.js.map +1 -1
  161. package/build-module/image/view.js +82 -40
  162. package/build-module/image/view.js.map +1 -1
  163. package/build-module/index.js +10 -0
  164. package/build-module/index.js.map +1 -1
  165. package/build-module/latest-posts/edit.js +6 -2
  166. package/build-module/latest-posts/edit.js.map +1 -1
  167. package/build-module/list-item/hooks/use-merge.js +15 -15
  168. package/build-module/list-item/hooks/use-merge.js.map +1 -1
  169. package/build-module/lock-unlock.js +1 -1
  170. package/build-module/lock-unlock.js.map +1 -1
  171. package/build-module/missing/edit.native.js +17 -65
  172. package/build-module/missing/edit.native.js.map +1 -1
  173. package/build-module/navigation/edit/index.js +0 -1
  174. package/build-module/navigation/edit/index.js.map +1 -1
  175. package/build-module/navigation/index.js +2 -1
  176. package/build-module/navigation/index.js.map +1 -1
  177. package/build-module/navigation/view.js +27 -5
  178. package/build-module/navigation/view.js.map +1 -1
  179. package/build-module/page-list-item/edit.js +3 -1
  180. package/build-module/page-list-item/edit.js.map +1 -1
  181. package/build-module/paragraph/index.js +7 -0
  182. package/build-module/paragraph/index.js.map +1 -1
  183. package/build-module/pattern/index.js +2 -1
  184. package/build-module/pattern/index.js.map +1 -1
  185. package/build-module/template-part/index.js +2 -1
  186. package/build-module/template-part/index.js.map +1 -1
  187. package/build-style/editor-rtl.css +50 -0
  188. package/build-style/editor.css +50 -0
  189. package/build-style/form-input/editor-rtl.css +106 -0
  190. package/build-style/form-input/editor.css +106 -0
  191. package/build-style/form-input/style-rtl.css +135 -0
  192. package/build-style/form-input/style.css +135 -0
  193. package/build-style/form-submission-notification/editor-rtl.css +118 -0
  194. package/build-style/form-submission-notification/editor.css +118 -0
  195. package/build-style/form-submit-button/style-rtl.css +91 -0
  196. package/build-style/form-submit-button/style.css +91 -0
  197. package/build-style/image/style-rtl.css +39 -5
  198. package/build-style/image/style.css +39 -5
  199. package/build-style/query/style-rtl.css +0 -10
  200. package/build-style/query/style.css +0 -10
  201. package/build-style/style-rtl.css +87 -5
  202. package/build-style/style.css +87 -5
  203. package/package.json +32 -32
  204. package/src/block/block.json +2 -1
  205. package/src/code/edit.native.js +15 -1
  206. package/src/cover/block.json +0 -3
  207. package/src/cover/deprecated.js +151 -1
  208. package/src/cover/edit/index.js +12 -3
  209. package/src/cover/edit/inspector-controls.js +19 -25
  210. package/src/cover/save.js +2 -1
  211. package/src/cover/shared.js +1 -1
  212. package/src/editor.scss +2 -0
  213. package/src/footnotes/block.json +1 -0
  214. package/src/form/block.json +60 -0
  215. package/src/form/edit.js +179 -0
  216. package/src/form/index.js +20 -0
  217. package/src/form/index.php +214 -0
  218. package/src/form/init.js +6 -0
  219. package/src/form/save.js +20 -0
  220. package/src/form/utils.js +39 -0
  221. package/src/form/variations.js +139 -0
  222. package/src/form/view.js +41 -0
  223. package/src/form-input/block.json +73 -0
  224. package/src/form-input/edit.js +151 -0
  225. package/src/form-input/editor.scss +24 -0
  226. package/src/form-input/index.js +20 -0
  227. package/src/form-input/index.php +45 -0
  228. package/src/form-input/init.js +6 -0
  229. package/src/form-input/save.js +83 -0
  230. package/src/form-input/style.scss +61 -0
  231. package/src/form-input/variations.js +82 -0
  232. package/src/form-submission-notification/block.json +19 -0
  233. package/src/form-submission-notification/edit.js +63 -0
  234. package/src/form-submission-notification/editor.scss +45 -0
  235. package/src/form-submission-notification/index.js +26 -0
  236. package/src/form-submission-notification/index.php +48 -0
  237. package/src/form-submission-notification/init.js +6 -0
  238. package/src/form-submission-notification/save.js +28 -0
  239. package/src/form-submission-notification/variations.js +59 -0
  240. package/src/form-submit-button/block.json +14 -0
  241. package/src/form-submit-button/edit.js +33 -0
  242. package/src/form-submit-button/index.js +18 -0
  243. package/src/form-submit-button/init.js +6 -0
  244. package/src/form-submit-button/save.js +14 -0
  245. package/src/form-submit-button/style.scss +3 -0
  246. package/src/group/block.json +0 -1
  247. package/src/heading/index.js +4 -2
  248. package/src/image/image.js +10 -0
  249. package/src/image/index.php +128 -82
  250. package/src/image/style.scss +49 -5
  251. package/src/image/view.js +100 -52
  252. package/src/index.js +10 -0
  253. package/src/latest-posts/edit.js +11 -2
  254. package/src/latest-posts/index.php +17 -8
  255. package/src/list-item/hooks/use-merge.js +20 -23
  256. package/src/lock-unlock.js +1 -1
  257. package/src/missing/edit.native.js +17 -115
  258. package/src/missing/style.native.scss +0 -67
  259. package/src/missing/test/edit-integration.native.js +135 -49
  260. package/src/missing/test/edit.native.js +0 -41
  261. package/src/navigation/block.json +2 -1
  262. package/src/navigation/edit/index.js +0 -1
  263. package/src/navigation/index.php +28 -8
  264. package/src/navigation/view.js +25 -6
  265. package/src/page-list-item/edit.js +2 -0
  266. package/src/paragraph/index.js +10 -0
  267. package/src/pattern/block.json +2 -1
  268. package/src/pattern/index.php +0 -3
  269. package/src/post-navigation-link/index.php +2 -1
  270. package/src/preformatted/test/edit.native.js +38 -0
  271. package/src/query/index.php +3 -2
  272. package/src/query/style.scss +0 -11
  273. package/src/search/index.php +0 -4
  274. package/src/style.scss +1 -0
  275. package/src/template-part/block.json +2 -1
  276. package/src/template-part/index.php +4 -7
  277. package/src/verse/test/edit.native.js +37 -0
package/src/editor.scss CHANGED
@@ -16,6 +16,8 @@
16
16
  @import "./details/editor.scss";
17
17
  @import "./embed/editor.scss";
18
18
  @import "./file/editor.scss";
19
+ @import "./form-input/editor.scss";
20
+ @import "./form-submission-notification/editor.scss";
19
21
  @import "./freeform/editor.scss";
20
22
  @import "./gallery/editor.scss";
21
23
  @import "./group/editor.scss";
@@ -33,6 +33,7 @@
33
33
  "html": false,
34
34
  "multiple": false,
35
35
  "reusable": false,
36
+ "inserter": false,
36
37
  "spacing": {
37
38
  "margin": true,
38
39
  "padding": true,
@@ -0,0 +1,60 @@
1
+ {
2
+ "$schema": "https://schemas.wp.org/trunk/block.json",
3
+ "apiVersion": 3,
4
+ "__experimental": true,
5
+ "name": "core/form",
6
+ "title": "Form",
7
+ "category": "common",
8
+ "description": "A form.",
9
+ "keywords": [ "container", "wrapper", "row", "section" ],
10
+ "textdomain": "default",
11
+ "icon": "feedback",
12
+ "attributes": {
13
+ "submissionMethod": {
14
+ "type": "string",
15
+ "default": "email"
16
+ },
17
+ "method": {
18
+ "type": "string",
19
+ "default": "post"
20
+ },
21
+ "action": {
22
+ "type": "string"
23
+ },
24
+ "email": {
25
+ "type": "string"
26
+ }
27
+ },
28
+ "supports": {
29
+ "anchor": true,
30
+ "className": false,
31
+ "color": {
32
+ "gradients": true,
33
+ "link": true,
34
+ "__experimentalDefaultControls": {
35
+ "background": true,
36
+ "text": true,
37
+ "link": true
38
+ }
39
+ },
40
+ "spacing": {
41
+ "margin": true,
42
+ "padding": true
43
+ },
44
+ "typography": {
45
+ "fontSize": true,
46
+ "lineHeight": true,
47
+ "__experimentalFontFamily": true,
48
+ "__experimentalTextDecoration": true,
49
+ "__experimentalFontStyle": true,
50
+ "__experimentalFontWeight": true,
51
+ "__experimentalLetterSpacing": true,
52
+ "__experimentalTextTransform": true,
53
+ "__experimentalDefaultControls": {
54
+ "fontSize": true
55
+ }
56
+ },
57
+ "__experimentalSelector": "form"
58
+ },
59
+ "viewScript": "file:./view.min.js"
60
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+ import {
6
+ InnerBlocks,
7
+ useBlockProps,
8
+ useInnerBlocksProps,
9
+ InspectorControls,
10
+ store as blockEditorStore,
11
+ } from '@wordpress/block-editor';
12
+ import { TextControl, SelectControl, PanelBody } from '@wordpress/components';
13
+ import { useSelect } from '@wordpress/data';
14
+
15
+ /**
16
+ * Internal dependencies
17
+ */
18
+ import {
19
+ formSubmissionNotificationSuccess,
20
+ formSubmissionNotificationError,
21
+ } from './utils.js';
22
+
23
+ const ALLOWED_BLOCKS = [
24
+ 'core/paragraph',
25
+ 'core/heading',
26
+ 'core/form-input',
27
+ 'core/form-submit-button',
28
+ 'core/form-submission-notification',
29
+ ];
30
+
31
+ const TEMPLATE = [
32
+ formSubmissionNotificationSuccess,
33
+ formSubmissionNotificationError,
34
+ [
35
+ 'core/form-input',
36
+ {
37
+ type: 'text',
38
+ label: __( 'Name' ),
39
+ required: true,
40
+ },
41
+ ],
42
+ [
43
+ 'core/form-input',
44
+ {
45
+ type: 'email',
46
+ label: __( 'Email' ),
47
+ required: true,
48
+ },
49
+ ],
50
+ [
51
+ 'core/form-input',
52
+ {
53
+ type: 'textarea',
54
+ label: __( 'Comment' ),
55
+ required: true,
56
+ },
57
+ ],
58
+ [ 'core/form-submit-button', {} ],
59
+ ];
60
+
61
+ const Edit = ( { attributes, setAttributes, clientId } ) => {
62
+ const { action, method, email, submissionMethod } = attributes;
63
+ const blockProps = useBlockProps();
64
+
65
+ const { hasInnerBlocks } = useSelect(
66
+ ( select ) => {
67
+ const { getBlock } = select( blockEditorStore );
68
+ const block = getBlock( clientId );
69
+ return {
70
+ hasInnerBlocks: !! ( block && block.innerBlocks.length ),
71
+ };
72
+ },
73
+ [ clientId ]
74
+ );
75
+
76
+ const innerBlocksProps = useInnerBlocksProps( blockProps, {
77
+ allowedBlocks: ALLOWED_BLOCKS,
78
+ template: TEMPLATE,
79
+ renderAppender: hasInnerBlocks
80
+ ? undefined
81
+ : InnerBlocks.ButtonBlockAppender,
82
+ } );
83
+
84
+ return (
85
+ <>
86
+ <InspectorControls>
87
+ <PanelBody title={ __( 'Settings' ) }>
88
+ <SelectControl
89
+ // __nextHasNoMarginBottom
90
+ // size={ '__unstable-large' }
91
+ label={ __( 'Submissions method' ) }
92
+ options={ [
93
+ // TODO: Allow plugins to add their own submission methods.
94
+ {
95
+ label: __( 'Send email' ),
96
+ value: 'email',
97
+ },
98
+ {
99
+ label: __( '- Custom -' ),
100
+ value: 'custom',
101
+ },
102
+ ] }
103
+ value={ submissionMethod }
104
+ onChange={ ( value ) =>
105
+ setAttributes( { submissionMethod: value } )
106
+ }
107
+ help={
108
+ submissionMethod === 'custom'
109
+ ? __(
110
+ 'Select the method to use for form submissions. Additional options for the "custom" mode can be found in the "Andvanced" section.'
111
+ )
112
+ : __(
113
+ 'Select the method to use for form submissions.'
114
+ )
115
+ }
116
+ />
117
+ { submissionMethod === 'email' && (
118
+ <TextControl
119
+ __nextHasNoMarginBottom
120
+ autoComplete="off"
121
+ label={ __( 'Email for form submissions' ) }
122
+ value={ email }
123
+ required
124
+ onChange={ ( value ) => {
125
+ setAttributes( { email: value } );
126
+ setAttributes( {
127
+ action: `mailto:${ value }`,
128
+ } );
129
+ setAttributes( { method: 'post' } );
130
+ } }
131
+ help={ __(
132
+ 'The email address where form submissions will be sent. Separate multiple email addresses with a comma.'
133
+ ) }
134
+ />
135
+ ) }
136
+ </PanelBody>
137
+ </InspectorControls>
138
+ { submissionMethod !== 'email' && (
139
+ <InspectorControls group="advanced">
140
+ <SelectControl
141
+ __nextHasNoMarginBottom
142
+ label={ __( 'Method' ) }
143
+ options={ [
144
+ { label: 'Get', value: 'get' },
145
+ { label: 'Post', value: 'post' },
146
+ ] }
147
+ value={ method }
148
+ onChange={ ( value ) =>
149
+ setAttributes( { method: value } )
150
+ }
151
+ help={ __(
152
+ 'Select the method to use for form submissions.'
153
+ ) }
154
+ />
155
+ <TextControl
156
+ __nextHasNoMarginBottom
157
+ autoComplete="off"
158
+ label={ __( 'Form action' ) }
159
+ value={ action }
160
+ onChange={ ( newVal ) => {
161
+ setAttributes( {
162
+ action: newVal,
163
+ } );
164
+ } }
165
+ help={ __(
166
+ 'The URL where the form should be submitted.'
167
+ ) }
168
+ />
169
+ </InspectorControls>
170
+ ) }
171
+ <form
172
+ { ...innerBlocksProps }
173
+ className="wp-block-form"
174
+ encType={ submissionMethod === 'email' ? 'text/plain' : null }
175
+ />
176
+ </>
177
+ );
178
+ };
179
+ export default Edit;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import initBlock from '../utils/init-block';
5
+ import edit from './edit';
6
+ import metadata from './block.json';
7
+ import save from './save';
8
+ import variations from './variations';
9
+
10
+ const { name } = metadata;
11
+
12
+ export { metadata, name };
13
+
14
+ export const settings = {
15
+ edit,
16
+ save,
17
+ variations,
18
+ };
19
+
20
+ export const init = () => initBlock( { name, metadata, settings } );
@@ -0,0 +1,214 @@
1
+ <?php
2
+ /**
3
+ * Server-side rendering of the `core/form` block.
4
+ *
5
+ * @package WordPress
6
+ */
7
+
8
+ /**
9
+ * Renders the `core/form` block on server.
10
+ *
11
+ * @param array $attributes The block attributes.
12
+ * @param string $content The saved content.
13
+ *
14
+ * @return string The content of the block being rendered.
15
+ */
16
+ function render_block_core_form( $attributes, $content ) {
17
+
18
+ $processed_content = new WP_HTML_Tag_Processor( $content );
19
+ $processed_content->next_tag( 'form' );
20
+
21
+ // Get the action for this form.
22
+ $action = '';
23
+ if ( isset( $attributes['action'] ) ) {
24
+ $action = str_replace(
25
+ array( '{SITE_URL}', '{ADMIN_URL}' ),
26
+ array( site_url(), admin_url() ),
27
+ $attributes['action']
28
+ );
29
+ }
30
+ $processed_content->set_attribute( 'action', esc_attr( $action ) );
31
+
32
+ // Add the method attribute. If it is not set, default to `post`.
33
+ $method = empty( $attributes['method'] ) ? 'post' : $attributes['method'];
34
+ $processed_content->set_attribute( 'method', $method );
35
+
36
+ $extra_fields = apply_filters( 'render_block_core_form_extra_fields', '', $attributes );
37
+
38
+ return str_replace(
39
+ '</form>',
40
+ $extra_fields . '</form>',
41
+ $processed_content->get_updated_html()
42
+ );
43
+ }
44
+
45
+ /**
46
+ * Additional data to add to the view.js script for this block.
47
+ */
48
+ function block_core_form_view_script() {
49
+ if ( ! gutenberg_is_experiment_enabled( 'gutenberg-form-blocks' ) ) {
50
+ return;
51
+ }
52
+
53
+ wp_localize_script(
54
+ 'wp-block-form-view',
55
+ 'wpBlockFormSettings',
56
+ array(
57
+ 'nonce' => wp_create_nonce( 'wp-block-form' ),
58
+ 'ajaxUrl' => admin_url( 'admin-ajax.php' ),
59
+ 'action' => 'wp_block_form_email_submit',
60
+ )
61
+ );
62
+ }
63
+ add_action( 'wp_enqueue_scripts', 'block_core_form_view_script' );
64
+
65
+ /**
66
+ * Adds extra fields to the form.
67
+ *
68
+ * If the form is a comment form, adds the post ID as a hidden field,
69
+ * to allow the comment to be associated with the post.
70
+ *
71
+ * @param string $extra_fields The extra fields.
72
+ * @param array $attributes The block attributes.
73
+ *
74
+ * @return string The extra fields.
75
+ */
76
+ function block_core_form_extra_fields_comment_form( $extra_fields, $attributes ) {
77
+ if ( ! empty( $attributes['action'] ) && str_ends_with( $attributes['action'], '/wp-comments-post.php' ) ) {
78
+ $extra_fields .= '<input type="hidden" name="comment_post_ID" value="' . get_the_ID() . '" id="comment_post_ID">';
79
+ }
80
+ return $extra_fields;
81
+ }
82
+ add_filter( 'render_block_core_form_extra_fields', 'block_core_form_extra_fields_comment_form', 10, 2 );
83
+
84
+ /**
85
+ * Sends an email if the form is a contact form.
86
+ */
87
+ function block_core_form_send_email() {
88
+ check_ajax_referer( 'wp-block-form' );
89
+
90
+ // Get the POST data.
91
+ $params = wp_unslash( $_POST );
92
+ // Start building the email content.
93
+ $content = sprintf(
94
+ /* translators: %s: The request URI. */
95
+ __( 'Form submission from %1$s', 'gutenberg' ) . '</br>',
96
+ '<a href="' . esc_url( get_site_url( null, $params['_wp_http_referer'] ) ) . '">' . get_bloginfo( 'name' ) . '</a>'
97
+ );
98
+
99
+ $skip_fields = array( 'formAction', '_ajax_nonce', 'action' );
100
+ foreach ( $params as $key => $value ) {
101
+ if ( in_array( $key, $skip_fields, true ) ) {
102
+ continue;
103
+ }
104
+ $content .= sanitize_key( $key ) . ': ' . wp_kses_post( $value ) . '</br>';
105
+ }
106
+
107
+ // Filter the email content.
108
+ $content = apply_filters( 'render_block_core_form_email_content', $content, $params );
109
+
110
+ // Send the email.
111
+ $result = wp_mail(
112
+ str_replace( 'mailto:', '', $params['wp-email-address'] ),
113
+ __( 'Form submission', 'gutenberg' ),
114
+ $content
115
+ );
116
+
117
+ if ( ! $result ) {
118
+ wp_send_json_error( $result );
119
+ }
120
+ wp_send_json_success( $result );
121
+ }
122
+ add_action( 'wp_ajax_wp_block_form_email_submit', 'block_core_form_send_email' );
123
+ add_action( 'wp_ajax_nopriv_wp_block_form_email_submit', 'block_core_form_send_email' );
124
+
125
+ /**
126
+ * Send the data export/remove request if the form is a privacy-request form.
127
+ */
128
+ function block_core_form_privacy_form() {
129
+ // Get the POST data.
130
+ $params = wp_unslash( $_POST );
131
+
132
+ // Bail early if not a form submission, or if the nonce is not valid.
133
+ if ( empty( $params['wp-action'] )
134
+ || 'wp_privacy_send_request' !== $params['wp-action']
135
+ || empty( $params['wp-privacy-request'] )
136
+ || '1' !== $params['wp-privacy-request']
137
+ || empty( $params['email'] )
138
+ ) {
139
+ return;
140
+ }
141
+
142
+ // Get the request types.
143
+ $request_types = _wp_privacy_action_request_types();
144
+ $requests_found = array();
145
+ foreach ( $request_types as $request_type ) {
146
+ if ( ! empty( $params[ $request_type ] ) ) {
147
+ $requests_found[] = $request_type;
148
+ }
149
+ }
150
+
151
+ // Bail early if no requests were found.
152
+ if ( empty( $requests_found ) ) {
153
+ return;
154
+ }
155
+
156
+ // Process the requests.
157
+ $actions_errored = array();
158
+ $actions_performed = array();
159
+ foreach ( $requests_found as $action_name ) {
160
+ // Get the request ID.
161
+ $request_id = wp_create_user_request( $params['email'], $action_name );
162
+
163
+ // Bail early if the request ID is invalid.
164
+ if ( is_wp_error( $request_id ) ) {
165
+ $actions_errored[] = $action_name;
166
+ continue;
167
+ }
168
+
169
+ // Send the request email.
170
+ wp_send_user_request( $request_id );
171
+ $actions_performed[] = $action_name;
172
+ }
173
+
174
+ /**
175
+ * Determine whether the core/form-submission-notification block should be shown.
176
+ *
177
+ * @param bool $show Whether to show the core/form-submission-notification block.
178
+ * @param array $attributes The block attributes.
179
+ *
180
+ * @return bool Whether to show the core/form-submission-notification block.
181
+ */
182
+ $show_notification = static function ( $show, $attributes ) use ( $actions_performed, $actions_errored ) {
183
+ switch ( $attributes['type'] ) {
184
+ case 'success':
185
+ return ! empty( $actions_performed ) && empty( $actions_errored );
186
+
187
+ case 'error':
188
+ return ! empty( $actions_errored );
189
+
190
+ default:
191
+ return $show;
192
+ }
193
+ };
194
+
195
+ // Add filter to show the core/form-submission-notification block.
196
+ add_filter( 'show_form_submission_notification_block', $show_notification, 10, 2 );
197
+ }
198
+ add_action( 'wp', 'block_core_form_privacy_form' );
199
+
200
+ /**
201
+ * Registers the `core/form` block on server.
202
+ */
203
+ function register_block_core_form() {
204
+ if ( ! gutenberg_is_experiment_enabled( 'gutenberg-form-blocks' ) ) {
205
+ return;
206
+ }
207
+ register_block_type_from_metadata(
208
+ __DIR__ . '/form',
209
+ array(
210
+ 'render_callback' => 'render_block_core_form',
211
+ )
212
+ );
213
+ }
214
+ add_action( 'init', 'register_block_core_form' );
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Internal dependencies
3
+ */
4
+ import { init } from './';
5
+
6
+ export default init();
@@ -0,0 +1,20 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
5
+
6
+ const Save = ( { attributes } ) => {
7
+ const blockProps = useBlockProps.save();
8
+ const { submissionMethod } = attributes;
9
+
10
+ return (
11
+ <form
12
+ { ...blockProps }
13
+ className="wp-block-form"
14
+ encType={ submissionMethod === 'email' ? 'text/plain' : null }
15
+ >
16
+ <InnerBlocks.Content />
17
+ </form>
18
+ );
19
+ };
20
+ export default Save;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ export const formSubmissionNotificationSuccess = [
7
+ 'core/form-submission-notification',
8
+ {
9
+ type: 'success',
10
+ },
11
+ [
12
+ [
13
+ 'core/paragraph',
14
+ {
15
+ content:
16
+ '<mark style="background-color:rgba(0, 0, 0, 0);color:#345C00" class="has-inline-color">' +
17
+ __( 'Your form has been submitted successfully' ) +
18
+ '</mark>',
19
+ },
20
+ ],
21
+ ],
22
+ ];
23
+ export const formSubmissionNotificationError = [
24
+ 'core/form-submission-notification',
25
+ {
26
+ type: 'error',
27
+ },
28
+ [
29
+ [
30
+ 'core/paragraph',
31
+ {
32
+ content:
33
+ '<mark style="background-color:rgba(0, 0, 0, 0);color:#CF2E2E" class="has-inline-color">' +
34
+ __( 'There was an error submitting your form.' ) +
35
+ '</mark>',
36
+ },
37
+ ],
38
+ ],
39
+ ];
@@ -0,0 +1,139 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __ } from '@wordpress/i18n';
5
+ /**
6
+ * Internal dependencies
7
+ */
8
+ import {
9
+ formSubmissionNotificationSuccess,
10
+ formSubmissionNotificationError,
11
+ } from './utils.js';
12
+
13
+ const variations = [
14
+ {
15
+ name: 'comment-form',
16
+ title: __( 'Experimental Comment form' ),
17
+ description: __( 'A comment form for posts and pages.' ),
18
+ attributes: {
19
+ submissionMethod: 'custom',
20
+ action: '{SITE_URL}/wp-comments-post.php',
21
+ method: 'post',
22
+ anchor: 'comment-form',
23
+ },
24
+ isDefault: false,
25
+ innerBlocks: [
26
+ [
27
+ 'core/form-input',
28
+ {
29
+ type: 'text',
30
+ name: 'author',
31
+ label: __( 'Name' ),
32
+ required: true,
33
+ visibilityPermissions: 'logged-out',
34
+ },
35
+ ],
36
+ [
37
+ 'core/form-input',
38
+ {
39
+ type: 'email',
40
+ name: 'email',
41
+ label: __( 'Email' ),
42
+ required: true,
43
+ visibilityPermissions: 'logged-out',
44
+ },
45
+ ],
46
+ [
47
+ 'core/form-input',
48
+ {
49
+ type: 'textarea',
50
+ name: 'comment',
51
+ label: __( 'Comment' ),
52
+ required: true,
53
+ visibilityPermissions: 'all',
54
+ },
55
+ ],
56
+ [ 'core/form-submit-button', {} ],
57
+ ],
58
+ scope: [ 'inserter', 'transform' ],
59
+ isActive: ( blockAttributes ) =>
60
+ ! blockAttributes?.type || blockAttributes?.type === 'text',
61
+ },
62
+ {
63
+ name: 'wp-privacy-form',
64
+ title: __( 'Experimental privacy request form' ),
65
+ keywords: [ 'GDPR' ],
66
+ description: __( 'A form torequest data exports and/or deletion.' ),
67
+ attributes: {
68
+ submissionMethod: 'custom',
69
+ action: '',
70
+ method: 'post',
71
+ anchor: 'gdpr-form',
72
+ },
73
+ isDefault: false,
74
+ innerBlocks: [
75
+ formSubmissionNotificationSuccess,
76
+ formSubmissionNotificationError,
77
+ [
78
+ 'core/paragraph',
79
+ {
80
+ content: __(
81
+ 'To request an export or deletion of your personal data on this site, please fill-in the form below. You can define the type of request you wish to perform, and your email address. Once the form is submitted, you will receive a confirmation email with instructions on the next steps.'
82
+ ),
83
+ },
84
+ ],
85
+ [
86
+ 'core/form-input',
87
+ {
88
+ type: 'email',
89
+ name: 'email',
90
+ label: __( 'Enter your email address.' ),
91
+ required: true,
92
+ visibilityPermissions: 'all',
93
+ },
94
+ ],
95
+ [
96
+ 'core/form-input',
97
+ {
98
+ type: 'checkbox',
99
+ name: 'export_personal_data',
100
+ label: __( 'Request data export' ),
101
+ required: false,
102
+ visibilityPermissions: 'all',
103
+ },
104
+ ],
105
+ [
106
+ 'core/form-input',
107
+ {
108
+ type: 'checkbox',
109
+ name: 'remove_personal_data',
110
+ label: __( 'Request data deletion' ),
111
+ required: false,
112
+ visibilityPermissions: 'all',
113
+ },
114
+ ],
115
+ [ 'core/form-submit-button', {} ],
116
+ [
117
+ 'core/form-input',
118
+ {
119
+ type: 'hidden',
120
+ name: 'wp-action',
121
+ value: 'wp_privacy_send_request',
122
+ },
123
+ ],
124
+ [
125
+ 'core/form-input',
126
+ {
127
+ type: 'hidden',
128
+ name: 'wp-privacy-request',
129
+ value: '1',
130
+ },
131
+ ],
132
+ ],
133
+ scope: [ 'inserter', 'transform' ],
134
+ isActive: ( blockAttributes ) =>
135
+ ! blockAttributes?.type || blockAttributes?.type === 'text',
136
+ },
137
+ ];
138
+
139
+ export default variations;