composer update

This commit is contained in:
Oliver Davies 2019-01-24 08:00:03 +00:00
parent f6abc3dce2
commit 71dfaca858
1753 changed files with 45274 additions and 14619 deletions

View file

@ -58,18 +58,17 @@ The primary use case for this module is to:
7. (optional) Install add-on contrib modules](/admin/structure/webform/addons).
### Releases
### Upgrading from pre-release versions
Even though the Webform module is still under active development with
regular [beta releases](https://www.drupal.org/documentation/version-info/alpha-beta-rc),
all existing configuration and submission data will be maintained and updated
between releases. **APIs can and will be changing** while this module moves
from beta releases to a final release candidate.
All existing configuration and submission data was maintained and updated
through the beta and rc release cycles.
**APIs have changed** during these release cycles.
Simply put, if you install and use the Webform module out of the box AS-IS,
you _should_ be okay. Once you start extending webforms with plugins, altering
hooks, and overriding templates, you will need to read each release's
notes and assume that _things will be changing_.
Simply put, if you installed and used the Webform module out of the box AS-IS,
and now you want to upgrade to a full release, then
you _should_ be okay. If you extended webforms with plugins, altered
hooks, and overrode templates, you will need to read each release's
notes and assume that _things have changed_.
### Project Status

View file

@ -32,7 +32,9 @@
},
"require-dev": {
"drupal/address": "~1.4",
"drupal/chosen": "~2.6",
"drupal/jsonapi": "~2.0",
"drupal/select2": "~1.1",
"drupal/token": "~1.3"
}
}

View file

@ -28,13 +28,13 @@
"type": "package",
"package": {
"name": "algolia/places",
"version": "1.13.0",
"version": "1.15.0",
"type": "drupal-library",
"extra": {
"installer-name": "algolia.places"
},
"dist": {
"url": "https://registry.npmjs.org/places.js/-/places.js-1.13.0.tgz",
"url": "https://registry.npmjs.org/places.js/-/places.js-1.15.0.tgz",
"type": "tar"
},
"require": {
@ -46,13 +46,13 @@
"type": "package",
"package": {
"name": "ckeditor/autogrow",
"version": "4.10.0",
"version": "4.10.1",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.autogrow"
},
"dist": {
"url": "https://download.ckeditor.com/autogrow/releases/autogrow_4.10.0.zip",
"url": "https://download.ckeditor.com/autogrow/releases/autogrow_4.10.1.zip",
"type": "zip"
},
"require": {
@ -82,13 +82,13 @@
"type": "package",
"package": {
"name": "ckeditor/fakeobjects",
"version": "4.10.0",
"version": "4.10.1",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.fakeobjects"
},
"dist": {
"url": "https://download.ckeditor.com/fakeobjects/releases/fakeobjects_4.10.0.zip",
"url": "https://download.ckeditor.com/fakeobjects/releases/fakeobjects_4.10.1.zip",
"type": "zip"
},
"require": {
@ -100,13 +100,13 @@
"type": "package",
"package": {
"name": "ckeditor/image",
"version": "4.10.0",
"version": "4.10.1",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.image"
},
"dist": {
"url": "https://download.ckeditor.com/image/releases/image_4.10.0.zip",
"url": "https://download.ckeditor.com/image/releases/image_4.10.1.zip",
"type": "zip"
},
"require": {
@ -118,13 +118,13 @@
"type": "package",
"package": {
"name": "ckeditor/link",
"version": "4.10.0",
"version": "4.10.1",
"type": "drupal-library",
"extra": {
"installer-name": "ckeditor.link"
},
"dist": {
"url": "https://download.ckeditor.com/link/releases/link_4.10.0.zip",
"url": "https://download.ckeditor.com/link/releases/link_4.10.1.zip",
"type": "zip"
},
"require": {
@ -136,13 +136,13 @@
"type": "package",
"package": {
"name": "codemirror/codemirror",
"version": "5.41.0",
"version": "5.42.0",
"type": "drupal-library",
"extra": {
"installer-name": "codemirror"
},
"dist": {
"url": "https://github.com/components/codemirror/archive/5.41.0.zip",
"url": "https://github.com/components/codemirror/archive/5.42.0.zip",
"type": "zip"
},
"require": {
@ -244,13 +244,13 @@
"type": "package",
"package": {
"name": "jquery/inputmask",
"version": "4.0.2",
"version": "4.0.4",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.inputmask"
},
"dist": {
"url": "https://github.com/RobinHerbots/jquery.inputmask/archive/4.0.2.zip",
"url": "https://github.com/RobinHerbots/jquery.inputmask/archive/4.0.4.zip",
"type": "zip"
},
"require": {
@ -262,13 +262,13 @@
"type": "package",
"package": {
"name": "jquery/intl-tel-input",
"version": "14.0.4",
"version": "14.0.6",
"type": "drupal-library",
"extra": {
"installer-name": "jquery.intl-tel-input"
},
"dist": {
"url": "https://github.com/jackocnr/intl-tel-input/archive/v14.0.4.zip",
"url": "https://github.com/jackocnr/intl-tel-input/archive/v14.0.6.zip",
"type": "zip"
},
"require": {
@ -404,20 +404,20 @@
}
},
"require": {
"algolia/places": "1.13.0",
"ckeditor/autogrow": "4.10.0",
"algolia/places": "1.15.0",
"ckeditor/autogrow": "4.10.1",
"ckeditor/codemirror": "v1.17.7",
"ckeditor/fakeobjects": "4.10.0",
"ckeditor/image": "4.10.0",
"ckeditor/link": "4.10.0",
"codemirror/codemirror": "5.41.0",
"ckeditor/fakeobjects": "4.10.1",
"ckeditor/image": "4.10.1",
"ckeditor/link": "4.10.1",
"codemirror/codemirror": "5.42.0",
"jquery/chosen": "1.8.7",
"jquery/geocomplete": "1.7.0",
"jquery/hotkeys": "0.2.0",
"jquery/icheck": "1.0.2 ",
"jquery/image-picker": "0.3.0",
"jquery/inputmask": "4.0.2",
"jquery/intl-tel-input": "14.0.4",
"jquery/inputmask": "4.0.4",
"jquery/intl-tel-input": "14.0.6",
"jquery/rateit": "1.1.1",
"jquery/select2": "4.0.5",
"jquery/textcounter": "0.8.0",

View file

@ -24,6 +24,7 @@ settings:
messages messages--error
messages messages--warning
messages messages--status
button_classes: ''
default_wizard_prev_button_label: '< Previous Page'
default_wizard_next_button_label: 'Next Page >'
@ -47,16 +48,16 @@ settings:
default_submission_views: { }
default_submission_views_replace:
global_routes:
- entity.webform_submission.collection
- entity.webform_submission.user
- entity.webform_submission.collection
- entity.webform_submission.user
webform_routes:
- entity.webform.results_submissions
- entity.webform.user.drafts
- entity.webform.user.submissions
- entity.webform.results_submissions
- entity.webform.user.drafts
- entity.webform.user.submissions
node_routes:
- entity.node.webform.results_submissions
- entity.node.webform.user.drafts
- entity.node.webform.user.submissions
- entity.node.webform.results_submissions
- entity.node.webform.user.drafts
- entity.node.webform.user.submissions
default_previous_submission_message: 'You have already submitted this webform. <a href="#">View your previous submission</a>.'
default_previous_submissions_message: 'You have already submitted this webform. <a href="#">View your previous submissions</a>.'
default_autofill_message: 'This submission has been autofilled with your previous submission.'
@ -64,12 +65,15 @@ settings:
messages messages--error
messages messages--warning
messages messages--status
confirmation_classes: |
messages messages--error
messages messages--warning
messages messages--status
confirmation_back_classes: |
button
default_limit_total_message: 'No more submissions are permitted.'
default_limit_user_message: 'No more submissions are permitted.'
dialog: false
@ -125,12 +129,14 @@ element:
messages messages--error
messages messages--warning
messages messages--status
classes: |
container-inline clearfix
form--inline clearfix
messages messages--error
messages messages--warning
messages messages--status
horizontal_rule_classes: |
webform-horizontal-rule--solid
webform-horizontal-rule--dashed
@ -141,6 +147,7 @@ element:
webform-horizontal-rule--thick
webform-horizontal-rule--flaired
webform-horizontal-rule--glyph
default_description_display: ''
default_more_title: More
default_section_title_tag: h2
@ -169,7 +176,7 @@ file:
default_managed_file_extensions: 'gif jpg png bmp eps tif pict psd txt rtf html odf pdf doc docx ppt pptx xls xlsx xml avi mov mp3 ogg wav bz2 dmg gz jar rar sit svg tar zip'
default_audio_file_extensions: 'mp3 ogg wav'
default_document_file_extensions: 'txt rtf pdf doc docx odt ppt pptx odp xls xlsx ods'
default_image_file_extensions: 'gif jpg png svg'
default_image_file_extensions: 'gif jpg png'
default_video_file_extensions: 'avi mov mp4 ogg wav webm'
make_unused_managed_files_temporary: true
delete_temporary_managed_files: true
@ -186,14 +193,16 @@ mail:
default_body_text: |
Submitted on [webform_submission:created]
Submitted by: [webform_submission:user]
Submitted values are:
[webform_submission:values]
default_body_html: |
<p>Submitted on [webform_submission:created]</p>
<p>Submitted by: [webform_submission:user]</p>
<p>Submitted values are:</p>
[webform_submission:values]
roles: { }
test:
types: |
@ -236,6 +245,7 @@ test:
webform_time:
- '09:00'
- '17:00'
names: |
first_name:
- 'John'
@ -275,6 +285,7 @@ test:
- 'Loremipsum'
- 'Oratione'
- 'Dixisset'
ui:
video_display: dialog
details_save: true

View file

@ -56,6 +56,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -188,6 +189,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
email_confirmation:
id: email

View file

@ -0,0 +1,11 @@
langcode: en
status: true
dependencies:
enforced:
module:
- webform
id: translations
label: Translations
category: Language
likert: false
options: ''

View file

@ -1,19 +1,15 @@
action.configuration.webform_submission_delete_action:
type: action_configuration_default
label: 'Delete submission configuration'
action.configuration.webform_submission_make_sticky_action:
type: action_configuration_default
label: 'Star/Flag selected submission configuration'
action.configuration.webform_submission_make_unsticky_action:
type: action_configuration_default
label: 'Unstar/Unflag selected submission configuration'
action.configuration.webform_submission_make_lock_action:
type: action_configuration_default
label: 'Lock selected submission configuration'
action.configuration.webform_submission_make_unlock_action:
type: action_configuration_default
label: 'Unlock selected submission configuration'

View file

@ -4,26 +4,25 @@ block.settings.webform_block:
mapping:
webform_id:
type: string
label: 'Webform'
label: Webform
default_data:
type: text
label: 'Default webform submission data'
redirect:
type: boolean
label: 'Redirect to the webform'
block.settings.webform_submission_limit_block:
type: block_settings
label: 'Webform submission limits block'
mapping:
type:
type: text
label: 'Type'
label: Type
source_entity:
type: boolean
label: 'Source entity'
content:
label: 'Content'
label: Content
type: text
progress_bar:
type: boolean
@ -36,7 +35,7 @@ block.settings.webform_submission_limit_block:
label: 'Progress bar message'
webform_id:
type: string
label: 'Webform'
label: Webform
entity_type:
type: string
label: 'Source entity type'

View file

@ -1,13 +1,13 @@
webform.webform.*:
'webform.webform.*':
type: config_entity
label: 'Webforms'
label: Webforms
mapping:
status:
type: string
label: 'Status'
label: Status
weight:
type: integer
label: 'Weight'
label: Weight
open:
type: string
label: 'Open date/time'
@ -16,25 +16,25 @@ webform.webform.*:
label: 'Close date/time'
uid:
type: integer
label: 'Author'
label: Author
template:
type: boolean
label: 'Template'
label: Template
archive:
type: boolean
label: 'Archive'
label: Archive
id:
type: string
label: 'Machine name'
title:
type: label
label: 'Title'
label: Title
description:
type: label
label: 'Administrative description'
category:
type: label
label: 'Category'
label: Category
elements:
type: text
label: 'Elements (YAML)'
@ -43,12 +43,10 @@ webform.webform.*:
label: 'CSS (Cascading Style Sheets)'
javascript:
type: string
label: 'JavaScript'
label: JavaScript
settings:
type: mapping
label: 'Settings'
# Below mapping is copied to: webform.handler.settings
#@see webform.plugin.handler.schema.yml
label: Settings
mapping:
ajax:
type: boolean
@ -89,6 +87,9 @@ webform.webform.*:
form_confidential_message:
type: text
label: 'Form confidential message'
form_remote_addr:
type: boolean
label: 'Track user IP address'
form_convert_anonymous:
type: boolean
label: 'Convert anonymous drafts and submissions to authenticated'
@ -127,7 +128,7 @@ webform.webform.*:
label: 'Display required indicator'
form_autofocus:
type: boolean
label: 'Autofocus'
label: Autofocus
form_details_toggle:
type: boolean
label: 'Display collapse/expand all details link'
@ -178,11 +179,11 @@ webform.webform.*:
label: 'Submission views'
sequence:
type: mapping
label: 'Submission view'
label: 'Submission view'
mapping:
title:
type: text
label: 'Title'
label: Title
view:
type: string
label: 'View name / Display ID'
@ -191,13 +192,13 @@ webform.webform.*:
label: 'Apply to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Apply to node'
sequence:
type: string
label: 'Route'
label: Route
submission_views_replace:
type: mapping
label: 'Submission view replace'
@ -207,19 +208,19 @@ webform.webform.*:
label: 'Replace to global'
sequence:
type: string
label: 'Route'
label: Route
webform_routes:
type: sequence
label: 'Replace to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Replace to node'
sequence:
type: string
label: 'Route'
label: Route
submission_user_columns:
type: sequence
label: 'Submission user columns'
@ -417,26 +418,26 @@ webform.webform.*:
label: 'Access Rules'
sequence:
type: mapping
label: 'Access Rule'
label: 'Access Rule'
mapping:
roles:
type: sequence
label: 'Roles'
label: Roles
sequence:
type: string
label: 'Role'
label: Role
users:
type: sequence
label: 'Users'
label: Users
sequence:
type: integer
label: 'User IDs'
permissions:
type: sequence
label: 'Permissions'
label: Permissions
sequence:
type: string
label: 'Permission'
label: Permission
handlers:
type: sequence
label: 'Webform handlers'
@ -451,20 +452,20 @@ webform.webform.*:
label: 'Handler instance ID'
label:
type: label
label: 'Label'
label: Label
status:
type: boolean
label: 'Status'
label: Status
conditions:
type: ignore
label: 'Conditional logic'
weight:
type: integer
label: 'Weight'
label: Weight
settings:
type: webform.handler.[%parent.id]
type: 'webform.handler.[%parent.id]'
third_party_settings:
type: sequence
label: 'Third party settings'
sequence:
type: webform.settings.third_party.[%key]
type: 'webform.settings.third_party.[%key]'

View file

@ -1,16 +1,16 @@
webform.webform_options.*:
'webform.webform_options.*':
type: config_entity
label: 'Options'
label: Options
mapping:
id:
type: string
label: 'Machine name'
label:
type: label
label: 'Label'
label: Label
category:
type: label
label: 'Category'
label: Category
likert:
type: boolean
label: 'Use as Likert'

View file

@ -5,7 +5,6 @@ field.storage_settings.webform:
target_type:
type: string
label: 'Type of item to reference'
base_webform_field_field_settings:
type: mapping
mapping:
@ -13,9 +12,8 @@ base_webform_field_field_settings:
type: string
label: 'Reference method'
handler_settings:
type: entity_reference_selection.[%parent.handler]
type: 'entity_reference_selection.[%parent.handler]'
label: 'Entity reference selection settings'
field.field_settings.webform:
type: base_webform_field_field_settings
label: 'Webform settings'
@ -32,7 +30,6 @@ field.field_settings.webform:
close:
type: string
label: 'Webform close date/time'
field.widget.settings.webform_entity_reference_autocomplete:
type: mapping
label: 'Webform autocomplete display format settings'
@ -45,11 +42,10 @@ field.widget.settings.webform_entity_reference_autocomplete:
label: 'Size of textfield'
placeholder:
type: label
label: 'Placeholder'
label: Placeholder
default_data:
type: boolean
label: 'Default submission data'
field.widget.settings.webform_entity_reference_select:
type: mapping
label: 'Webform select display format settings'
@ -57,7 +53,6 @@ field.widget.settings.webform_entity_reference_select:
default_data:
type: boolean
label: 'Default submission data'
field.formatter.settings.webform_entity_reference_entity_view:
type: mapping
label: 'Display the referenced webform with default submission data.'
@ -65,7 +60,6 @@ field.formatter.settings.webform_entity_reference_entity_view:
source_entity:
type: boolean
label: 'Source entity'
field.formatter.settings.webform_entity_reference_link:
type: mapping
label: 'Display the referenced webform as a link.'

View file

@ -1,11 +1,10 @@
webform.exporter.*:
'webform.exporter.*':
type: mapping
label: 'Exporter settings'
webform.exporter.delimited_text:
type: mapping
label: 'Delimiter'
label: Delimiter
mapping:
delimiter:
type: string
label: 'Delimiter'
label: Delimiter

View file

@ -1,31 +1,30 @@
webform.handler.*:
'webform.handler.*':
type: mapping
label: 'Handler settings'
webform.handler.action:
type: mapping
label: 'Action'
label: Action
mapping:
states:
type: sequence
label: 'States'
label: States
sequence:
type: string
label: 'State'
label: State
notes:
label: 'Notes'
label: Notes
type: text
sticky:
label: 'Flag'
label: Flag
type: boolean
locked:
label: 'Locked'
label: Locked
type: boolean
data:
label: 'Data'
label: Data
type: text
message:
label: 'Message'
label: Message
type: text
message_type:
label: 'Message type'
@ -33,22 +32,20 @@ webform.handler.action:
debug:
type: boolean
label: 'Enable debugging'
webform.handler.log:
type: mapping
label: 'Log'
label: Log
mapping: { }
webform.handler.email:
type: mapping
label: 'Email'
label: Email
mapping:
states:
type: sequence
label: 'States'
label: States
sequence:
type: string
label: 'State'
label: State
to_mail:
label: 'Email to address'
type: email
@ -111,29 +108,28 @@ webform.handler.email:
label: 'Exclude unselected checkboxes'
html:
type: boolean
label: 'HTML'
label: HTML
attachments:
type: boolean
label: 'Attachments'
label: Attachments
twig:
type: boolean
label: 'Twig'
label: Twig
theme_name:
type: string
label: 'Theme name'
debug:
type: boolean
label: 'Enable debugging'
webform.handler.remote_post:
type: mapping
label: 'Remote Post'
mapping:
method:
label: 'Method'
label: Method
type: string
type:
label: 'Type'
label: Type
type: string
excluded_data:
type: sequence
@ -188,7 +184,7 @@ webform.handler.remote_post:
type: sequence
sequence:
type: mapping
label: 'Message'
label: Message
mapping:
code:
type: integer
@ -196,18 +192,13 @@ webform.handler.remote_post:
message:
type: text
label: 'Response message'
webform.handler.settings:
type: mapping
label: 'Settings'
label: Settings
mapping:
debug:
type: string
label: 'Enable debugging'
# Below mapping is copied from: webform.webform.*
# @see webform.entity.webform.schema.yml
# NOTE: 'type: boolean' is changed to 'type: string
# NOTE: 'type: integer' is changed to 'type: string
ajax:
type: string
label: 'Use Ajax'
@ -282,7 +273,7 @@ webform.handler.settings:
label: 'Display required indicator'
form_autofocus:
type: string
label: 'Autofocus'
label: Autofocus
form_details_toggle:
type: string
label: 'Display collapse/expand all details link'
@ -318,11 +309,11 @@ webform.handler.settings:
label: 'Submission views'
sequence:
type: mapping
label: 'Submission view'
label: 'Submission view'
mapping:
title:
type: text
label: 'Title'
label: Title
view:
type: string
label: 'View name / Display ID'
@ -331,13 +322,13 @@ webform.handler.settings:
label: 'Apply to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Apply to node'
sequence:
type: string
label: 'Route'
label: Route
submission_views_replace:
type: mapping
label: 'Submission view replace'
@ -347,19 +338,19 @@ webform.handler.settings:
label: 'Replace to global'
sequence:
type: string
label: 'Route'
label: Route
webform_routes:
type: sequence
label: 'Replace to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Replace to node'
sequence:
type: string
label: 'Route'
label: Route
submission_user_columns:
type: sequence
label: 'Submission user columns'

View file

@ -122,11 +122,11 @@ webform.settings:
label: 'Default submission views'
sequence:
type: mapping
label: 'Submission view'
label: 'Submission view'
mapping:
title:
type: text
label: 'Title'
label: Title
view:
type: string
label: 'View name / Display ID'
@ -135,19 +135,19 @@ webform.settings:
label: 'Apply to global'
sequence:
type: string
label: 'Route'
label: Route
webform_routes:
type: sequence
label: 'Apply to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Apply to node'
sequence:
type: string
label: 'Route'
label: Route
default_submission_views_replace:
type: mapping
label: 'Default submission view replace'
@ -157,19 +157,19 @@ webform.settings:
label: 'Replace to global'
sequence:
type: string
label: 'Route'
label: Route
webform_routes:
type: sequence
label: 'Replace to webform'
sequence:
type: string
label: 'Route'
label: Route
node_routes:
type: sequence
label: 'Replace to node'
sequence:
type: string
label: 'Route'
label: Route
default_submission_access_denied_message:
type: text
label: 'Default submission access denied message'
@ -234,7 +234,7 @@ webform.settings:
label: 'CSS (Cascading Style Sheets)'
javascript:
type: string
label: 'JavaScript'
label: JavaScript
element:
type: mapping
label: 'Element default settings'
@ -382,10 +382,10 @@ webform.settings:
label: 'Default email body (HTML)'
roles:
type: sequence
label: 'Roles'
label: Roles
sequence:
type: string
label: 'Role'
label: Role
export:
type: mapping
label: 'Export default settings'
@ -527,7 +527,7 @@ webform.settings:
label: 'Use CDN'
requirements:
type: mapping
label: 'Requirements'
label: Requirements
mapping:
cdn:
type: boolean
@ -540,7 +540,7 @@ webform.settings:
label: 'Check if SPAM protection module is installed'
contribute:
type: mapping
label: 'Contribute'
label: Contribute
mapping:
account_type:
type: string
@ -552,4 +552,4 @@ webform.settings:
type: sequence
label: 'Third party settings'
sequence:
type: webform.admin_settings.third_party.[%key]
type: 'webform.admin_settings.third_party.[%key]'

View file

@ -8,7 +8,6 @@ webform.admin_settings.third_party.honeypot:
time_restriction:
type: boolean
label: 'Add time limit to all webforms'
webform.settings.third_party.honeypot:
type: mapping
label: 'Webform test third party settings'

View file

@ -0,0 +1,8 @@
/**
* @file
* Element date styles.
*/
.ui-datepicker-trigger {
margin: 0 2px;
}

View file

@ -0,0 +1,8 @@
/**
* @file
* Element datelist styles.
*/
.form-type-datelist input[type="text"] {
max-width: 5em;
}

View file

@ -9,3 +9,7 @@ img.webform-image-file {
max-width: 100%;
height: auto;
}
.webform-image-file-modal img {
display: block;
}

View file

@ -0,0 +1,30 @@
/**
* @file
* Managed file styles.
*/
.webform-managed-file-preview-wrapper + input[type="submit"],
.webform-managed-file-preview-wrapper + button,
.webform-managed-file-preview + input[type="submit"],
.webform-managed-file-preview + button {
margin: .5em 0;
}
.webform-managed-file-preview-wrapper,
.webform-managed-file-preview-wrapper.form-item {
display: table;
border: 1px solid #ccc;
padding: .5em;
}
.webform-managed-file-preview,
label.webform-managed-file-preview,
label.option.webform-managed-file-preview {
display: block;
}
.webform-managed-file-placeholder,
.webform-managed-file-preview,
.webform-file-button {
margin: .5em 0;
}

View file

@ -65,3 +65,14 @@ tr.webform-states-table--state td select {
.webform-states-table .tabledrag-changed {
display: none !important; /* Must use !important because .tabledrag-changed 'display' is set via JavaScript */
}
/**
* Limit results in jQuery UI Autocomplete
*
* https://stackoverflow.com/questions/7617373/limit-results-in-jquery-ui-autocomplete
*/
.ui-autocomplete {
max-height: 200px;
overflow-y: auto;
overflow-x: hidden;
}

View file

@ -5,17 +5,7 @@
* @see /webform/test_element_media_file
*/
.webform-video-file {
position: relative;
max-width: 640px;
height: 0;
padding-bottom: 56.25%;
}
.webform-video-file video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
height: auto;
}

View file

@ -49,18 +49,28 @@ code {
}
/* Add yellow background to tooltips and tabs */
/* @see core/assets/vendor/jquery.ui/themes/base/tabs.css */
.ui-tooltip.ui-widget {
background: #fe6;;
border: 1px solid #ed5;
}
.webform-tabs .ui-tabs-nav .ui-tabs-anchor {
text-decoration: inherit;
}
.webform-tabs .ui-tabs-active.ui-state-active {
background: #fe6;
border: 1px solid #ed5;
text-decoration: none;
}
.webform-tabs .ui-tabs-active.ui-state-active.ui-state-focus a {
text-decoration: underline;
.webform-tabs .ui-state-hover {
text-decoration: underline !important;
}
.webform-tabs .ui-state-active.ui-state-hover {
text-decoration: none !important;
}
/** Compress tabs for mobile */
@ -137,6 +147,27 @@ pre.webform-codemirror-runmode {
margin: 1em 0;
}
/* jQuery UI autocomplete states */
.ui-autocomplete a /* For filter autocomplete. */,
.ui-autocomplete .ui-menu-item-wrapper /* For #states value autocomplete. */ {
display: block;
border: 1px solid transparent;
color: #0074bd;
}
.ui-autocomplete a.ui-state-hover,
.ui-autocomplete a.ui-state-active,
.ui-autocomplete a.ui-state-focus,
.ui-autocomplete .ui-menu-item-wrapper.ui-state-hover,
.ui-autocomplete .ui-menu-item-wrapper.ui-state-active,
.ui-autocomplete .ui-menu-item-wrapper.ui-state-focus {
text-decoration: underline;
color: #0074bd;
background: #fe6;
border: solid 1px #ed5;
margin: 0;
}
/* jQuery UI button states */
.webform-buttons .ui-button.ui-state-default {
background: #f5f5f2;
@ -179,7 +210,6 @@ pre.webform-codemirror-runmode {
text-decoration: underline;
}
/* Token tree */
.token-tree ul {
margin: 0;

View file

@ -43,7 +43,7 @@ git push
git branch -D [issue-number]-[issue-description]
git push origin :[issue-number]-[issue-description]
# Delete remove branch
# Delete remote branch
git push origin --delete [issue-number]-[issue-description]
```
@ -130,6 +130,7 @@ drush en -y webform\
webform_test_handler\
webform_test_handler_remote_post\
webform_test_options\
webform_test_paragraphs\
webform_test_rest\
webform_test_submissions\
webform_test_translation\

View file

@ -1,219 +1,460 @@
Features
--------
## Form Builder
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-builder.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-builder.png" alt="Form Builder" />
</a>
<blockquote>
The Webform module provides all the features expected from an enterprise
proprietary form builder combined with the flexibility and openness of Drupal
</blockquote>
The Webform module allows you to build any type of form that can collect any
type of data, which can be submitted to any application or system.
Every single behavior and aspect of your forms and its inputs are customizable.
Whether you need a multi-page form containing a multi-column input layout with
conditional logic or a simple contact form that pushes data to a SalesForce/CRM,
it is all possible using the Webform module for Drupal 8.
Drupal and the Webform module strives to be fully accessible to all users and
site builders. Assistive technologies, including screen readers and
keyboard access, are fully supported.
Besides being a feature rich form builder, the Webform module is part of the
Drupal project's ecosystem and community.
<blockquote>
The <a href="https://www.drupal.org/about">Drupal project</a> is open source software.
Anyone can download, use, work on, and share it with others.
It's built on principles like collaboration, globalism, and innovation.
It's distributed under the terms of the <a href="https://www.gnu.org/copyleft/gpl.html">GNU General Public License</a> (GPL).
There are <a href="https://www.drupal.org/about/licensing">no licensing fees</a>, ever. Drupal (and Webform) will always be free.
</blockquote>
<div align="center">
<table class="views-view-grid">
<tr>
<td><a class="action-button" href="https://youtu.be/VncMRSwjVto">▶ Watch video</a></td>
<td><a class="action-button" href="https://simplytest.me/project/webform/8.x-5.x">Try Webform</a></td>
</tr>
</table>
</div>
The Webform module provides an intuitive webform builder based upon Drupal 8's
best practices for user interface and user experience. The webform builder allows non-technical users to easily build and maintain webforms.
<hr/>
## Form manager
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--form-manager.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--form-manager.png" alt="Form manager" /><br/>
<strong>Form manager</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--form-manager-add.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--form-manager-add.png" alt="Form manager: Add webform" /><br/>
<strong>Add webform</strong>
</a>
</div></td>
</tr>
</table>
The form manager provides a list of all available webforms.
Form manager features include:
- Filtering by keyword, category, and status
- Sorting by total number of submissions
- Archiving of old forms
## Form builder
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--form-builder.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--form-builder.png" alt="Form builder" /><br/>
<strong>Form builder</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--form-builder.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--form-builder.png" alt="Edit element" /><br/>
<strong>Edit element</strong>
</a>
</div></td>
</tr>
</table>
The Webform module provides an intuitive form builder based upon Drupal 8's
best practices for user interface design and user experience.
The form builder allows non-technical users to easily build
and maintain webforms.
Form builder features include:
- Drag-n-drop webform element management
- Generation of test submissions
- Duplication of existing webforms, templates, and elements
- Drag-n-drop form element management
- Multi-column layout management
- Conditional logic overview
- Element duplication
## Configuration settings
Form behaviors, features, submission handling, messaging, and confirmations are completely customizable using global settings and/or form-specific settings.
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-general.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-general.png" alt="Configuration settings: General" /><br/>
<strong>General</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-form.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-form.png" alt="Configuration settings: Form" /><br/>
<strong>Form</strong>
</a>
</div></td>
</tr>
</table>
### General settings
Allow a webform's administrative information, paths, behaviors, and third-party settings to be customized.
General settings include:
- Categorization
- Customizable paths
- Disable saving of results
- Ajax support
### Form settings
Allow a form's status, attributes, behaviors, labels, messages, wizard settings,
and preview to be customized.
Form settings include:
- Open and close date/time scheduling
- Login redirection with custom messaging.
- Multiple step wizard forms
- Submission preview
- Input prepopulation using query string parameters.
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-submissions.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-submissions.png" alt="Configuration settings: Submisssions" /><br/>
<strong>Submisssions</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-confirmation.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-confirmation.png" alt="Configuration settings: Confirmation" /><br/>
<strong>Confirmation</strong>
</a>
</div></td>
</tr>
</table>
### Submissions settings
Allows a submission's labels, behaviors, limits, and draft settings to be
customized.
Submission settings include:
- Saving of drafts
- Automatic purging of submissions
- Submission limits per user and/or per form
- Autofilling form using previously submitted values
### Confirmation settings
Allows the form's confirmation type, message, and URL to be customized.
Confirmation types include:
- Dedicated page
- Redirect to internal or external URL
- Displaying of a custom status message
- Opening a modal dialog
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-handlers.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-handlers.png" alt="Configuration settings: Handlers" /><br/>
<strong>Handlers</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-handlers-email.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-handlers-email.png" alt="Configuration settings: Email handler" /><br/>
<strong>Email handler</strong>
</a>
</div></td>
</tr>
</table>
## Form Settings
### Emails / Handlers
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-settings.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-settings-thumbnail.png" alt="Form Settings" />
</a>
</div>
Form submission handling, messaging, and confirmations are completely
customizable using global settings and/or form-specific settings.
Form settings that can be customized include:
- Messages and button labels
- Confirmation page, messages, and redirects
- Saving drafts
- Previewing submissions
- Confidential submissions
- Prepopulating a webform's elements using query string parameters
- Preventing duplicate submissions
- Disabling back button
- Warning users about unsaved changes
- Disabling client-side validation
- Limiting number of submission per user, per webform, and/or per node
- Look-n-feel of webform, confirmation page, and buttons
- Injection webform specific CSS and JavaScript
## Elements
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-elements.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-elements-thumbnail.png" alt="Elements" />
</a>
</div>
The Webform module is built directly on top of Drupal 8's Form API. Every
[form element](https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/8)
available in Drupal 8 is supported by the Webform module.
Form elements include:
- **HTML:** Textfield, Textareas, Checkboxes, Radios, Select menu,
Password, and more…
- **HTML5:** Email, Url, Number, Telephone, Date, Number, Range,
and more…
- **Drupal specific** File uploads, Entity References, Table select, Date list,
and more…
- **Custom:** [Likert scale](https://en.wikipedia.org/wiki/Likert_scale),
Star rating, Toggle, Buttons, Geolocation,
Select/Checkboxes/Radios with other, and more…
- **Markups** Inline dismissable messages, HTML Markup, Details, and Fieldsets.
- **Composite elements:** Name, Address, and Contact
## Element Settings
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-element-settings.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-element-settings-thumbnail.png" alt="Element Settings" />
</a>
</div>
All of Drupal 8's default webform element properties and behaviors are supported.
There are also several custom webform element properties and settings
available to enhance a webform element's behavior.
Standard and custom properties allow for:
- **Customizable required error messages**
- **Conditional logic** using [FAPI States API](https://api.drupal.org/api/examples/form_example%21form_example_states.inc/function/form_example_states_form/7)
- **Input masks** (using [jquery.inputmask](https://github.com/RobinHerbots/jquery.inputmask))
- **[Select2](https://select2.github.io/)** replacement of select boxes
- **Word and character counting** for text elements
- **Help popup** (using [jQuery UI Tooltip](https://jqueryui.com/tooltip/))
- **Regular expression pattern validation**
- **Private** elements, visible only to administrators
- **Unique** values per element
## Viewing Source
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-source.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-source-thumbnail.png" alt="Viewing Source" />
</a>
</div>
At the heart of a Webform module's webform elements is a Drupal render array,
which can be edited and managed by developers. The Drupal render array gives developers
complete control over a webform's elements, layout, and look-and-feel by
allowing developers to make bulk updates to a webform's label, descriptions, and
behaviors.
## States/Conditional Logic
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-states.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-states.png" alt="States/Conditional Logic" />
</a>
</div>
Drupal's State API can be used by developers to provide conditional logic to
hide and show webform elements.
Drupal's State API supports:
- Show/Hide
- Open/Close
- Enable/Disable
## Multistep Forms
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-wizard.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-wizard.png" alt="Multistep Forms" />
</a>
</div>
Forms can be broken up into multiple pages using a progress bar. Authenticated
users can save drafts and/or have their changes automatically saved as they
progress through a long webform.
Multistep webform features include:
- Customizable progress bar
- Customizable previous and next button labels and styles
- Saving drafts between steps
## Email & Remote Post Handlers
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-handlers.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-handlers-thumbnail.png" alt="Email/Handlers" />
</a>
</div>
Upon webform submission, customizable email notifications and confirmations can
be sent to users and administrators.
An extendable plugin that allows developers to push submitted data
to external or internal systems and/or applications is provided.
Allows additional actions and behaviors to be processed when a webform or
submission is created, updated, or deleted. Handlers are used to route
submitted data to external applications and send notifications & confirmations.
Email support features include:
- Previewing and resending emails
- Sending HTML emails
- File attachments (requires the [Mail System](https://www.drupal.org/project/mailsystem) and [Swift Mailer](https://www.drupal.org/project/swiftmailer) module.)
- File attachments (requires the Mail System and Swift Mailer module.)
- HTML and plain-text email-friendly Twig templates
- Customizable display formats for individual webform elements
- Customizable display formats for individual form elements
Remote post features include:
- Posting selected elements to remote server
- Posting selected elements to a remote server
- Adding custom parameters to remote post requests
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-assets.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-assets.png" alt="Configuration settings: CSS/JS assets" /><br/>
<strong>CSS/JS assets</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--settings-access.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--settings-access.png" alt="Configuration settings: Access" /><br/>
<strong>Access</strong>
</a>
</div></td>
</tr>
</table>
## Results Management
### CSS/JS assets
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-results.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-results-thumbnail.png" alt="Results Management" />
</a>
</div>
The CSS/JS assets page allows site builders to attach custom CSS and JavaScript
to a webform. Custom CSS can be used to make simple layout or design tweaks
to a form. Custom JavaScript allows additional conditional logic and
behaviors to be added to a form.
Form submissions can optionally be stored in the database, reviewed, and
downloaded.
### Access settings
Submissions can also be flagged with administrative notes.
Allows an administrator to determine who can administer a webform and/or create,
update, delete, and purge webform submissions.
## Elements
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--elements.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--elements.png" alt="Elements" /><br/>
<strong>Elements</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--elements-settings.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--elements-settings.png" alt="Element settings" /><br/>
<strong>Element settings</strong>
</a>
</div></td>
</tr>
</table>
The Webform module is built directly on top of Drupal 8's Form API.
Every form element available in Drupal 8 is supported by the Webform module.
Form elements include:
- **Basic HTML**: Textfield, Textareas, Checkboxes, Radios, Select menu, Password, and more...
- **Advanced HTML5**: Email, Url, Number, Telephone, Date, Number, Range, and more...
- **Advanced Drupal**: File uploads, Entity References, Table select, Date list, and more...
- **Widgets**: Likert scale, Star rating, Buttons, Geolocation, Terms of service, Select/Checkboxes/Radios with other, and more...
- **Markup**: Dismissible messages, Basic HTML, Advanced HTML, Details, and Fieldsets.
- **Composites**: Name, Address, Contact, Credit Card, and event custom composites
- **Computed**: Calculated values using Tokens and Twig with Ajax support.
### Element settings
All of Drupal 8's default form element properties and behaviors are supported.
There are also several custom webform element properties and settings available
to enhance a form element's behavior.
Standard and custom properties allow for:
- Customizable error validation messages
- Conditional logic using [FAPI States API](https://api.drupal.org/api/examples/form_example%21form_example_states.inc/function/form_example_states_form/7)
- Input masks (using [jquery.inputmask](https://github.com/RobinHerbots/jquery.inputmask))
- [Select2](https://select2.github.io/) or [Chosen](https://harvesthq.github.io/chosen/) replacement of select boxes
- Word and character counting for text elements
- Help tooltips (using [jQuery UI Tooltip](https://jqueryui.com/tooltip/))
- More information slideouts
- Regular expression pattern validation
- Private elements, visible only to administrators
- Unique values per element
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--elements-conditional.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--elements-conditional.png" alt="Conditional logic" /><br/>
<strong>Conditional logic</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--elements-source.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--elements-source.png" alt="View source" /><br/>
<strong>View source</strong>
</a>
</div></td>
</tr>
</table>
### States/Conditional logic
Drupal's State API can be used by developers to provide conditional logic
to hide and show form elements.
Drupal's State API supports:
- Show/Hide
- Required/Optional
- Open/Close
- Enable/Disable
### Viewing source
At the heart of a Webform module's form elements is a Drupal
[render array](https://www.drupal.org/docs/8/api/render-api/render-arrays),
which can be edited and managed by developers. The Drupal render array
gives developers complete control over a webform's elements, layout,
and look-and-feel by allowing developers to make bulk updates
to a webform's label, descriptions, and behaviors.
## Forms
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--forms-accessiblity.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--forms-accessiblity.png" alt="Accessibility" /><br/>
<strong>Accessibility</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--forms-wizard.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--forms-wizard.png" alt="Multistep form" /><br/>
<strong>Multistep form</strong>
</a>
</div></td>
</tr>
</table>
### Accessibility
The outputted forms and even the Webform module's administrative interface
(i.e. form builder) are accessible using keyboard navigation and screen readers.
The Webform module complies with [WCAG 2.0](http://www.w3.org/TR/WCAG20/#contents)
and [ATAG 2.0](http://www.w3.org/TR/ATAG20/#contents) guidelines.
### Multistep form
Forms can be broken up into multiple pages using a progress bar.
Authenticated users can save drafts and/or have their changes automatically
saved as they progress through a long form.
Multistep form features include:
- Customizable progress bar
- Customizable previous and next button labels and styles
- Saving drafts between steps
### Drupal integration
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--forms-block.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--forms-block.png" alt="Block" /><br/>
<strong>Block</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--forms-node.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--forms-node.png" alt="Node" /><br/>
<strong>Node</strong>
</a>
</div></td>
</tr>
</table>
Webforms can be attached to nodes or displayed as blocks.
Webforms can also have dedicated SEO-friendly URLs.
Form elements are render arrays that can easily be altered using
custom hooks and/or plugins.
## Results management
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--results.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--results.png" alt="Results" /><br/>
<strong>Results</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--results-customize.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--results-customize.png" alt="Customize results" /><br/>
<strong>Customize results </strong>
</a>
</div></td>
</tr>
</table>
Form submissions can optionally be stored in the database, reviewed,
and downloaded. Submissions can also be flagged with administrative notes.
Results management features include:
- Flagging
- Administrative notes
- Submission flagging, locking, and notes
- Viewing submissions as HTML, plain text, and YAML
- Customizable reports
- Downloading results as a CSV to Google Sheets or MS Excel
- Saving of download preferences per form
- Automatically purging old submissions based on certain criteria
- [Drupal Views](https://www.drupal.org/docs/8/core/modules/views) integration
for advanced reporting.
## Access controls
## Access Controls
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--access-permissions.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--access-permissions.png" alt="Permissions" /><br/>
<strong>Permissions</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--access-element.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--access-element.png" alt="Element access" /><br/>
<strong>Element access</strong>
</a>
</div></td>
</tr>
</table>
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-access.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-access-thumbnail.png" alt="Access Controls" />
</a>
</div>
The Webform module provides full access controls for managing who can create
forms, post submissions, and access a webform's results.
Access controls can be applied to roles and/or specific users.
The Webform module provides full access controls and permissions for managing
who can create forms, post submissions, and access a webform's results.
Access controls can be applied to roles and/or specific users.
The Webform access submodule allows you to even setup reusable permission
groups which can be applied to multiple instances of the same webform.
Access controls allow users to:
@ -226,162 +467,173 @@ Access controls allow users to:
- View selected elements
- Update selected elements
## Reusable templates
## Reusable Templates
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--templates.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--templates.png" alt="Templates" /><br/>
<strong>Templates</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--templates-preview.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--templates-preview.png" alt="Templates preview" /><br/>
<strong>Templates preview</strong>
</a>
</div></td>
</tr>
</table>
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-templates.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-templates-thumbnail.png" alt="Reusable Templates" />
</a>
</div>
The Webform module provides a few starter templates and multiple example forms
which webform administrators can update or use to create new reusable templates
for their organization.
The Webform module provides a few starter templates and multiple example
forms which webform administrators can update or use to create new
reusable templates for their organization.
Starter templates include:
- Contact Us
- Contact Us
- Donation
- Employee Evaluation
- Issue
- Job Application
- Job Application
- Job Seeker Profile
- Registration
- Session Evaluation
- Subscribe
- User Profile
Example webforms include:
## Reusable options
- Elements
- Basic layout
- Flexbox layout
- Input masks
- Options
- Wizard
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--options.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--options.png" alt="Options" /><br/>
<strong>Options</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--options-likert.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--options-likert.png" alt="Likert" /><br/>
<strong>Likert</strong>
</a>
</div></td>
</tr>
</table>
## Reusable Options
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-options.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-options-thumbnail.png" alt="Reusable Options" />
</a>
</div>
Administrators can define reusable global options for select menus, checkboxes,
and radio buttons. The Webform module includes default options for states,
countries, [likert](https://en.wikipedia.org/wiki/Likert_scale) answers,
and more.
Administrators can define reusable global options for select menus, checkboxes,
and radio buttons. The Webform module includes default options for states,
countries, demographics, likert answers, and more.
Reusable options include:
- Country codes & names
- Days, Months, Time zones
- Education, Employment status, Ethnicity, Industry, Languages, Marital status, Relationship, Size, and Titles
- Likert agreement, comparison, importance, quality, satisfaction, ten scale, and
would you
- State/province codes & names
- State codes & names
- **Geographic**: Languages, country, and states
- **Date and time**: Days, months, and time zones
- **Demographic**: Education, employment status, ethnicity, Industry,
languages, marital status, relationship, size, and job titles
- **Likert**: Agreement, comparison, importance, quality, satisfaction,
ten scale, and would you
## Internationalization
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-internalization.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-internalization-thumbnail.png" alt="Internationalization" />
</a>
</div>
Forms and configuration can be translated into multiple languages using Drupal's
configuration translation system.
Forms and configuration can be translated into multiple languages using
Drupal's [configuration translation system](https://www.drupal.org/docs/8/core/modules/config-translation.
## Add-ons
## Drupal Integration
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--addons.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--addons.png" alt="Add-ons" /><br/>
<strong>Add-ons</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--addons-webform-analysis.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--addons-webform-analysis.png" alt="Analysis" /><br/>
<strong>Analysis</strong>
</a>
</div></td>
</tr>
</table>
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-integration.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-integration-thumbnail.png" alt="Drupal Integration" />
</a>
</div>
There are [dozens of add-ons available](https://www.drupal.org/node/2837065)
that extend and/or provide additional functionality to the Webform module
and Drupal's Form API.
Forms can be attached to nodes or displayed as blocks. Webforms can also have
dedicated SEO-friendly URLs. Webform elements are simply render arrays that can
easily be altered using custom hooks and/or plugins.
Add-ons include:
- Analysis for creating graphs and charts
- CRM integration including SalesForce, HubSpot, MyEmma, SugarCRM, more…
- SPAM protection
- Advanced workflows
- Data encryption
- GDPR compliance
## Add-ons & Third Party Settings
## Development tools
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-add-ons.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-add-ons-thumbnail.png" alt="Add-ons & Third Party Settings" />
</a>
</div>
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--devel-test.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--devel-test.png" alt="Test" /><br/>
<strong>Test</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--devel-api.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--devel-api.png" alt="API" /><br/>
<strong>API</strong>
</a>
</div></td>
</tr>
</table>
Includes a list of modules and projects that extend and/or provide additional
functionality to the Webform module and Drupal's Form API.
Examples and tools are provided to help developers get started customizing
existing features and adding new features to the Webform module.
Development tools include:
## Extendable Plugins
- Test forms using customizable default values
- Easy to export configuration files
- Debugging tools for all handlers
- Examples for external API integration using remotes posts or custom code
- Example modules for creating custom elements and handlers
- Demos for building event registration and application evaluation system
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-plugin.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-plugin.png" alt="Extendable Plugins" />
</a>
</div>
## Drush & Composer integration
The Webform module provides [plugins](https://www.drupal.org/developing/api/8/plugins)
and hooks that allow contrib and custom modules to extend and enhance webform
elements and submission handling.
**WebformElement plugin** is used to integrate and enhance webform elements so
that they can be properly integrated into the Webform module.
**WebformHandler plugin** allows developers to extend a webform's submission
handling.
**WebformExporter plugin** allows developers to export results using custom
formats and file types.
## Help & Video Tutorials
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-help.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-help-thumbnail.png" alt="Help & Video Tutorials" />
</a>
</div>
The Webform module provides examples, inline help, and screencast walk throughs.
Screencasts include:
- [Welcome to the Webform module](https://youtu.be/sQGsfQ_LZJ4)
- [Installing the Webform module and third party libraries](https://youtu.be/IMfFTrsjg5k)
- [Managing Webforms, Templates, and Examples](https://youtu.be/T5MVGa_3jOQ)
- [Adding Elements, Composites, and Containers](https://youtu.be/LspF9mAvRcY)
- [Configuring Webform Settings and Behaviors](https://youtu.be/UJ0y09ZS9Uc)
- [Controlling Access to Webforms and Elements](https://youtu.be/SFm76DAVjbE)
- [Collecting Submissions, Sending Emails, and Posting Results](https://youtu.be/OdfVm5LMH9A)
- [Placing Webforms in Blocks and Creating Webform Nodes](https://youtu.be/xYBW2g0osd4)
- [Administering and Extending the Webform module](https://youtu.be/bkScAX_Qbt4)
- [Using the Source](https://youtu.be/2pWkJiYeR6E)
- [Getting Help](https://youtu.be/sRXUR2c2brA)
## Drush Integration
<div class="thumbnail">
<a href="https://www.drupal.org/files/webform-8.x-5.x-drush.png">
<img src="https://www.drupal.org/files/webform-8.x-5.x-drush.png" alt="Drush Integration" />
</a>
</div>
<table class="views-view-grid" width="100%">
<tr>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--drush.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--drush.png" alt="Drush" /><br/>
<strong>Drush</strong>
</a>
</div></td>
<td width="50%"><div class="note">
<a href="https://www.drupal.org/files/webform-8.x.5.x-features--drush-composer.png">
<img src="https://www.drupal.org/files/webform-8.x.5.x-features--drush-composer.png" alt="Composer" /><br/>
<strong>Composer</strong>
</a>
</div></td>
</tr>
</table>
Drush commands are provided to:
- Generate multiple webform submissions
- Export webform submissions
- Purge webform submissions
- Download and manage third party libraries
- Generate multiple submissions
- Export submissions
- Purge submissions
- Download and manage third-party libraries
- Generate a composer.js file for third-party libraries
- Tidy YAML configuration files

View file

@ -11,6 +11,10 @@ Steps for creating a new release
1. Review code
--------------
# Remove files that should never be reviewed.
cd modules/sandbox/webform
rm *.patch interdiff-*
[PHP](https://www.drupal.org/node/1587138)
# Check Drupal PHP coding standards

View file

@ -177,13 +177,13 @@ function webform_drush_command() {
),
),
'webform-repair' => array(
'description' => 'Makes sure all Webform admin settings and webforms are up-to-date.',
'description' => 'Makes sure all Webform admin configuration and webform settings are up-to-date.',
'core' => array(
'8+',
),
'bootstrap' => 1,
'examples' => array(
'webform-repair' => 'Repairs admin settings and webforms are up-to-date.',
'webform-repair' => 'Repairs admin configuration and webform settings are up-to-date.',
),
'aliases' => array(
'wfr',

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

View file

@ -7,9 +7,31 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Datetime\DateHelper;
/**
* Callback for custom datetime datepicker.
* Callback for removing abbreviation from datelist.
*
* @param array $element
* The element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Datetime\DrupalDateTime|null $date
* The date value.
*
* @see \Drupal\Core\Datetime\Element\Datelist::processDatelist
*/
function _webform_datelist_date_date_callback(array &$element, FormStateInterface $form_state, $date) {
$no_abbreviate = (isset($element['#date_abbreviate']) && $element['#date_abbreviate'] === FALSE);
if ($no_abbreviate && isset($element['month']) && isset($element['month']['#options'])) {
// Load translated date part labels from the appropriate calendar plugin.
$date_helper = new DateHelper();
$element['month']['#options'] = $date_helper->monthNames($element['#required']);;
}
}
/**
* Callback for custom datetime date element.
*
* @param array $element
* The element.
@ -20,19 +42,27 @@ use Drupal\Core\Datetime\DrupalDateTime;
*
* @see \Drupal\webform\Plugin\WebformElement\DateTime::prepare
*/
function _webform_datetime_datepicker(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Convert #type from datepicker to textfield.
if (isset($element['#date_date_element']) && $element['#date_date_element'] === 'datepicker') {
$element['date']['#type'] = 'textfield';
function _webform_datetime_date(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Make sure the date element is being displayed.
if (!isset($element['date'])) {
return;
}
// Must manually set 'data-drupal-date-format' to trigger date picker.
// @see \Drupal\Core\Render\Element\Date::processDate
$element['date']['#attributes']['data-drupal-date-format'] = [$element['date']['#date_date_format']];
$type = (isset($element['#date_date_element'])) ? $element['#date_date_element'] : 'date';
switch ($type) {
case 'datepicker':
// Convert #type from datepicker to textfield.
$element['date']['#type'] = 'textfield';
// Must manually set 'data-drupal-date-format' to trigger date picker.
// @see \Drupal\Core\Render\Element\Date::processDate
$element['date']['#attributes']['data-drupal-date-format'] = [$element['date']['#date_date_format']];
break;
}
}
/**
* Callback for custom datetime timepicker.
* Callback for custom datetime time element.
*
* @param array $element
* The element.
@ -43,16 +73,58 @@ function _webform_datetime_datepicker(array &$element, FormStateInterface $form_
*
* @see \Drupal\webform\Plugin\WebformElement\DateTime::prepare
*/
function _webform_datetime_timepicker(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Convert #type from timepicker to textfield.
if (isset($element['#date_time_element']) && $element['#date_time_element'] === 'timepicker') {
$element['time']['#type'] = 'textfield';
function _webform_datetime_time(array &$element, FormStateInterface $form_state, DrupalDateTime $date = NULL) {
// Make sure the time element is being displayed.
if (!isset($element['time'])) {
return;
}
// Must manually set 'data-webform-time-format' to trigger time picker.
// @see \Drupal\webform\Element\WebformTime::processWebformTime
$element['time']['#attributes']['data-webform-time-format'] = [$element['#date_time_format']];
// Apply time specific min/max to the element.
foreach (['min', 'max'] as $property) {
if (!empty($element["#date_time_$property"])) {
$value = $element["#date_time_$property"];
}
elseif (!empty($element["#date_$property"])) {
$value = date('H:i:s', strtotime($element["#date_$property"]));
}
else {
$value = NULL;
}
if ($value) {
$element['time']["#$property"] = $value;
$element['time']['#attributes'][$property] = $value;
}
}
// Attached custom timepicker library.
$element['time']['#attached']['library'][] = 'webform/webform.element.time';
// Apply time step and format to the element.
if (!empty($element['#date_time_step'])) {
$element['time']['#step'] = $element['#date_time_step'];
$element['time']['#attributes']['step'] = $element['#date_time_step'];
}
if (!empty($element['#date_time_format'])) {
$element['time']['#time_format'] = $element['#date_time_format'];
}
// Remove extra attributes for date element.
unset(
$element['time']['#attributes']['data-min-year'],
$element['time']['#attributes']['data-max-year']
);
$type = (isset($element['#date_time_element'])) ? $element['#date_time_element'] : 'time';
switch ($type) {
case 'timepicker':
$element['time']['#type'] = 'webform_time';
$element['time']['#timepicker'] = TRUE;
break;
case 'time':
$element['time']['#type'] = 'webform_time';
break;
case 'text':
$element['time']['#element_validate'][] = ['\Drupal\webform\Element\WebformTime', 'validateWebformTime'];
break;
}
}

View file

@ -19,6 +19,7 @@ use Drupal\webform\Plugin\WebformHandler\EmailWebformHandler;
use Drupal\webform\WebformInterface;
use Drupal\webform\Plugin\WebformHandler\RemotePostWebformHandler;
use Drupal\webform\Utility\WebformArrayHelper;
use Drupal\webform\Utility\WebformFormHelper;
use Drupal\webform\Utility\WebformOptionsHelper;
use Drupal\webform\Utility\WebformReflectionHelper;
use Drupal\webform\Utility\WebformYaml;
@ -2712,6 +2713,10 @@ function webform_update_8146() {
}
}
/******************************************************************************/
// Webform-8.x-5.0-rc23 - October 20, 2018.
/******************************************************************************/
/**
* Issue #3006468: Hide empty fields on on submission page.
*/
@ -2743,9 +2748,200 @@ function webform_update_8149() {
}
}
/******************************************************************************/
// Webform-8.x-5.0-rc24 - October 22, 2018.
/******************************************************************************/
/**
* Issue #2980032: SUBMISSION BEHAVIORS: Allow edit the previous submission.
*/
function webform_update_8150() {
_webform_update_webform_settings();
}
/******************************************************************************/
// Webform-8.x-5.0-rc25 - November 5, 2018 (No update required).
/******************************************************************************/
/******************************************************************************/
// Webform-8.x-5.0-rc26 - November 5, 2018 (No update required).
/******************************************************************************/
/******************************************************************************/
// Webform-8.x-5.0-rc27 - November 28, 2018.
/******************************************************************************/
/**
* Issue #3013767: Computed twig element is not working on multi-step form.
*/
function webform_update_8151() {
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$elements = $webform_config->get('elements');
// Try to decode elements.
try {
$elements = Yaml::decode($elements);
}
catch (\Exception $exception) {
continue;
}
// Make sure elements is an array.
if (!is_array($elements)) {
continue;
}
$has_computed_element = FALSE;
$flattened_elements =& WebformFormHelper::flattenElements($elements);
foreach ($flattened_elements as &$element) {
// Convert #value property to #template property.
// @see \Drupal\webform\Entity\Webform::initElementsRecursive
if (isset($element['#type']) && strpos($element['#type'], 'webform_computed_') === 0) {
$has_computed_element = TRUE;
if (isset($element['#value']) && !isset($element['#template'])) {
$element['#template'] = $element['#value'];
unset($element['#value']);
}
}
}
if ($has_computed_element) {
$webform_config->set('elements', Yaml::encode($elements));
$webform_config->save(TRUE);
}
}
}
/**
* Issue #3014933: Webform paths not being removed when a webform is deleted.
*/
function webform_update_8153() {
// Load all webforms to improve performance.
$webform = Webform::loadMultiple();
$database = \Drupal::database();
$select = $database->select('url_alias', 'u');
$select->fields('u', ['pid', 'source', 'alias', 'langcode']);
$select->condition('source', '/webform/%', 'LIKE');
$result = $select->execute();
while ($record = $result->fetchAssoc()) {
if (preg_match('#^/webform/([^/]+)/(?:drafts|submissions)$#', $record['source'], $match)) {
// Check if the webform still exists.
$webform_id = $match[1];
if (!isset($webform[$webform_id])) {
// Delete the broken URL alias.
$database->delete('url_alias')
->condition('pid', $record['pid'])
->execute();
}
}
}
}
/**
* Issue #3015990: Option not to store the IP address for logged-in users.
*/
function webform_update_8154() {
_webform_update_webform_settings();
}
/******************************************************************************/
// Webform-8.x-5.0-rc28 - TBD.
/******************************************************************************/
/**
* Issue #3017679: 2 different validation range modes for date/time field.
*/
function webform_update_8155() {
$config_factory = \Drupal::configFactory();
foreach ($config_factory->listAll('webform.webform.') as $webform_config_name) {
$webform_config = $config_factory->getEditable($webform_config_name);
$elements = $webform_config->get('elements');
// Try to decode elements.
try {
$elements = Yaml::decode($elements);
}
catch (\Exception $exception) {
continue;
}
// Make sure elements is an array.
if (!is_array($elements)) {
continue;
}
$has_date_element = FALSE;
$flattened_elements =& WebformFormHelper::flattenElements($elements);
foreach ($flattened_elements as &$element) {
// Convert #min/max property to #date_date_(min|max) property.
// @see \Drupal\webform\Entity\Webform::initElementsRecursive
if (isset($element['#type']) && in_array($element['#type'], ['date', 'datetime', 'datelist'])) {
$has_date_element = TRUE;
if (isset($element['#min']) && !isset($element['#date_date_min'])) {
$element['#date_date_min'] = $element['#min'];
unset($element['#min']);
}
if (isset($element['#max']) && !isset($element['#date_date_max'])) {
$element['#date_date_max'] = $element['#max'];
unset($element['#max']);
}
}
}
if ($has_date_element) {
$webform_config->set('elements', Yaml::encode($elements));
$webform_config->save(TRUE);
}
}
}
/**
* Issue #3015180: Add 'webform_submission_log' submodule.
*/
function webform_update_8156() {
$enable = \Drupal::config('webform.settings')->get('settings.default_submission_log');
if (!$enable) {
$query = \Drupal::entityQuery('webform')
->condition('settings.submission_log', TRUE)
->count();
$enable = $query->execute() > 0;
}
if ($enable) {
try {
\Drupal::service('module_installer')->install(['webform_submission_log']);
}
catch (\Drupal\Core\Database\SchemaObjectExistsException $exception) {
// This is actually expected. The table {webform_submission_log} would exist
// from webform submission entity schema.
}
// Because MySQL does not allow default value on blob/text column types and
// we want to add a not null blob column to a table that is likely to have
// existing rows, we are doing it in such a 3-step fashion.
\Drupal::database()->schema()->addField('webform_submission_log', 'variables', [
'type' => 'blob',
'size' => 'big',
'description' => 'Serialized array of variables that match the message string and that is passed into the t() function.',
]);
\Drupal::database()->update('webform_submission_log')->fields([
'variables' => serialize([]),
])->execute();
\Drupal::database()->schema()->changeField('webform_submission_log', 'variables', 'variables', [
'type' => 'blob',
'not null' => TRUE,
'size' => 'big',
'description' => 'Serialized array of variables that match the message string and that is passed into the t() function.',
]);
}
}
/**
* Issue #3022398: Possible modification to update hook and/or documentation.
*/
function webform_update_8157() {
_webform_update_webform_submission_storage_schema();
}

View file

@ -9,24 +9,37 @@
* Implements hook_library_info_alter().
*/
function webform_library_info_alter(&$libraries, $extension) {
$webform_libraries_modules = \Drupal::moduleHandler()->getImplementations('webform_libraries_info');
$webform_libraries_modules[] = 'webform';
// Only alter modules that declare webform libraries.
// @see hook_webform_libraries_info()
$webform_libraries_modules = \Drupal::moduleHandler()->getImplementations('webform_libraries_info');
$webform_libraries_modules[] = 'webform';
if (!in_array($extension, $webform_libraries_modules)) {
return;
}
// Prevent duplicate instances of the chosen plugin and use
// the chosen_lib.module's as the dependency.
if (isset($libraries['webform.element.chosen']) && \Drupal::moduleHandler()->moduleExists('chosen_lib')) {
$dependencies =& $libraries['webform.element.chosen']['dependencies'];
foreach ($dependencies as $index => $dependency) {
if ($dependency === 'webform/libraries.jquery.chosen') {
$dependencies[$index] = 'chosen_lib/chosen';
$dependencies[] = 'chosen_lib/chosen.css';
break;
// If chosen_lib.module is installed, then update the dependency.
if (\Drupal::moduleHandler()->moduleExists('chosen_lib')) {
if (isset($libraries['webform.element.chosen'])) {
$dependencies =& $libraries['webform.element.chosen']['dependencies'];
foreach ($dependencies as $index => $dependency) {
if ($dependency === 'webform/libraries.jquery.chosen') {
$dependencies[$index] = 'chosen_lib/chosen';
$dependencies[] = 'chosen_lib/chosen.css';
break;
}
}
}
}
// If select2.module is installed, then update the dependency.
if (\Drupal::moduleHandler()->moduleExists('select2')) {
if (isset($libraries['webform.element.select2'])) {
$dependencies =& $libraries['webform.element.select2']['dependencies'];
foreach ($dependencies as $index => $dependency) {
if ($dependency === 'webform/libraries.jquery.select2') {
$dependencies[$index] = 'select2/select2';
break;
}
}
}
}
@ -43,6 +56,11 @@ function webform_library_info_alter(&$libraries, $extension) {
continue;
}
// Skip libraries installed by other modules.
if (isset($library['module'])) {
continue;
}
if (!empty($library['dependencies'])) {
// Remove excluded libraries from dependencies.
foreach ($library['dependencies'] as $dependency_index => $dependency_name) {

View file

@ -73,3 +73,16 @@ function webform_webform_options_languages_alter(array &$options, array $element
}
}
}
/**
* Implements hook_webform_options_WEBFORM_OPTIONS_ID_alter().
*/
function webform_webform_options_translations_alter(array &$options, array $element = []) {
if (empty($options)) {
$languages = \Drupal::languageManager()->getLanguages();
$options = [];
foreach ($languages as $language) {
$options[$language->getId()] = $language->getName();
}
}
}

View file

@ -289,13 +289,16 @@ function webform_preprocess_table(&$variables) {
foreach ($variables['rows'] as &$row) {
// Check first cell.
if (!isset($row['cells'][0]['content'])
|| !is_array($row['cells'][0]['content'])
|| !isset($row['cells'][0]['content']['#markup'])) {
continue;
}
// Check last cell edit link.
if (!isset($row['cells'][1]['content'])
|| !is_array($row['cells'][1]['content'])
|| !isset($row['cells'][1]['content']['#links'])
|| !is_array($row['cells'][1]['content']['#links'])
|| !isset($row['cells'][1]['content']['#links']['edit'])) {
continue;
}

View file

@ -283,6 +283,11 @@ function template_preprocess_webform_submission_navigation(array &$variables) {
*/
function template_preprocess_webform_submission(array &$variables) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
$variables['navigation'] = $variables['elements']['navigation'];
$variables['information'] = $variables['elements']['information'];
$variables['submission'] = $variables['elements']['submission'];
$variables['webform_submission'] = $variables['elements']['#webform_submission'];
if ($variables['webform_submission'] instanceof WebformSubmissionInterface) {
$variables['webform'] = $variables['webform_submission']->getWebform();
@ -413,19 +418,21 @@ function template_preprocess_webform_element_base_html(array &$variables) {
if (empty($variables['options']['email'])) {
$type = $element['#type'];
$attributes = (isset($element['#format_attributes'])) ? $element['#format_attributes'] : [];
$attributes += ['class' => []];
// Use wrapper attributes for the id instead of #id,
// this stops the <label> from having a 'for' attribute.
$attributes += [
'id' => $element['#webform_id'],
];
$attributes['class'][] = 'webform-element';
$attributes['class'][] = 'webform-element-type-' . str_replace('_', '-', $type);
$variables['item'] = [
'#type' => 'item',
'#title' => $variables['title'],
'#name' => $element['#webform_key'],
// Use wrapper attributes for the id instead of #id,
// this stops the <label> from having a 'for' attribute.
'#wrapper_attributes' => [
'id' => $element['#webform_id'],
'class' => [
'webform-element',
'webform-element-type-' . str_replace('_', '-', $type),
],
],
'#wrapper_attributes' => $attributes,
];
if (is_array($variables['value'])) {
$variables['item']['value'] = $variables['value'];
@ -942,8 +949,11 @@ function template_preprocess_webform_element_image_file(array &$variables) {
$uri = $file->getFileUri();
$url = Url::fromUri(file_create_url($uri));
$extension = pathinfo($uri, PATHINFO_EXTENSION);
$is_image = in_array($extension, ['gif', 'png', 'jpg', 'jpeg']);
// Build image.
if (\Drupal::moduleHandler()->moduleExists('image') && $style_name && ImageStyle::load($style_name)) {
if ($is_image && \Drupal::moduleHandler()->moduleExists('image') && $style_name && ImageStyle::load($style_name)) {
$variables['image'] = [
'#theme' => 'image_style',
'#style_name' => $variables['style_name'],

View file

@ -187,16 +187,7 @@ function webform_lingotek_config_entity_document_upload(array &$source_data, Con
$translation_elements = $translation_manager->getTranslationElements($entity, $entity->language()->getId());
$source_data['elements'] = $translation_elements;
// Encode all [tokens].
$yaml = Yaml::encode($source_data);
$yaml = preg_replace_callback(
'/\[([a-z][^]]+)\]/',
function ($matches) {
return '[***' . base64_encode($matches[1]) . '***]';
},
$yaml
);
$source_data = Yaml::decode($yaml);
_webform_lingotek_decode_tokens($source_data);
break;
case 'webform_options';
@ -212,16 +203,7 @@ function webform_lingotek_config_entity_document_upload(array &$source_data, Con
function webform_lingotek_config_entity_translation_presave(ConfigEntityInterface &$translation, $langcode, &$data) {
switch ($translation->getEntityTypeId()) {
case 'webform';
// Decode all [tokens].
$yaml = Yaml::encode($data);
$yaml = preg_replace_callback(
'/\[\*\*\*([^]]+)\*\*\*\]/',
function ($matches) {
return '[' . base64_decode($matches[1]) . ']';
},
$yaml
);
$data = Yaml::decode($yaml);
_webform_lingotek_decode_tokens($data);
/** @var \Drupal\webform\WebformInterface $translation */
$translation->setElements($data['elements']);
@ -236,3 +218,79 @@ function webform_lingotek_config_entity_translation_presave(ConfigEntityInterfac
break;
}
}
/**
* Implements hook_lingotek_config_object_document_upload()
*/
function webform_lingotek_config_object_document_upload(array &$data, $config_name) {
if ($config_name !== 'webform.settings') {
return;
}
$data['webform.settings']['test.types'] = Yaml::decode($data['webform.settings']['test.types']);
$data['webform.settings']['test.names'] = Yaml::decode($data['webform.settings']['test.names']);
_webform_lingotek_encode_tokens($data);
}
/**
* Implements hook_lingotek_config_object_translation_presave()
*/
function webform_lingotek_config_object_translation_presave(array &$data, $config_name) {
if ($config_name !== 'webform.settings') {
return;
}
_webform_lingotek_decode_tokens($data);
$data['webform.settings']['test.types'] = Yaml::encode($data['webform.settings']['test.types']);
$data['webform.settings']['test.names'] = Yaml::encode($data['webform.settings']['test.names']);
}
/******************************************************************************/
// Lingotek decode/encode token functions.
/******************************************************************************/
/**
* Encode all tokens so that they won't be translated.
*
* @param array $data
* An array of data.
*/
function _webform_lingotek_encode_tokens(array &$data) {
$yaml = Yaml::encode($data);
$yaml = preg_replace_callback(
'/\[([a-z][^]]+)\]/',
function ($matches) {
// Encode all token characters to HTML entities.
// @see https://stackoverflow.com/questions/6720826/php-convert-all-characters-to-html-entities.
$replacement = mb_encode_numericentity($matches[1], array(0x000000, 0x10ffff, 0, 0xffffff), 'UTF-8');
return "[$replacement]";
},
$yaml
);
$data = Yaml::decode($yaml);
}
/**
* Decode all tokens after string have been translated.
*
* @param array $data
* An array of data.
*/
function _webform_lingotek_decode_tokens(array &$data) {
$yaml = Yaml::encode($data);
$yaml = preg_replace_callback(
'/\[([^]]+?)\]/',
function ($matches) {
// Decode token HTML entities to characters.
// @see https://stackoverflow.com/questions/6720826/php-convert-all-characters-to-html-entities.
$token = mb_decode_numericentity($matches[1], array(0x000000, 0x10ffff, 0, 0xffffff), 'UTF-8');
return "[$token]";
},
$yaml
);
$data = Yaml::decode($yaml);
}

View file

@ -0,0 +1,33 @@
/**
* @file
* JavaScript behaviors for announcing changes.
*/
(function ($, Drupal) {
'use strict';
/**
* Provide Webform announce attribute behavior.
*
* Announces changes using [data-webform-announce] attribute.
*
* The announce attributes allows FAPI Ajax callbacks to easily
* trigger announcements.
*
* @see \Drupal\webform\Element\WebformComputedBase::ajaxWebformComputedCallback
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches the behavior to [data-webform-announce] attribute.
*/
Drupal.behaviors.webformAnnounce = {
attach: function (context) {
$('[data-webform-announce]', context).once('data-webform-announce').each(function () {
Drupal.announce($(this).data('webform-announce'));
});
}
};
})(jQuery, Drupal);

View file

@ -38,7 +38,7 @@
var options = $.extend({
mode: $(this).attr('data-webform-codemirror-mode'),
lineNumbers: true,
lineWrapping: true,
c: ($(this).attr('wrap') === 'off') ? false : true,
viewportMargin: Infinity,
readOnly: ($(this).prop('readonly') || $(this).prop('disabled')) ? true : false,
extraKeys: {

View file

@ -29,26 +29,36 @@
return;
}
// Add event handler to elements that are used by the computed element.
// Get computed element triggers.
var inputs = [];
$.each(elementKeys, function (i, key) {
$form.find(':input[name^="' + key + '"]')
.on('keyup change', debounce(triggerUpdate, Drupal.webform.computed.delay));
// Exact input match.
inputs.push(':input[name="' + key + '"]');
// Sub inputs. (aka #tree)
inputs.push(':input[name^="' + key + '["]');
});
var $triggers = $form.find(inputs.join(','));
// Add event handler to computed element triggers.
$triggers.on('keyup change',
debounce(triggerUpdate, Drupal.webform.computed.delay));
// Initialize computed element update which refreshes the displayed
// value and accounts for any changes to the #default_value for a
// computed element.
triggerUpdate();
triggerUpdate(true);
function triggerUpdate() {
function triggerUpdate(initialize) {
// Prevent duplicate computations.
// @see Drupal.behaviors.formSingleSubmit
var formValues = $form.find('input[name!=form_build_id]').serialize();
var previousValues = $element.attr('data-webform-computed-last');
if (previousValues === formValues) {
return;
if (initialize !== true) {
var formValues = $triggers.serialize();
var previousValues = $element.attr('data-webform-computed-last');
if (previousValues === formValues) {
return;
}
$element.attr('data-webform-computed-last', formValues);
}
$element.attr('data-webform-computed-last', formValues);
// Add loading class to computed wrapper.
$element.find('.js-webform-computed-wrapper')

View file

@ -41,6 +41,16 @@
changeYear: true
}, Drupal.webform.datePicker.options);
// Add datepicker button.
if ($input.hasData('datepicker-button')) {
options = $.extend({
showOn: 'both',
buttonImage: settings.webform.datePicker.buttonImage,
buttonImageOnly: true,
buttonText: Drupal.t('Select date')
}, Drupal.webform.datePicker.options);
}
var dateFormat = $input.data('drupalDateFormat');
// The date format is saved in PHP style, we need to convert to jQuery
@ -78,6 +88,11 @@
// First day of the week.
options.firstDay = settings.webform.dateFirstDay;
// Disable autocomplete.
// @see https://gist.github.com/niksumeiko/360164708c3b326bd1c8
var isChrome = /Chrome/.test(window.navigator.userAgent) && /Google Inc/.test(window.navigator.vendor);
$input.attr('autocomplete', (isChrome) ? 'off' : 'false');
$input.datepicker(options);
});
}

View file

@ -56,7 +56,7 @@
// Set the saved states for all the details elements.
// @see webform.element.details.save.js
if (!Drupal.webformDetailsSaveGetName) {
if (Drupal.webformDetailsSaveGetName) {
$form.find('details').each(function () {
var name = Drupal.webformDetailsSaveGetName($(this));
if (name) {
@ -70,7 +70,7 @@
if ($tabs.length) {
// Add toggle state before the tabs.
$tabs.find('.item-list:first-child').before($toggle);
$tabs.find('.item-list:first-child').eq(0).before($toggle);
}
else {
// Add toggle state link to first details element.

View file

@ -66,7 +66,7 @@
// Disable autocomplete.
// @see https://gist.github.com/niksumeiko/360164708c3b326bd1c8
var isChrome = /Chrome/.test(window.navigator.userAgent) && /Google Inc/.test(window.navigator.vendor);
$input.attr('autocomplete', (isChrome) ? 'disabled' : 'false');
$input.attr('autocomplete', (isChrome) ? 'off' : 'false');
// Sync values on change and clear events.
placesAutocomplete.on('change', function (e) {

View file

@ -0,0 +1,53 @@
/**
* @file
* JavaScript behaviors for element #states.
*/
(function ($, Drupal, drupalSettings) {
'use strict';
/**
* Element #states builder.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.webformElementStates = {
attach: function (context) {
$(context).find('.webform-states-table--condition').once('webform-element-states').each(function () {
var $condition = $(this);
var $selector = $condition.find('.webform-states-table--selector select');
var $value = $condition.find('.webform-states-table--value input');
var $trigger = $condition.find('.webform-states-table--trigger select');
// Initialize autocompletion.
$value.autocomplete({minLength: 0}).on('focus', function () {
$value.autocomplete('search', '');
});
// Initialize trigger and selector.
$trigger.on('change', function () {$selector.change();});
$selector.on('change', function () {
var selector = $selector.val();
var sourceKey = drupalSettings.webformElementStates.selectors[selector];
var source = drupalSettings.webformElementStates.sources[sourceKey];
var notPattern = ($trigger.val().indexOf('pattern') === -1);
if (source && notPattern) {
// Enable autocompletion.
$value
.autocomplete('option', 'source', source)
.addClass('form-autocomplete');
}
else {
// Disable autocompletion.
$value
.autocomplete('option', 'source', [])
.removeClass('form-autocomplete');
}
}).change();
});
}
};
})(jQuery, Drupal, drupalSettings);

View file

@ -123,10 +123,10 @@
// @see Issue #2977569: Hidden fieldsets that become visible with conditional logic cannot be made required.
if ($target.is('.js-webform-type-radios, .js-webform-type-checkboxes, fieldset')) {
if (e.value) {
$target.find('legend span:not(.visually-hidden)').addClass('js-form-required form-required');
$target.find('legend span.fieldset-legend:not(.visually-hidden)').addClass('js-form-required form-required');
}
else {
$target.find('legend span:not(.visually-hidden)').removeClass('js-form-required form-required');
$target.find('legend span.fieldset-legend:not(.visually-hidden)').removeClass('js-form-required form-required');
}
}

View file

@ -19,12 +19,21 @@
attach: function (context) {
// Make sure on page load or Ajax refresh the location ?page is correct
// since conditional logic can skip pages.
// Note: window.history is only supported by IE 10+ and all other browsers.
if (window.history && history.replaceState) {
$('form[data-webform-wizard-current-page]', context).once('webform-wizard-current-page').each(function () {
var page = $(this).attr('data-webform-wizard-current-page');
history.replaceState(null, null, window.location.toString().replace(/\?.+$/, '') + '?page=' + page);
});
// Note: window.history is only supported by IE 10+.
if (window.history && window.history.replaceState) {
// Track the form's current page for 8.5.x and below.
// @todo Remove the below code once only 8.6.x is supported.
// @see https://www.drupal.org/project/drupal/issues/2508796
$('form[data-webform-wizard-current-page]', context)
.once('webform-wizard-current-page')
.each(function () {
trackPage(this);
});
// Track the form's current page for 8.6.x and above.
if ($(context).hasData('webform-wizard-current-page')) {
trackPage(context);
}
}
// When paging next and back update the URL so that Drupal knows what
@ -35,6 +44,23 @@
var page = $(this).attr('data-webform-wizard-page');
this.form.action = this.form.action.replace(/\?.+$/, '') + '?page=' + page;
});
/**
* Append the form's current page data attribute to the browser's URL.
*
* @param {HTMLElement} form
* The form element.
*/
function trackPage(form) {
var $form = $(form);
// Make sure the form is visible before updating the URL.
if ($form.is(':visible')) {
var page = $form.attr('data-webform-wizard-current-page');
var url = window.location.toString().replace(/\?.+$/, '') +
'?page=' + page;
window.history.replaceState(null, null, url);
}
}
}
};

View file

@ -31,7 +31,7 @@ use Drupal\webform_access\WebformAccessGroupInterface;
* },
* links = {
* "add-form" = "/admin/structure/webform/config/access/group/add",
* "edit-form" = "/admin/structure/webform/config/access/group/manage/{webform_access_group}/edit",
* "edit-form" = "/admin/structure/webform/config/access/group/manage/{webform_access_group}",
* "duplicate-form" = "/admin/structure/webform/config/access/group/manage/{webform_access_group}/duplicate",
* "delete-form" = "/admin/structure/webform/config/access/group/manage/{webform_access_group}/delete",
* "collection" = "/admin/structure/webform/config/access/group/manage",

View file

@ -29,7 +29,7 @@ use Drupal\webform_access\WebformAccessTypeInterface;
* },
* links = {
* "add-form" = "/admin/structure/webform/config/access/type/add",
* "edit-form" = "/admin/structure/webform/config/access/type/manage/{webform_access_type}/edit",
* "edit-form" = "/admin/structure/webform/config/access/type/manage/{webform_access_type}",
* "delete-form" = "/admin/structure/webform/config/access/type/manage/{webform_access_type}/delete",
* "collection" = "/admin/structure/webform/config/access/type/manage",
* },

View file

@ -38,7 +38,7 @@ class WebformAccessTest extends WebformAccessTestBase {
$this->drupalLogin($this->rootUser);
foreach ($this->groups as $name => $group) {
$this->drupalPostForm(
"/admin/structure/webform/access/group/manage/$name/edit",
"/admin/structure/webform/access/group/manage/$name",
['users[]' => $this->users[$name]->id()],
t('Save')
);
@ -64,7 +64,7 @@ class WebformAccessTest extends WebformAccessTestBase {
// Unassign employee user from employee group via the UI.
$this->drupalLogin($this->rootUser);
$this->drupalPostForm(
'/admin/structure/webform/access/group/manage/employee/edit',
'/admin/structure/webform/access/group/manage/employee',
['users[]' => 1],
t('Save')
);
@ -86,7 +86,7 @@ class WebformAccessTest extends WebformAccessTestBase {
$this->drupalLogin($this->rootUser);
foreach ($this->groups as $name => $group) {
$this->drupalPostForm(
"/admin/structure/webform/access/group/manage/$name/edit",
"/admin/structure/webform/access/group/manage/$name",
['entities[]' => 'node:' . $this->nodes['contact_02']->id() . ':webform:contact'],
t('Save')
);

View file

@ -5,13 +5,13 @@ namespace Drupal\webform_access;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\webform\Entity\Webform;
use Drupal\webform\Plugin\WebformElementManagerInterface;
use Drupal\webform\Utility\WebformDialogHelper;
use Drupal\webform\WebformAccessRulesManagerInterface;
use Drupal\webform\WebformEntityReferenceManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityManager;
/**
* Provides a form to define a webform access group.
@ -25,6 +25,13 @@ class WebformAccessGroupForm extends EntityForm {
*/
protected $database;
/**
* Entity manager.
*
* @var Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* The webform element manager.
*
@ -51,6 +58,8 @@ class WebformAccessGroupForm extends EntityForm {
*
* @param \Drupal\Core\Database\Connection $database
* The database.
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
* @param \Drupal\webform\Plugin\WebformElementManagerInterface $element_manager
* The webform element manager.
* @param \Drupal\webform\WebformEntityReferenceManagerInterface $webform_entity_reference_manager
@ -58,8 +67,9 @@ class WebformAccessGroupForm extends EntityForm {
* @param \Drupal\webform\WebformAccessRulesManagerInterface $webform_access_rules_manager
* The webform access rules manager.
*/
public function __construct(Connection $database, WebformElementManagerInterface $element_manager, WebformEntityReferenceManagerInterface $webform_entity_reference_manager, WebformAccessRulesManagerInterface $webform_access_rules_manager) {
public function __construct(Connection $database, EntityManager $entity_manager, WebformElementManagerInterface $element_manager, WebformEntityReferenceManagerInterface $webform_entity_reference_manager, WebformAccessRulesManagerInterface $webform_access_rules_manager) {
$this->database = $database;
$this->entityManager = $entity_manager;
$this->elementManager = $element_manager;
$this->webformEntityReferenceManager = $webform_entity_reference_manager;
$this->webformAccessRulesManager = $webform_access_rules_manager;
@ -71,6 +81,7 @@ class WebformAccessGroupForm extends EntityForm {
public static function create(ContainerInterface $container) {
return new static(
$container->get('database'),
$container->get('entity.manager'),
$container->get('plugin.manager.webform.element'),
$container->get('webform.entity_reference_manager'),
$container->get('webform.access_rules_manager')
@ -281,7 +292,7 @@ class WebformAccessGroupForm extends EntityForm {
$webforms = Webform::loadMultiple($webform_ids);
/** @var \Drupal\node\NodeInterface[] $nodes */
$nodes = Node::loadMultiple($nids);
$nodes = $this->entityManager->getStorage('node')->loadMultiple($nids);
$options = [];
foreach ($webform_nodes as $nid => $field_names) {

View file

@ -7,8 +7,8 @@ dependencies:
- 'drupal:webform'
- 'drupal:webform_node'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -15,3 +15,15 @@ webform.config.webform_access_type:
route_name: entity.webform_access_type.collection
parent_id: webform.config.webform_access
weight: 20
entity.webform_access_group.edit_form:
route_name: entity.webform_access_group.edit_form
base_route: entity.webform_access_group.edit_form
title: 'Edit'
weight: 0
entity.webform_access_type.edit_form:
route_name: entity.webform_access_type.edit_form
base_route: entity.webform_access_type.edit_form
title: 'Edit'
weight: 0

View file

@ -114,6 +114,17 @@ function webform_access_field_storage_config_delete(EntityInterface $entity) {
* @see \Drupal\Core\Menu\Plugin\Block\LocalTasksBlock::build
*/
function webform_access_menu_local_tasks_alter(&$data, $route_name) {
// Change config entities 'Translate *' tab to be just label 'Translate'.
$webform_entities = [
'webform_access_group',
'webform_access_type',
];
foreach ($webform_entities as $webform_entity) {
if (isset($data['tabs'][0]["config_translation.local_tasks:entity.$webform_entity.config_translation_overview"]['#link']['title'])) {
$data['tabs'][0]["config_translation.local_tasks:entity.$webform_entity.config_translation_overview"]['#link']['title'] = t('Translate');
}
}
$route_name = \Drupal::routeMatch()->getRouteName();
if ($route_name !== 'entity.node.canonical' && strpos($route_name, 'entity.node.webform.') !== 0) {
return;
@ -322,6 +333,19 @@ function _webform_access_form_node_form_submit(&$form, FormStateInterface $form_
* Add the webform access group to an individual user's account page.
*/
function webform_access_form_user_form_alter(&$form, FormStateInterface $form_state) {
// Make sure some webform access groups exist before displaying
// the webform access details widget.
if (!WebformAccessGroup::loadMultiple()) {
return;
}
// Only display the webform access detail widget if the current user can
// administer webform and users.
if (!\Drupal::currentUser()->hasPermission('administer webform')
|| !\Drupal::currentUser()->hasPermission('administer users')) {
return;
}
$account = $form_state->getFormObject()->getEntity();
$default_value = \Drupal::database()->select('webform_access_group_user', 'gu')
->fields('gu', ['group_id'])
@ -339,6 +363,7 @@ function webform_access_form_user_form_alter(&$form, FormStateInterface $form_st
$form,
$form_state
);
$form['actions']['submit']['#submit'][] = '_webform_access_user_profile_form_submit';
}

View file

@ -17,7 +17,7 @@ entity.webform_access_group.add_form:
_entity_create_access: 'webform_access_group'
entity.webform_access_group.edit_form:
path: '/admin/structure/webform/access/group/manage/{webform_access_group}/edit'
path: '/admin/structure/webform/access/group/manage/{webform_access_group}'
defaults:
_entity_form: 'webform_access_group.edit'
_title: 'Edit webform access group'
@ -59,7 +59,7 @@ entity.webform_access_type.add_form:
_entity_create_access: 'webform_access_type'
entity.webform_access_type.edit_form:
path: '/admin/structure/webform/access/type/manage/{webform_access_type}/edit'
path: '/admin/structure/webform/access/type/manage/{webform_access_type}'
defaults:
_entity_form: 'webform_access_type.edit'
_title: 'Edit webform access type'

View file

@ -8,8 +8,8 @@ dependencies:
- 'webform:webform'
- 'webform:webform_bootstrap'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -22,8 +22,8 @@ regions:
libraries:
- 'webform_bootstrap_test_theme/global-styling'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -6,8 +6,8 @@ package: Webform
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -7,6 +7,8 @@
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Utility\WebformArrayHelper;
use Drupal\webform\Utility\WebformElementHelper;
/**
* Implements hook_page_attachments().
@ -154,6 +156,27 @@ function webform_bootstrap_preprocess_input(&$variables) {
}
}
/**
* Prepares variables for form element templates.
*/
function webform_bootstrap_preprocess_form_element(&$variables) {
if (!_webform_bootstrap_is_active_theme()) {
return;
}
if (!WebformElementHelper::isWebformElement($variables['element'])) {
return;
}
// Do not display phone number using inline form.
// @see https://www.drupal.org/project/webform/issues/2910776s
// @see https://www.drupal.org/project/bootstrap/issues/2829634
if (WebformElementHelper::isType($variables['element'], 'tel')
&& isset($variables['attributes']['class'])) {
WebformArrayHelper::removeValue($variables['attributes']['class'], 'form-inline');
}
}
/**
* Implements template_preprocess_fieldset().
*/

View file

@ -88,6 +88,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -221,4 +222,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -44,6 +44,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -176,4 +177,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -8,8 +8,8 @@ dependencies:
- 'webform:webform'
- 'webform:webform_node'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -19,7 +19,7 @@ default_value:
status: open
open: ''
close: ''
target_uuid: c9a4a1ff-ba66-454d-a572-9c2624b73a67
target_uuid: ''
default_value_callback: ''
settings:
handler: 'default:webform'

View file

@ -64,6 +64,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -188,6 +189,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
email_notification:
id: email

View file

@ -10,8 +10,8 @@ dependencies:
- 'webform:webform_node'
- 'webform:webform_scheduled_email'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -56,6 +56,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -188,6 +189,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
employee_email:
id: email

View file

@ -10,8 +10,8 @@ dependencies:
- 'webform:webform_node'
- 'webform:webform_access'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -5,10 +5,11 @@ namespace Drupal\webform_devel\Commands;
use Drupal\Core\Serialization\Yaml;
use Drupal\webform\Utility\WebformYaml;
use Drush\Commands\DrushCommands;
use Drush\Exceptions\UserAbortException;
use Psr\Log\LogLevel;
/**
* Webform scheduled email commands for Drush 9.x.
* Webform devel commandfile.
*/
class WebformDevelCommands extends DrushCommands {
@ -63,4 +64,24 @@ class WebformDevelCommands extends DrushCommands {
}
}
/**
* Executes webform devel reset.
*
* @command webform:devel:reset
* @aliases wfdr
*
* @see drush_webform_devel_reset()
*/
public function drush_webform_devel_reset() {
if (!$this->io()->confirm(dt("Are you sure you want repair the Webform module's admin settings and webforms?"))) {
throw new UserAbortException();
}
$this->output()->writeln(dt('Resetting message closed via State API…'));
\Drupal::state()->delete('webform.element.message');
$this->output()->writeln(dt('Resetting message closed via User Data…'));
\Drupal::service('user.data')->delete('webform', NULL, 'webform.element.message');
}
}

View file

@ -46,6 +46,8 @@ function webform_devel_drush_help($section) {
/**
* Implements drush_hook_COMMAND().
*
* @see \Drupal\webform_devel\Commands\WebformDevelCommands::drush_webform_devel_reset()
*/
function drush_webform_devel_reset() {
if (!drush_confirm(dt("Are you sure you want reset the Webform module's user data and saved state?"))) {

View file

@ -7,8 +7,8 @@ dependencies:
- 'devel:devel'
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -7,8 +7,8 @@ hidden: true
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -40,6 +40,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -172,4 +173,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -39,6 +39,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -171,4 +172,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -19,7 +19,7 @@ category: Example
elements: |
value:
'#type': textfield
'#title': 'Value'
'#title': Value
'#required': true
'#description': 'Enter a value to displayed in a custom message.'
@ -39,6 +39,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -171,6 +172,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
example:
id: example
@ -182,6 +187,3 @@ handlers:
settings:
message: 'You entered: <code>[webform_submission:values:value]</code>'
debug: false
uuid: ce0077fd-9eb1-4bb9-a270-e82713f8d2d3
_core:
default_config_hash: tdCyBfZG8ZroUObP_Uc4R4mroXfqE2j2rY_pJd7ENT0

View file

@ -1,9 +1,9 @@
webform.handler.example:
type: mapping
label: 'Example'
label: Example
mapping:
message:
label: 'Message'
label: Message
type: string
debug:
type: boolean

View file

@ -83,7 +83,6 @@ class ExampleWebformHandler extends WebformHandlerBase {
'#type' => 'textfield',
'#title' => $this->t('Message to be displayed when form is completed'),
'#default_value' => $this->configuration['message'],
'#parents' => ['settings', 'message'],
'#required' => TRUE,
];
@ -97,11 +96,10 @@ class ExampleWebformHandler extends WebformHandlerBase {
'#title' => $this->t('Enable debugging'),
'#description' => $this->t('If checked, every handler method invoked will be displayed onscreen to all users.'),
'#return_value' => TRUE,
'#parents' => ['settings', 'debug'],
'#default_value' => $this->configuration['debug'],
];
return $form;
return $this->setSettingsParents($form);
}
/**

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -56,6 +56,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -190,6 +191,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
remote_post:
id: remote_post

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -19,7 +19,7 @@ elements: |
'#title': Calculation
'#type': webform_wizard_page
'#open': true
calculation:
calculation_section:
'#type': webform_section
'#title': 'Basic adding calculation using a ''computed twig'' element'
container:
@ -47,8 +47,8 @@ elements: |
'#type': webform_computed_twig
'#title': c
'#title_display': invisible
'#value': '{% if data.a|length and data.b|length %}{{ data.a + data.b }}{% else %}c{% endif %}'
'#ajax': true
'#template': '{% if data.a|length and data.b|length %}{{ data.a + data.b }}{% else %}c{% endif %}'
message_warning:
'#type': webform_message
'#states':
@ -87,9 +87,9 @@ elements: |
'#open': true
computed:
'#type': webform_computed_twig
'#title': 'Computed'
'#title': Computed
'#title_display': hidden
'#value': |
'#template': |
{% set attributes = create_attribute() %}
<h2{{ attributes.setAttribute('id', 'custom').setAttribute('style', 'color:' ~ data.color) }}>
Hello {{ data.first_name }} {{ data.last_name }}!!!
@ -112,6 +112,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -244,4 +245,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -37,8 +37,8 @@ elements: |
'#type': container
'#attributes':
class:
- 'container-inline'
- 'calculation'
- container-inline
- calculation
a:
'#type': number
'#title': a
@ -61,8 +61,8 @@ elements: |
'#type': webform_computed_twig
'#title': c
'#title_display': invisible
'#value': '{% if data.a|length and data.b|length %}{{ data.a + data.b }}{% else %}c{% endif %}'
'#ajax': true
'#template': '{% if data.a|length and data.b|length %}{{ data.a + data.b }}{% else %}c{% endif %}'
user_information:
'#type': fieldset
'#title': 'User information'
@ -78,33 +78,33 @@ elements: |
user_ud:
'#type': webform_computed_token
'#title': 'User: ID'
'#value': '[webform_submission:values:user:entity:uid:clear]'
'#ajax': true
'#hide_empty': true
'#template': '[webform_submission:values:user:entity:uid:clear]'
user_display_name:
'#type': webform_computed_token
'#title': 'User: Display name'
'#value': '[webform_submission:values:user:entity:display-name:clear]'
'#ajax': true
'#hide_empty': true
'#template': '[webform_submission:values:user:entity:display-name:clear]'
user_mail:
'#type': webform_computed_token
'#title': 'User: Email'
'#value': '[webform_submission:values:user:entity:mail:clear]'
'#ajax': true
'#hide_empty': true
'#template': '[webform_submission:values:user:entity:mail:clear]'
user_url:
'#type': webform_computed_token
'#title': 'User: URL'
'#value': '[webform_submission:values:user:entity:url:clear]'
'#ajax': true
'#hide_empty': true
'#template': '[webform_submission:values:user:entity:url:clear]'
user_created:
'#type': webform_computed_token
'#title': 'User: Created'
'#value': '[webform_submission:values:user:entity:created:clear]'
'#ajax': true
'#hide_empty': true
'#template': '[webform_submission:values:user:entity:created:clear]'
css: |
.calculation {
@ -130,6 +130,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -262,4 +263,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -208,6 +208,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -340,4 +341,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -134,6 +134,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -266,4 +267,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -102,6 +102,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -234,4 +235,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -380,7 +380,7 @@ elements: |
'#title': 'Employment status'
age:
'#type': number
'#title': 'Age'
'#title': Age
form_elements:
'#type': details
'#title': 'Form elements'
@ -390,12 +390,12 @@ elements: |
'#title': 'Form element'
'#description': '{description}'
'#size': 5
'#field_prefix': '$'
'#field_prefix': $
'#field_suffix': '.00'
form_element_required:
'#type': textfield
'#title': 'Form element (Required)'
'#required': TRUE
'#required': true
'#default_value': '{value}'
'#attributes':
class:
@ -483,9 +483,9 @@ elements: |
'#wrapper_attributes':
class:
- 'container-inline clearfix'
divider:
dividers:
'#type': details
'#title': 'Divider'
'#title': Dividers
'#open': true
horizontal_rule_dotted_medium:
'#type': webform_horizontal_rule
@ -540,7 +540,7 @@ elements: |
'#message_close': true
flexbox:
'#type': details
'#title': 'Flexbox'
'#title': Flexbox
'#open': true
webform_flexbox:
'#type': webform_flexbox
@ -582,6 +582,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -714,4 +715,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -72,6 +72,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -204,4 +205,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'webform:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -34,7 +34,7 @@ elements: |
'#open': true
select_select2:
'#type': select
'#title': 'Select2'
'#title': Select2
'#options':
one: One
two: Two
@ -133,14 +133,14 @@ elements: |
'#open': true
textfield_input_hide:
'#type': textfield
'#title': "Textfield with input hiding"
'#title': 'Textfield with input hiding'
'#input_hide': true
'#default_value': '{value}'
email_input_hide:
'#type': email
'#title': "Email with input hiding"
'#title': 'Email with input hiding'
'#input_hide': true
'#default_value': 'example@example.com'
'#default_value': example@example.com
widget_elements:
'#type': details
'#title': 'Widget elements'
@ -192,7 +192,7 @@ elements: |
'#title': 'Composite elements'
'#open': true
address:
'#title': 'Address'
'#title': Address
'#type': webform_address
multiple_elements:
'#type': details
@ -229,6 +229,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -361,4 +362,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -23,7 +23,7 @@ elements: |
'#title': 'Text field'
'#type': textfield
textarea:
'#title': 'Textarea'
'#title': Textarea
'#type': textarea
option_elements:
'#type': details
@ -33,31 +33,31 @@ elements: |
'#title': 'Select one'
'#type': select
'#options':
'option_1': 'Option 1'
'option_2': 'Option 2'
'option_3': 'Option 3'
option_1: 'Option 1'
option_2: 'Option 2'
option_3: 'Option 3'
select_multiple:
'#title': 'Select multiple'
'#type': select
'#multiple': true
'#options':
'option_1': 'Option 1'
'option_2': 'Option 2'
'option_3': 'Option 3'
option_1: 'Option 1'
option_2: 'Option 2'
option_3: 'Option 3'
radios:
'#title': 'Radios'
'#title': Radios
'#type': radios
'#options':
'option_1': 'Option 1'
'option_2': 'Option 2'
'option_3': 'Option 3'
option_1: 'Option 1'
option_2: 'Option 2'
option_3: 'Option 3'
checkboxes:
'#title': 'Checkboxes'
'#title': Checkboxes
'#type': checkboxes
'#options':
'option_1': 'Option 1'
'option_2': 'Option 2'
'option_3': 'Option 3'
option_1: 'Option 1'
option_2: 'Option 2'
option_3: 'Option 3'
checkbox:
'#type': checkbox
'#title': Checkbox
@ -125,9 +125,6 @@ elements: |
'#output': right
'#output__field_prefix': $
'#output__field_suffix': '.00'
color:
'#type': color
'#title': Color
css: ''
javascript: ''
@ -145,6 +142,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -277,4 +275,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -23,21 +23,21 @@ elements: |
'#help': 'This is help text.'
'#more': 'This is more text'
'#required': true
'#field_prefix': 'prefix'
'#field_suffix': 'suffix'
'#field_prefix': prefix
'#field_suffix': suffix
fieldset:
'#type': fieldset
'#title': 'Fieldset'
'#title': Fieldset
'#placeholder': 'This is a placeholder'
'#description': 'This is a description.'
'#help': 'This is help text.'
'#more': 'This is more text'
'#required': true
'#field_prefix': 'prefix'
'#field_suffix': 'suffix'
'#field_prefix': prefix
'#field_suffix': suffix
details:
'#type': details
'#title': 'details'
'#title': details
'#placeholder': 'This is a placeholder'
'#description': 'This is a description.'
'#help': 'This is help text.'
@ -67,6 +67,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -199,4 +200,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -27,17 +27,17 @@ elements: |
'#help': 'This is help text.'
'#more': 'This is more text'
'#required': true
'#field_prefix': 'prefix'
'#field_suffix': 'suffix'
'#field_prefix': prefix
'#field_suffix': suffix
datelist_element:
'#type': datelist
'#title': 'Datelist'
'#title': Datelist
'#placeholder': 'This is a placeholder'
'#description': 'This is a description.'
'#help': 'This is help text.'
'#more': 'This is more text'
'#field_prefix': 'prefix'
'#field_suffix': 'suffix'
'#field_prefix': prefix
'#field_suffix': suffix
element_title:
'#type': details
'#title': 'Element title'
@ -60,7 +60,6 @@ elements: |
'#title': 'Title displayed inline composite'
'#title_display': inline
'#description': 'This is a description.'
'#title_display': inline
'#options':
one: One
two: Two
@ -89,7 +88,7 @@ elements: |
'#open': true
help:
'#type': textfield
'#title': 'Help'
'#title': Help
'#help': 'This is help.'
element_more:
'#type': details
@ -97,7 +96,7 @@ elements: |
'#open': true
more:
'#type': textfield
'#title': 'More'
'#title': More
'#more': 'This is more text.'
fieldset_elements:
'#type': details
@ -105,13 +104,13 @@ elements: |
'#open': true
fieldset:
'#type': fieldset
'#title': 'Fieldset'
'#title': Fieldset
'#description': 'This is a description.'
'#help': 'This is help text.'
'#more': 'This is more text'
'#required': true
'#field_prefix': 'prefix'
'#field_suffix': 'suffix'
'#field_prefix': prefix
'#field_suffix': suffix
fieldset_description:
'#type': fieldset
'#title': 'Fieldset description'
@ -135,7 +134,7 @@ elements: |
'#open': true
details:
'#type': details
'#title': 'details'
'#title': details
'#description': 'This is a description.'
'#help': 'This is help text.'
'#more': 'This is more text'
@ -198,6 +197,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -330,4 +330,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -72,6 +72,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -204,4 +205,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -6,8 +6,8 @@ package: 'Webform example'
dependencies:
- 'drupal:webform'
# Information added by Drupal.org packaging script on 2018-11-06
version: '8.x-5.0-rc26'
# Information added by Drupal.org packaging script on 2019-01-02
version: '8.x-5.1'
core: '8.x'
project: 'webform'
datestamp: 1541466489
datestamp: 1546458493

View file

@ -1,16 +1,16 @@
webform_image_select.webform_image_select_images.*:
'webform_image_select.webform_image_select_images.*':
type: config_entity
label: 'Images'
label: Images
mapping:
id:
type: string
label: 'Machine name'
label:
type: label
label: 'Label'
label: Label
category:
type: label
label: 'Category'
label: Category
images:
type: text
label: 'Images (YAML)'

View file

@ -0,0 +1,55 @@
<?php
namespace Drupal\webform_image_select\Controller;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Provides route responses for webform images options.
*/
class WebformImageSelectImagesController extends ControllerBase {
/**
* Returns response for the webform options autocompletion.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object containing the search string.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* A JSON response containing the autocomplete suggestions.
*/
public function autocomplete(Request $request) {
$q = $request->query->get('q');
$webform_images_storage = $this->entityTypeManager()->getStorage('webform_image_select_images');
$query = $webform_images_storage->getQuery()
->range(0, 10)
->sort('label');
// Query title and id.
$or = $query->orConditionGroup()
->condition('id', $q, 'CONTAINS')
->condition('label', $q, 'CONTAINS');
$query->condition($or);
$entity_ids = $query->execute();
if (empty($entity_ids)) {
return new JsonResponse([]);
}
$webform_images = $webform_images_storage->loadMultiple($entity_ids);
$matches = [];
foreach ($webform_images as $webform_image) {
$value = new FormattableMarkup('@label (@id)', ['@label' => $webform_image->label(), '@id' => $webform_image->id()]);
$matches[] = ['value' => $value, 'label' => $value];
}
return new JsonResponse($matches);
}
}

View file

@ -70,7 +70,7 @@ class WebformImageSelect extends Select {
}
// Convert #images to #options and make sure images are keyed by value.
if (empty($element['#options']) && !empty($element['#images'])) {
if (empty($element['#options'])) {
$options = [];
foreach ($element['#images'] as $value => &$image) {
if (isset($image['text'])) {

View file

@ -146,9 +146,8 @@ class WebformImageSelectImages extends ConfigEntityBase implements WebformImageS
* {@inheritdoc}
*/
public static function getElementImages(array &$element) {
// If element already has #images return them.
if (is_array($element['#images'])) {
if (isset($element['#images']) && is_array($element['#images'])) {
return $element['#images'];
}

View file

@ -0,0 +1,88 @@
<?php
namespace Drupal\webform_image_select\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Provides the webform image select images filter form.
*/
class WebformImageSelectImagesFilterForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'webform_image_select_images_filter_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $search = NULL, $category = NULL, array $categories = []) {
$form['#attributes'] = ['class' => ['webform-filter-form']];
$form['filter'] = [
'#type' => 'details',
'#title' => $this->t('Filter images'),
'#open' => TRUE,
'#attributes' => ['class' => ['container-inline']],
];
$form['filter']['search'] = [
'#type' => 'search',
'#title' => $this->t('Keyword'),
'#title_display' => 'invisible',
'#autocomplete_route_name' => 'entity.webform_image_select_images.autocomplete',
'#placeholder' => $this->t('Filter by title or images'),
'#size' => 45,
'#default_value' => $search,
];
$form['filter']['category'] = [
'#type' => 'select',
'#title' => $this->t('Category'),
'#title_display' => 'invisible',
'#options' => $categories,
'#empty_option' => ($category) ? $this->t('Show all images') : $this->t('Filter by category'),
'#default_value' => $category,
];
$form['filter']['submit'] = [
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => $this->t('Filter'),
];
if (!empty($search) || !empty($category)) {
$form['filter']['reset'] = [
'#type' => 'submit',
'#submit' => ['::resetForm'],
'#value' => $this->t('Reset'),
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$query = [
'search' => trim($form_state->getValue('search')),
'category' => trim($form_state->getValue('category')),
];
$form_state->setRedirect($this->getRouteMatch()->getRouteName(), $this->getRouteMatch()->getRawParameters()->all(), [
'query' => $query ,
]);
}
/**
* Resets the filter selection.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function resetForm(array &$form, FormStateInterface $form_state) {
$form_state->setRedirect($this->getRouteMatch()->getRouteName(), $this->getRouteMatch()->getRawParameters()->all());
}
}

View file

@ -53,9 +53,7 @@ class WebformImageSelect extends Select {
*/
public function initialize(array &$element) {
// Set element images.
if (isset($element['#images'])) {
$element['#images'] = WebformImageSelectImages::getElementImages($element);
}
$element['#images'] = WebformImageSelectImages::getElementImages($element);
WebformImageSelectElement::setOptions($element);

View file

@ -4,9 +4,14 @@ namespace Drupal\webform_image_select;
use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Url;
use Drupal\webform\Utility\WebformDialogHelper;
use Drupal\webform_image_select\Entity\WebformImageSelectImages;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Defines a class to build a listing of webform image select images entities.
@ -15,12 +20,65 @@ use Drupal\webform_image_select\Entity\WebformImageSelectImages;
*/
class WebformImageSelectImagesListBuilder extends ConfigEntityListBuilder {
/**
* Search keys.
*
* @var string
*/
protected $keys;
/**
* Search category.
*
* @var string
*/
protected $category;
/**
* Constructs a new WebformImageSelectImagesListBuilder object.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition.
* @param \Drupal\Core\Entity\EntityStorageInterface $storage
* The entity storage class.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, RequestStack $request_stack) {
parent::__construct($entity_type, $storage);
$this->request = $request_stack->getCurrentRequest();
$this->keys = $this->request->query->get('search');
$this->category = $this->request->query->get('category');
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('entity.manager')->getStorage($entity_type->id()),
$container->get('request_stack')
);
}
/**
* {@inheritdoc}
*/
public function render() {
// Handler autocomplete redirect.
if ($this->keys && preg_match('#\(([^)]+)\)$#', $this->keys, $match)) {
if ($webform_images = $this->getStorage()->load($match[1])) {
return new RedirectResponse($webform_images->toUrl()->setAbsolute(TRUE)->toString());
}
}
$build = [];
// Filter form.
$build['filter_form'] = $this->buildFilterForm();
// Display info.
$build['info'] = $this->buildInfo();
@ -35,6 +93,17 @@ class WebformImageSelectImagesListBuilder extends ConfigEntityListBuilder {
return $build;
}
/**
* Build the filter form.
*
* @return array
* A render array representing the filter form.
*/
protected function buildFilterForm() {
$categories = $this->getStorage()->getCategories();
return \Drupal::formBuilder()->getForm('\Drupal\webform_image_select\Form\WebformImageSelectImagesFilterForm', $this->keys, $this->category, $categories);
}
/**
* Build information summary.
*
@ -42,7 +111,7 @@ class WebformImageSelectImagesListBuilder extends ConfigEntityListBuilder {
* A render array representing the information summary.
*/
protected function buildInfo() {
$total = $this->getStorage()->getQuery()->count()->execute();
$total = $this->getQuery($this->keys, $this->category)->count()->execute();
if (!$total) {
return [];
}
@ -172,4 +241,46 @@ class WebformImageSelectImagesListBuilder extends ConfigEntityListBuilder {
];
}
/**
* Get the base entity query filtered by search and category.
*
* @param string $keys
* (optional) Search key.
* @param string $category
* (optional) Category.
*
* @return \Drupal\Core\Entity\Query\QueryInterface
* An entity query.
*/
protected function getQuery($keys = '', $category = '') {
$query = $this->getStorage()->getQuery();
// Filter by key(word).
if ($keys) {
$or = $query->orConditionGroup()
->condition('id', $keys, 'CONTAINS')
->condition('title', $keys, 'CONTAINS')
->condition('images', $keys, 'CONTAINS');
$query->condition($or);
}
// Filter by category.
if ($category) {
$query->condition('category', $category);
}
return $query;
}
/**
* {@inheritdoc}
*/
protected function getEntityIds() {
$header = $this->buildHeader();
$query = $this->getQuery($this->keys, $this->category);
$query->tableSort($header);
$query->pager($this->limit);
return $query->execute();
}
}

View file

@ -163,6 +163,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -295,4 +296,8 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers: { }

View file

@ -44,12 +44,12 @@ elements: |
'#open': true
webform_image_select_element_images_entity:
'#type': webform_image_select_element_images
'#title': 'webform_image_select_element_images_entity'
'#title': webform_image_select_element_images_entity
'#required': true
'#default_value': kittens
webform_image_select_element_images_custom:
'#type': webform_image_select_element_images
'#title': 'webform_image_select_element_images_custom'
'#title': webform_image_select_element_images_custom
'#required': true
'#default_value':
kitten_1:
@ -81,6 +81,7 @@ settings:
form_previous_submissions: true
form_confidential: false
form_confidential_message: ''
form_remote_addr: true
form_convert_anonymous: false
form_prepopulate: false
form_prepopulate_source_entity: false
@ -213,6 +214,10 @@ access:
roles: { }
users: { }
permissions: { }
configuration:
roles: { }
users: { }
permissions: { }
handlers:
debug:
id: debug

Some files were not shown because too many files have changed in this diff Show more