diff --git a/Build/Resources/Public/Less/form.less b/Build/Resources/Public/Less/form.less index 92969d29cbd3fdbc1ff27101daa65bd3d6333542..b7d0033a58d874913ef2e453778f228c721d22f9 100644 --- a/Build/Resources/Public/Less/form.less +++ b/Build/Resources/Public/Less/form.less @@ -1,703 +1,948 @@ @charset "UTF-8"; -.std-em-selector { - font-size: 90%; - font-style: normal; +// +// Variables +// +// @toDo remove these variables after including this file in backend.less +// Bootstrap: variables.less +@panel-default-text: @gray-dark; + +// /Build/Resources/Public/Less/cropper/variables.less +@screen-lg: 1200px; // Large screen / wide desktop + +// /Build/Resources/Public/Less/_variables.less +@gray-dark: rgb(90, 90, 90); +@gray: rgb(115, 115, 115); +@brand-primary: #0078e6; +@brand-success: #79a548; +@brand-info: #6daae0; +@brand-warning: #e8a33d; +@brand-danger: #c83c3c; +@table-bg: #fafafa; +@table-bg-hover: darken(@table-bg, 5%); +@panel-default-heading-bg: #ddd; +@text-color: #000; +@btn-default-bg: #eee; +@btn-default-border: #bbb; + +// /Build/Resources/Public/Less/Component/module.less +@module-docheader-height: 65px; +@module-docheader-border: #c3c3c3; + +// /Build/Resources/Public/Less/TYPO3/_module_web_page.less +@page-ce-header-hover-bg: #d0d0d0; + +// /Build/Resources/Public/Less/TYPO3/_element_tree.less +@navigation-bg: #f5f5f5; + +// Form Variables +@stage-max-width: 600px; +@stage-abstract-element-height: 62px; +@stage-abstract-element-toolbar-height: 35px; +@stage-icon-container-width: 40px; +@stage-validation-list-width: 100px; +@stage-breakpoint: (@screen-lg + 100); +@stage-validation-transition-time-in: 0.2s; +@stage-validation-transition-time-out: 0.3s; + +@stage-background-color: #fafafa; +@stage-element-toolbar-background: #d0d0d0; +@collection-element-background: @page-ce-header-hover-bg; + +// +// Mixins +// + +.fade-out-gradient-effect-bottom (@color, @gradient-start-height, @gradient-height) { + &:before, &:after { + display: block; + content: ''; + position: absolute; + bottom: 0; + right: 0; + left: 0; + } + &:before { + height: @gradient-start-height; + background: @color; + } + &:after { + bottom: @gradient-start-height; + height: @gradient-height; + background: linear-gradient(to bottom, rgba(red(@color), green(@color), blue(@color), 0) 0%, @color 100%); + } } -.std-strong-selector { - display: block; - font-size: 90%; - font-weight: normal; - color: #C00; +.selected-button-style-primary () { + .btn { + background-color: #fff; + border-color: #fff; + &:hover, &.active { + background-color: lighten(@brand-info, 30%); + } + } + .icon { + svg path { + fill: @brand-primary; + } + } } -.std-li-selector{ - float: none; - width: auto; - margin-right: 0; - margin-left: 1em; +.collapsed-icon-animation () { + transform: rotate(0deg); + transition: transform 0.2s; } -#fake-form { - - ol { - padding-left: 0 !important; - list-style: none !important; - } - /* style for each form element */ - li { - overflow: hidden; - padding: 0.5em; - margin-bottom: 0.5em; - - &#element-placeholder{ - padding: 0; - margin: 0; - } +.expanded-icon-animation () { + transform: rotate(90deg); + transition: transform 0.2s; +} - input + label, - textarea + label, - select + label { - .std-li-selector; - } +// +// X-Component +// +.t3-form-x-component { + position: absolute; + top: 0; + height: 100%; + line-height: normal; + background: @navigation-bg; - textarea + label { - vertical-align: top; - } + a { + text-decoration: none; } - - textarea, input[type=text]{ - border: 1px solid #c0c0c0; + ol, + ul { + list-style: none; + padding: 0; } - - input[type=text]{ - // equal width like textareas - width:300px; - padding: 3px; + .ui-sortable-placeholder { + outline-offset: -1px !important; } +} - label { - display:block; - margin-right: 1em; - vertical-align: baseline; +.t3-form-x-component-inner-wrapper { + padding: 1.5em; +} - em{ - .std-em-selector; - } +// +// Structure Tree +// +#t3-form-navigation-component { + overflow: hidden; + left: 0; +} - strong{ - .std-strong-selector; - } - } +#t3-form-structure-panel { + overflow: auto; + padding-top: @module-docheader-height; + height: 100%; - .x-checkbox, .x-radio{ - label{ - display:inline-block; - } + .icon { + z-index: 1; } - - legend { - border-bottom:0; - em{ - .std-em-selector; - } - - strong{ - .std-strong-selector; - } + #t3-form-navigation-component-tree-root-container, .tree li > div { + border: 1px solid transparent; + cursor: pointer; } - - fieldset { - position: relative; - margin: 0; - padding: 0; - - &.submit { - border-style: none; - } - - &.fieldset-horizontal { - border-width: 0; - - &.label-below label { - display: block; - margin-left: 0; - margin-top: 0.2em; - font-size: 90%; - text-align: left; - color: #999999; - } - - label{ - em { - display: inline; - } - } - - ol { - padding: 0; + .tree { + .svg-wrapper { + svg { + overflow: visible; + position: relative; + top: -0.8em; + left: 0.6em; } - - li { - float: left; - margin-right: 1em; - padding: 0; + path { + fill: none; + shape-rendering: crispEdges; + stroke: rgb(221, 221, 221); + stroke-width: 1; } } - - &.fieldset-subgroup { - margin-bottom: -2em; - border-style: none; - - ol { - position: relative; - top: -1.4em; - padding: 0; - } - - li { - padding: 0; + li { + white-space: nowrap; + .icon-actions-pagetree-collapse { + margin-right: 0.3em; + img { + .expanded-icon-animation (); + } } - - legend { - margin-left: 0; - padding: 0; + &.mjs-nestedSortable-collapsed { + > ol { + display: none; + } + .icon-actions-pagetree-collapse img { + .collapsed-icon-animation (); + } } - - input + label { - float: none; - width: auto; - display: inline; - margin: 0 0 0 1em; + small { + padding-left: 0.5em; + font-size: 80%; } } - } - - legend { - font-size: 12px; - font-weight: bold; - color: #000000; - - em { - position: absolute; - } - - strong { - position: absolute; - top: 1.4em; + .t3-form-icon { + margin-right: 0.5em; + margin-left: 0.5em; } - } - - /* labels as block, labels displayed above or below the input fields */ - .labels-block{ - label { - display: block; - float: none; - margin: 0 0 0.5em; - width: auto; + .t3-form-element-has-children > div .t3-form-icon { + margin-left: 0.1em; } - - input + label, - textarea + label{ - margin: 0.5em 0 0; + .sortable-hover { + outline: 1px solid darken(@panel-default-heading-bg, 20%); } - + } + .tree li > div:hover, + .t3-form-form-element-selected, + #t3-form-navigation-component-tree-root-container:hover, + .t3-form-root-element-selected { + background-color: darken(@navigation-bg, 1%); + border-color: darken(@navigation-bg, 10%); + border-radius: 2px; + margin-left: -2em; + padding-left: 2em; + margin-right: -1.3em; + } + .tree li > .t3-form-form-element-selected, + .tree li > .t3-form-form-element-selected:hover, + #t3-form-navigation-component-tree-root-container.t3-form-root-element-selected, + #t3-form-navigation-component-tree-root-container.t3-form-root-element-selected:hover { + background-color: #fff; + border-color: darken(@navigation-bg, 10%); + } + .t3-form-x-component-inner-wrapper { + padding-top: 2.5em; } } -/* labels alignment right */ -#fake-form .labels-alignment-right label, -#fake-form .labels-alignment-right .fieldset-subgroup legend, -#fake-form .labels-alignment-right.fieldset-subgroup legend { - text-align: right; -} - -#fake-form .labels-block fieldset.fieldset-subgroup, -#fake-form fieldset.labels-block.fieldset-subgroup { - margin-bottom: 0; -} - -#fake-form .labels-block .fieldset-subgroup legend, -#fake-form .labels-block.fieldset-subgroup legend { - width: auto; -} - -#fake-form .labels-block .fieldset-subgroup legend em, -#fake-form .labels-block.fieldset-subgroup legend em { - position: relative; -} - -#fake-form .labels-block .fieldset-subgroup legend strong, -#fake-form .labels-block.fieldset-subgroup legend strong { - position: relative; - top: 0; -} - -#fake-form .labels-block .fieldset-subgroup ol, -#fake-form .labels-block.fieldset-subgroup ol { - top: 0; - margin: 0; - padding: 0.5em 0 0; -} - -/* element HIDDEN */ -#fake-form .formwizard-element.hidden-element { - cursor: default; -} - -#fake-form .formwizard-element .hidden-dummy-element { - margin: 0; - padding: 5px; - border:1px dotted #A9A9A9; +// +// Inspector +// +.form-group.t3-form-collection-element-remove-button, +.t3-form-inspector-finishers-editor-removeButton, +.form-group.t3-form-inspector-validators-editor-removeButton { + margin: 0 !important; + font-size: 0; } -/* styles for drag and drop content */ -.x-dd-drag-ghost .formwizard-element { - list-style:none; +#t3-form-inspector-panels-container { + overflow: hidden; + right: 0; + padding-top: @module-docheader-height; } -.x-dd-drop-icon { - top: 7px; +#t3-form-inspector-panels { + overflow: auto; + height: 100%; } -.x-dd-drag-ghost ol { - margin: 5px 0; - padding: 0; - list-style: none; -} +#t3-form-inspector { + padding: 1em 0.5em; -.x-dd-drag-ghost .buttongroup, -.x-dd-drag-ghost label em, -.x-dd-drag-ghost label strong { - display: none; + h2, + h3, + h4 { + margin: 0; + padding: 0.1em 0.2em 0.2em 0.5em; + border-top: 1px solid @module-docheader-border; + clear: both; + font: inherit; + font-weight: bold; + } + h2 { + padding-bottom: 1em; + border: none; + border-bottom: 1px solid @module-docheader-border; + } + > h2:first-child { + border-top: none; + } + h3 { + color: @text-color; + padding-top: 0.3em; + border: none; + } + h4 { + padding: 0.8em 3em 0.8em 2.5em; + font-weight: 500; + background-color: @panel-default-heading-bg; + span[data-template-property="label"] { + vertical-align: top; + } + } + .t3-form-remove-element-button { + position: absolute; + top: 90px; + right: 2.5em; + } + .t3-form-control-group, + .t3-form-add-collection-element { + margin: 1.5em 0.5em; + clear: both; + } + .t3-form-inspector-editor-requiredValidator { + label { + cursor: pointer; + } + } } -.x-dd-drag-ghost label { - margin: 0 10px 0 5px; +// +// Inspector Collection +// +.t3-form-add-collection-element { + padding-bottom: 1em; } -.x-dd-drag-ghost legend { - margin: 0 5px; - font-size: 14px; - font-weight: bold; - color: #000; - border: none; -} +.t3-form-collection-container { + margin-top: -1em; + padding: 0.6em; -.x-grid-panel .remove { - background-image: url("../Images/remove.gif"); - width: 15px; - height: 16px; + .ui-sortable-handle { + cursor: auto; + } + h4 { + cursor: move; + } + .icon-actions-view-table-expand { + position: absolute; + left: 0.5em; + } + a.collapsed { + .icon-actions-view-table-expand svg { + .collapsed-icon-animation (); + } + } + a:not(.collapsed) { + .icon-actions-view-table-expand svg { + .expanded-icon-animation (); + } + } } -.x-dd-drag-proxy, -.x-dd-drop-nodrop { - background-color: #fff; - border-color: #c0c0c0; +.t3-form-collection-element { + position: relative; + margin-bottom: 0.5em; + border: 1px solid @module-docheader-border; + border-top: none; + background: @navigation-bg; + + .t3-form-collection-element-remove-button { + position: absolute; + right: 0.5em; + top: 0.6em; + } } -.tab-content{ - fieldset{ - #formwizard{ - display:inherit; +// +// Inspector Property Grid +// +.property-grid { + .form-control { + min-width: initial; + min-width: auto; + font-size: 0.9em; + } + .table { + th { + font-size: 0.9em; } - - &.form-section{ - float: left; - min-width: 380px; - width: 100%; - padding-bottom: 15px; - - &:last-child{ - margin-bottom: 1em; + > tbody > tr { + cursor: pointer; + background-color: @table-bg; + &:last-child { + cursor: auto; } - - ol{ - &#formwizard-right{ - // overwrite inline-style "auto" - width:100vw !important; - overflow: visible !important; - position: relative; - float:none; - left:5px !important; - padding-top:0; - padding-left:0; - margin-right: 10px; - top:30px !important; - display: table-cell; - height:auto !important; - list-style: none; - border-top-style: none; - - &.hover{ - left:0; - width:auto; - } + > td { + padding: 0.6em 0.3em; + text-align: center; + &:first-child { + width: 35px; + } + &:nth-child(2), &:nth-child(3) { + width: 75px; + } + &:nth-child(4) { + width: 65px; + } + &:nth-child(5) { + width: 35px; } } } + .btn { + background-color: @btn-default-bg; + border-color: @btn-default-border; + } } -} - -/* outer wrapper of whole wizard */ -#form-wizard-element { - z-index: 1; - - #formwizard-left{ - display: table-cell; - float:left !important; - margin-right: -1px; - - .x-tab-panel-body{ - // overwrite inline-styles with important ;( - height:100% !important; - overflow:visible !important; + .sort-row-field { + cursor: move; + } + .ui-sortable-helper { + td { + border: none; } } + .ui-sortable-placeholder { + height: 45px; + border-left: 1px solid @module-docheader-border !important; + border-right: 1px solid @module-docheader-border !important; + outline-offset: -5px !important; + } } -/* inner wrapper of whole wizard */ -#formwizard { - background-color: #F8F8F8; -} - -/* applied when a element is moved */ -#formwizard.hover-move { - cursor: move; +// +// Stage +// +#t3-form-stage-inner-container { + display: inline-block; + width: 90%; + text-align: left; + @media (min-width: @stage-breakpoint) { + width: @stage-max-width; + } } -/* left panel */ -#formwizard-left.x-border-panel { +#t3-form-stage-container { + overflow: auto; position: relative; - left: auto; - top: auto; -} - -/* tabs */ -#formwizard-left .x-tab-panel-header { - background-color: transparent; -} - -/* tabs inner */ -#formwizard-left .x-tab-strip { - margin-bottom: 0; -} - -#formwizard-left .x-tab-strip-top .x-tab-left { - padding-right: 20px; -} - -#formwizard-left .x-tab-strip-top .x-tab-right { - padding: 5px 10px 2px; - background-color: #EDEDED; - border-radius: 0; -} - -#formwizard-left .x-tab-strip-top .x-tab-strip-active .x-tab-right, -#formwizard-left .x-tab-strip-top .x-tab-strip-active.x-tab-strip-over .x-tab-right{ - background-color: transparent; - border-bottom-color: #F8F8F8; -} - -#formwizard-left .x-tab-strip-top .x-tab-strip-over .x-tab-right { - background-color: #E1E1E1; -} - -#formwizard-left li.validation-error .x-tab-left, -#formwizard-left div.validation-error .x-accordion-hd { - margin-right: 14px; - background-image: url("../../../../../t3skin/extjs/images/form/exclamation.gif"); - background-position: right 1px; - background-repeat: no-repeat; -} - -/* content below tabs */ -#formwizard-left .x-tab-panel-body-content { - min-height: 330px; - padding: 10px; - background: transparent; - border: 1px solid #C0C0C0; - border-top-width: 0; -} - -/* info messages (also for drag and drop) */ -#formwizard-left .message-information, -#fake-form .message-information, -.x-dd-drag-ghost .message-information { - margin: 10px 0 15px 16px; - padding: 12px 10px; - background-image: none; - border-radius: 0; - box-shadow: none; -} - -#formwizard-left .message-information p, -#fake-form .message-information p, -.x-dd-drag-ghost .message-information { - margin: 0; -} - -/* intro info messages */ -#formwizard-left #formwizard-left-elements-intro, -#formwizard-left #formwizard-left-options-dummy, -#fake-form .message-information { - margin: 0 0 10px; -} - -#formwizard-left .x-tab-panel-body, -#formwizard-left .x-accordion-hd { - background: transparent none; - border-width: 0; -} - -/* accordion */ -#formwizard-left .x-panel-accordion { - border-bottom: 1px solid #C7C7C7; -} - -#formwizard-left .x-panel-accordion:last-child { - border-bottom: medium none; -} - -/* headline of accordion */ -#formwizard-left .x-accordion-hd { - padding-left: 0; -} - -/* toggle icon of accordion */ -#formwizard-left .x-accordion-hd .x-tool-toggle { - margin: 0; - float: left; - background-image: url("../Images/module-menu-down.png"); - background-position: 0 4px; -} - -#formwizard-left .x-panel-collapsed .x-accordion-hd .x-tool-toggle { - background-image: url("../Images/module-menu-right.png"); - background-position: 1px 3px; -} - -#formwizard-left .x-accordion-hd .x-panel-header-text { - font-weight: bold; -} - -#formwizard-left .x-accordion-hd .x-panel-body { - padding-left: 15px; -} - -/* element inside accordion */ -#formwizard-left .x-form { - margin-left: 15px; - margin-top: 10px; -} - -#formwizard-left .x-form fieldset { - padding: 0; - border: none; -} -#formwizard-left .x-form fieldset legend { - padding: 0; - font-size: 12px; - color: #222222; -} - -#formwizard-left .x-panel-tbar { - margin-top: 10px; - padding-left: 15px; - padding-bottom: 0; - border-width: 0; -} - -#formwizard-left .x-panel-tbar .x-toolbar { - padding: 0; -} - -#formwizard-left .x-table-layout { - margin-bottom: 10px; -} - -/* generic element like textfield */ -#formwizard-left .formwizard-element { - margin-left: 12px; - background-color: transparent; - background-image: none; - border-color: transparent; -} - -#formwizard-left .formwizard-element.x-btn-over { - background-color: #D5D5D5; - background-image: -moz-linear-gradient(center top , #F6F6F6 10%, #D5D5D5 90%); - border-color: #C0C0C0; - border-radius: 0; -} - -#formwizard-left .formwizard-element .x-btn-mc { + height: 100%; text-align: left; -} - -/* form elements in left panel */ -.formwizard-left-elements-basic-button { - background-image: url("../Images/ui-button.png"); -} - -.formwizard-left-elements-basic-checkbox { - background-image: url("../Images/ui-check-box.png"); -} - -.formwizard-left-elements-basic-fieldset { - background-image: url("../Images/ui-group-box.png"); -} - -.formwizard-left-elements-basic-fileupload { - background-image: url("../Images/drive-upload.png"); -} - -.formwizard-left-elements-basic-hidden { - background-image: url("../Images/ui-text-field-hidden.png"); -} - -.formwizard-left-elements-basic-password { - background-image: url("../Images/ui-text-field-password.png"); -} - -.formwizard-left-elements-basic-radio { - background-image: url("../Images/ui-radio-button.png"); -} - -.formwizard-left-elements-basic-reset { - background-image: url("../Images/broom.png"); -} - -.formwizard-left-elements-basic-select { - background-image: url("../Images/ui-combo-box.png"); -} - -.formwizard-left-elements-basic-submit { - background-image: url("../Images/ui-button-default.png"); -} - -.formwizard-left-elements-basic-textarea { - background-image: url("../Images/ui-scroll-pane-text.png"); -} - -.formwizard-left-elements-basic-textline { - background-image: url("../Images/ui-text-field.png"); -} - -.formwizard-left-elements-predefined-checkboxgroup { - background-image: url("../Images/ui-check-boxes.png"); -} - -.formwizard-left-elements-predefined-email { - background-image: url("../Images/mail.png"); -} - -.formwizard-left-elements-predefined-name { - background-image: url("../Images/user-silhouette.png"); -} - -.formwizard-left-elements-predefined-radiogroup { - background-image: url("../Images/ui-radio-buttons.png"); -} - -.formwizard-left-elements-content-header { - background-image: url("../Images/edit-heading.png"); -} - -.formwizard-left-elements-content-textblock { - background-image: url("../Images/edit-textblock.png"); -} - -#formwizard-left .x-form-text { - height: 17px; -} - -#formwizard-left .x-btn-text-icon .x-btn-icon-small-left .x-btn-text { - color: black; -} - -#formwizard-left .x-small-editor .x-form-text { - height: 13px !important; -} - -/* icon in element field for applying entered text */ -#formwizard-left .x-form-field-wrap .x-form-submit-trigger { - background-image: url("../Images/submit-trigger.gif"); -} - -/* right panel */ -#formwizard-right { - min-height: 350px; - padding: 30px 0 10px 2px; - overflow: visible; -} - -#fake-form { - padding: 10px; - background-color: tansparent; - border: 1px solid #C0C0C0; -} - -#fake-form li { - overflow: visible; -} - -/* visible area of element on right panel */ -#fake-form div.overflow-hidden { - overflow: hidden; - - input{ - margin-left: 1px; + @media (min-width: @stage-breakpoint) { + text-align: center; } -} -/* wrap around all elements on right panel */ -#fake-form .formwizard-element { - border: 1px solid transparent; - position: relative; -} + ol, + ul { + list-style: none; + } + .form-section { + border: none; + } + .panel-heading { + button { + outline: none; + } + .paginiation-label { + margin-right: 1em; + } + } + .t3-form-new-element-container { + height: @stage-abstract-element-height; + border: 1px dashed @panel-default-heading-bg; + text-align: center; + padding-top: @stage-abstract-element-height/2; + .btn { + transform: translateY(-50%); + } + } -#fake-form .formwizard-element.hover, -#fake-form .formwizard-element.hidden.hover { - background-color: #F9FCFF; - border: 1px solid #C5DBE6; -} + // Abstract + &.t3-form-stage-viewmode-abstract { + ol, + ul { + padding-left: @stage-icon-container-width; + padding-right: 1em; + } + .t3-form-page-title { + margin: 0 0 0.5em; + } + #t3-form-stage-inner-container { + overflow: hidden; + } + .t3-form-element-composit { + &:not(.t3-form-element-toplevel) { + margin-bottom: 1em; + padding-bottom: 1px; + outline: 1px solid #dddddd; + outline-offset: -1px; + } + .sortable-hover { + outline-color: darken(@panel-default-heading-bg, 40%); + } + .t3-form-form-composit-element-selected { + outline-color: @brand-primary; + } + } + .t3-form-element-composit.sortable-hover > .ui-sortable-handle, + .ui-sortable-handle:hover { + border-color: darken(@panel-default-heading-bg, 40%); + .t3-form-icon-container { + background-color: darken(@panel-default-heading-bg, 40%); + path { + fill: #fff; + } + } + } + .ui-sortable { + fieldset { + position: relative; + min-height: 130px; + padding-top: 5em; + legend { + position: absolute; + top: 1em; + display: inline-block; + width: 95%; + } + } + } + .ui-sortable-handle { + overflow: hidden; + position: relative; + height: @stage-abstract-element-height; + margin-bottom: 1em; + border: 1px solid @panel-default-heading-bg; + background-color: #fff; + + &:hover { + .t3-form-validator-list { + right: 0; + transition: right @stage-validation-transition-time-in; + } + .t3-form-element-info .element-content { + span, div { + color: @gray-dark; + } + } + .t3-form-validator-info .t3-form-icon { + margin-right: (@stage-validation-list-width - 25); + transition: margin @stage-validation-transition-time-in; + } + } + &:has (.ui-sortable-handle:hover) { + border-color: transparent; + } + span { + color: @gray-dark; + } + } + .ui-state-disabled { + cursor: auto; + &:hover { + background: none; + } + } + .ui-sortable-placeholder { + margin-bottom: 1em; + } + .t3-form-icon-container { + float: left; + width: @stage-icon-container-width; + height: 100%; + padding: 1em; + cursor: move; + background-color: @panel-default-heading-bg; + .t3-form-icon { + height: 100%; + } + } + .t3-form-form-element-body { + height: 100%; + } + .t3-form-element-info { + position: relative; + float: left; + width: 55%; + height: 100%; + padding-left: 1em; + .fade-out-gradient-effect-bottom (#fff, 0.8em, 1em); + .element-label-container { + float: left; + position: relative; + width: 45%; + height: 100%; + .element-label { + overflow: hidden; + position: absolute; + top: 50%; + width: 100%; + text-overflow: ellipsis; + transform: translateY(-50%); + } + } + .element-content { + padding-top: 1em; + white-space: nowrap; + font-size: 0.8em; + span, div { + color: @panel-default-heading-bg; + } + } + } + .t3-form-validator-info { + position: relative; + overflow: hidden; + float: right; + height: 100%; + .t3-form-icon { + height: 100%; + z-index: 1; + margin-left: 1em; + transition: margin @stage-validation-transition-time-out; + filter: grayscale(100%); + } + .t3-form-validator-list { + .fade-out-gradient-effect-bottom(@panel-default-heading-bg, 1em, 1em); + position: absolute; + top: 0; + right: -@stage-validation-list-width; + width: @stage-validation-list-width; + height: 100%; + padding: 1em 1em 1em (@stage-validation-list-width - 65); + font-size: 0.8em; + transition: right @stage-validation-transition-time-out; + background-color: @panel-default-heading-bg; + } + .validator-label { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: @gray-dark; + } + } + #t3-form-stage .t3-form-form-element-selected { + position: relative; + padding-top: @stage-abstract-element-toolbar-height; + height: @stage-abstract-element-height + @stage-abstract-element-toolbar-height; + border: none; + + .t3-form-form-element-body { + border: 1px solid @brand-primary; + } + .t3-form-icon-container { + background-color: @brand-primary; + } + .t3-form-element-info .element-content { + span, div { + color: @gray-dark; + } + } + .t3-form-validator-list { + @validation-list-background: lighten(@brand-info, 30%); + right: 0; + transition: right @stage-validation-transition-time-in; + background-color: @validation-list-background; + &:before { + background-color: @validation-list-background; + } + &:after { + background: linear-gradient(to bottom, rgba(red(@validation-list-background), green(@validation-list-background), blue(@validation-list-background), 0) 0%, @validation-list-background 100%); + } + } + .t3-form-validator-info .t3-form-icon { + margin-right: (@stage-validation-list-width - 25); + filter: none; + } + .btn-toolbar-container { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: @stage-abstract-element-toolbar-height; + border: 1px solid @brand-primary; + background-color: @brand-primary; + padding-right: 0.7em; + padding-top: 0.4em; + &:before, &:after { + position: absolute; + top: 0; + display: block; + width: 1px; + height: 100%; + content: ' '; + background-color: @brand-primary; + } + &:before { + left: -1px; + } + &:after { + right: -1px; + } + .dropdown-menu { + left: auto; + left: initial; + min-width: initial; + right: 0; + padding-left: 0; + padding-right: 0; + background-color: darken(@brand-primary, 10%); + > li a:hover { + background-color: darken(@brand-primary, 5%); + } + } + .caret { + color: @brand-primary; + } + .t3-form-dropdown-buttons { + .icon { + margin-right: 0.5em; + } + } + .btn-toolbar { + float: right; + .selected-button-style-primary; + } + } + .meta-label { + display: inline-block; + top: 1em; + left: 5em; + bottom: auto; + font-size: 0.9em; + color: #fff; + span { + color: #fff; + } + } + } + .panel.t3-form-form-stage-selected { + border-color: @brand-primary; + > .panel-heading { + background-color: @brand-primary; + border-color: @brand-primary; + color: #fff; + .selected-button-style-primary; + } + } + } -#fake-form .formwizard-element.active, -#fake-form .formwizard-element.hidden.active { - background-color: #EAF7FF; - border: 1px solid #C5DBE6; -} + // Preview + &.t3-form-stage-viewmode-preview { + input[type="text"], input[type="date"], input[type="password"], textarea, select { + color: #000; + background-color: lighten(@panel-default-heading-bg, 3%); + } + ::placeholder { + color: @gray; + font-style: italic; + } + input[type="date"] { + display: block; + width: 100%; + height: 32px; + padding: 0.6em; + font-size: 12px; + line-height: 1.5; + background-image: none; + border: 1px solid @module-docheader-border; + border-radius: 2px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + } + select[multiple="multiple"] { + height: auto; + min-height: 32px; + } + textarea { + min-height: 100px; + } + legend.t3-form-form-element-selected { + border-color: @module-docheader-border; + } + .form-navigation { + .btn-group { + span, button { + display: inline-block; + margin-right: 1em; + } + } + } + .preview-table-first-col { + width: 30%; + } + .t3-form-element-preview { + position: relative; + display: inline-block; + width: 100%; + } + .t3-form-new-element-container { + display: none; + } + .t3-form-element-toplevel > form > .tooltip { + top: 100px !important; + } + } -#fake-form .formwizard-element.hidden { - min-height: 1em; - background-color: transparent; - border: 1px dotted #C5DBE6; + #t3-form-stage { + margin-bottom: 0; + padding-top: 0.5em; + > ol, > ol > li > ol { + padding-left: 0; + padding-right: 0; + } + .t3-form-element-toplevel { + > .t3-form-form-element-selected { + height: auto; + padding-top: 0; + } + > .t3-form-form-element-selected .btn-toolbar-container { + display: none; + } + } + } } -/* toolbar on each element */ -#fake-form .formwizard-element div.buttongroup { +.meta-label { + z-index: 1; position: absolute; - right: 0; - top: -35px; + bottom: 1em; + left: 5.5em; display: none; - z-index: 1; - padding: 4px 3px 12px; - background-image: url("../Images/tooltip.png"); + color: @brand-primary; + line-height: 1.6; + font-size: 0.8em; + .ui-sortable-handle:hover > & { + display: inline-block; + } } -#fake-form .formwizard-element.hover > div.buttongroup, -#fake-form .formwizard-element.active > div.buttongroup { - display: block; +.ui-sortable-placeholder, +.t3-form-element-composit.ui-sortable-placeholder { + background-color: #fff !important; + border: none !important; + outline: 1px dashed lighten(@brand-success, 30%) !important; + outline-offset: -2px !important; + visibility: visible !important; } -#fake-form .formwizard-element div.buttongroup button { - width: 16px; - height: 16px; - background-color: transparent; - border: 0 solid transparent; +// +// Icons +// +.t3-form-icon { + margin-right: 1em; } -#fake-form .formwizard-element div.buttongroup span { - margin: 0 3px; +// +// Validation Errors +// +.t3-form-validation-child-has-error { + color: @brand-danger; } -#fake-form .formwizard-element div.buttongroup span.x-btn-over { - background-color: transparent; - background-image: none; +.t3-form-validation-errors { + #t3-form-navigation-component &, + #t3-form-stage-container & { + position: relative; + color: @brand-danger; + &:before { + z-index: 1; + position: absolute; + display: inline-block; + width: 15px; + height: 15px; + font-family: FontAwesome; + vertical-align: middle; + border-radius: 50%; + font-size: 1em; + line-height: 1.4; + text-align: center; + background: none; + } + } + #t3-form-navigation-component & { + &:hover:before, + &.t3-form-form-element-selected:before { + left: 2.4em; + } + &:before { + margin-top: 0.2em; + color: #fff; + font-size: 10px; + font-weight: 800; + content: "\f12a"; + background-color: @brand-danger; + } + } + &#t3-form-navigation-component-tree-root:before { + left: -2em !important; + margin-top: 0.1em; + } + #t3-form-stage-container &.ui-sortable-handle { + border-color: @brand-danger; + &:before { + left: 4.5em; + margin-top: 1.9em; + content: "\f071"; + } + .element-label { + padding-left: 1.5em; + } + } + #t3-form-inspector-panels .t3-form-collection-element & { + display: inline-block; + color: #fff; + font-size: 0.8em; + font-weight: 700; + background-color: @brand-danger; + margin-top: 0.5em; + padding: 0.1em 0.5em; + border-radius: 2px; + } + #t3-form-inspector-panels &.t3-form-collection-element { + border-color: @brand-danger; + + h4 { + border-color: @brand-danger; + background-color: @brand-danger; + color: #fff; + path { + fill: #fff; + } + } + .t3-form-collection-element-remove-button { + background: #fff; + border-color: transparent; + path { + fill: @brand-danger; + } + } + } } -#fake-form .formwizard-element button.t3-icon-edit-delete { - background-image: url('../../../../core/Resources/Public/Icons/T3Icons/actions/actions-delete.svg'); +// +// Loading Editor Spinner +// +.form-editor-loading-spinner { + width: 150px; + margin: 5em auto 0; + text-align: center; } -#fake-form .formwizard-element button.t3-icon-document-open { - background-image: url('../../../../core/Resources/Public/Icons/T3Icons/actions/actions-open.svg'); +// +// jQuery nestedSortable +// +.ui-sortable-handle { + cursor: pointer; } -@media only screen and (max-width:615px) { - .tab-content fieldset.form-section ol#formwizard-right{ - left:0 !important; +// +// Module +// +.module[data-module-name="web_FormFormbuilder_FormEditor"] { + overflow: hidden; + .module-body, div[data-identifier="moduleWrapper"] { + height: 100%; + } + .module-body { + padding-bottom: 0.5em; + } + .module-docheader-bar-column-left { + button { + &, &:focus, &:active { + outline: 0; + outline-color: initial; + outline-style: initial; + outline-width: 0px; + } + } + .btn-group { + margin-left: 25px; + } } } + +.t3-form-element-new-page-button { + position: absolute; + left: 0.5em; +} \ No newline at end of file diff --git a/composer.json b/composer.json index 784ca9ab3632bbedfa8600ab09125d941c918518..7c587acd4c1b54a8dbd999456ea6fa5870e9c827 100644 --- a/composer.json +++ b/composer.json @@ -40,6 +40,7 @@ "swiftmailer/swiftmailer": "~5.4.3", "symfony/console": "^2.7 || ^3.0", "symfony/finder": "^2.7 || ^3.0", + "symfony/yaml": "^2.7 || ^3.0", "doctrine/instantiator": "~1.0.4", "typo3/class-alias-loader": "^1.0", "typo3/cms-composer-installers": "^1.2.8", diff --git a/composer.lock b/composer.lock index 51dff215a913d6658830f899ec1383c080bf3447..fe9516c43d57fb141dc3a6869ac30638492d252e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "90479fd517e730794243c516ef4ba9ae", - "content-hash": "9ac01b16aca6a55472ecf320b6dacf31", + "hash": "9cc1058ed137d0775741d7c5701e77a1", + "content-hash": "2749660dc0a03d1b473808cf28c9cf10", "packages": [ { "name": "cogpowered/finediff", @@ -1119,6 +1119,55 @@ ], "time": "2016-05-18 14:26:46" }, + { + "name": "symfony/yaml", + "version": "v3.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2016-10-24 18:41:13" + }, { "name": "typo3/class-alias-loader", "version": "1.0.0", @@ -3234,55 +3283,6 @@ "homepage": "https://symfony.com", "time": "2016-06-29 05:41:56" }, - { - "name": "symfony/yaml", - "version": "v3.1.6", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/7ff51b06c6c3d5cc6686df69004a42c69df09e27", - "reference": "7ff51b06c6c3d5cc6686df69004a42c69df09e27", - "shasum": "" - }, - "require": { - "php": ">=5.5.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2016-10-24 18:41:13" - }, { "name": "webmozart/assert", "version": "1.1.0", diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-77910-EXTform-IntroduceNewFormFramework.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-77910-EXTform-IntroduceNewFormFramework.rst new file mode 100644 index 0000000000000000000000000000000000000000..db99783b331ef18ea90391ed43e92eefebc3f9e5 --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-77910-EXTform-IntroduceNewFormFramework.rst @@ -0,0 +1,54 @@ +.. include:: ../../Includes.txt + +========================================================= +Feature: #77910 - EXT:form - introduce new form framework +========================================================= + +See :issue:`77910` + +Description +=========== + +A flexible framework for building forms is integrated. It replaces the legacy 'form wizard' based on ExtJS and the +depending frontend rendering system. + +The new backend 'form editor' relies on vanilla JS and jQuery. Different JS patterns have been applied to ensure +a modern architecture, high flexibility and extensibility. + +A new backend module lists all existing forms and allows the creation of new ones. The 'mailform' content element +is reworked. It lists available forms and enables the backend editor to override certain settings, e.g. 'finisher' +settings (formerly known as 'postProcessors'). + +Till now it was not possible to customize and extend the 'form editor'. To allow the registration of new +finishers, validators and pre-defined form elements a lot of architectural changes were needed. After a long +conceptional phase the team decided to remove the former code base, backport the 'form' package of the Flow +project and improve the given ideas and concepts. The result is a new form extension. A lot of code received +major improvements and tons of additional features have been integrated. + +The list of features is long and impressive. The documentation will explain the ideas, concept and architecture +as well as the functionality in detail. The following list names some of them: + +* YAML as configuration and description language including inheritances and overrides. +* File based configuration. +* All JavaScript components of the form wizard (and the wizard itself) can be replaced or extended. +* Own PHP renderer for form and/ or form elements possible. +* Create entire forms via API. +* Create conditions for form elements and validators programmatically. +* Create 'prototypes' and use them as boilerplate. +* Create new form elements and use them in the wizard. +* Uploads are handled as FAL objects. +* Ships bunch of built-in finishers, like email, redirect, save to database. +* Create own finishers. Override thos in the content element. +* Create and apply own validators. +* Multi language support. +* Multi step support. +* Multiple forms per page. +* Built-in spam protection (honeypot). + + +Impact +====== + +Happy little wizard. + +.. index:: Frontend, PHP-API, JavaScript, ext:form \ No newline at end of file diff --git a/typo3/sysext/form/Classes/ContentObject/FormContentObject.php b/typo3/sysext/form/Classes/ContentObject/FormContentObject.php deleted file mode 100644 index e2176de9c1a7624b24658c5f606772c3f26f38f9..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/ContentObject/FormContentObject.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\ContentObject; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser; -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Frontend\ContentObject\AbstractContentObject; -use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; - -/** - * FORM cObject, a wrapper to allow to use 10 = FORM in TypoScript - * which actually executes the Extbase plugin (marked as non-cached) - */ -class FormContentObject extends AbstractContentObject -{ - /** - * Renders the application defined cObject FORM - * - * The Extbase plugin "Form" is initialized. At this time, the - * controller "Frontend" action "show" does the rest. - * - * @param array $conf TS configuration for this cObject - * @return string HTML output - * @throws \InvalidArgumentException - */ - public function render($conf = []) - { - $mergedTypoScript = null; - // If the FORM configuration is retrieved from the database - // all TypoScript interpretation will be disabled for security. - if ($this->cObj->data['CType'] === 'mailform') { - // If the FORM configuration is retrieved from the database - // and a predefined form is selected then the TypoScript - // interpretation is allowed. - $renderPredefinedForm = false; - $predefinedFormIdentifier = null; - if (!empty($this->cObj->data['tx_form_predefinedform'])) { - $predefinedFormIdentifier = $this->cObj->data['tx_form_predefinedform']; - if (isset($this->getTypoScriptFrontendController()->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.'])) { - $renderPredefinedForm = true; - } else { - throw new \InvalidArgumentException('No FORM configuration for identifier "' . $predefinedFormIdentifier . '" available.', 1466769483); - } - } - - if ($renderPredefinedForm && $predefinedFormIdentifier) { - $mergedTypoScript = $this->getTypoScriptFrontendController()->tmpl->setup['plugin.']['tx_form.']['predefinedForms.'][$predefinedFormIdentifier . '.']; - ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $conf); - } else { - $bodytext = $this->cObj->data['bodytext']; - /** @var $typoScriptParser TypoScriptParser */ - $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class); - $typoScriptParser->parse($bodytext); - $mergedTypoScript = (array)$typoScriptParser->setup; - ArrayUtility::mergeRecursiveWithOverrule($mergedTypoScript, $conf); - // Disables TypoScript interpretation since TypoScript is handled that could contain insecure settings: - $mergedTypoScript[Configuration::DISABLE_CONTENT_ELEMENT_RENDERING] = true; - } - } - - // make sure the extbase plugin is marked as Uncached - $content = $this->prepareNonCacheableUserFunction(is_array($mergedTypoScript) ? $mergedTypoScript : $conf); - - // Only apply stdWrap to TypoScript that was NOT created by the wizard: - if (isset($conf['stdWrap.'])) { - $content = $this->cObj->stdWrap($content, $conf['stdWrap.']); - } - return $content; - } - - /** - * Set up the extbase plugin to be a non-cacheable user function - * - * @param array $typoScript - * @return string the content as placeholder for USER_INT code - */ - protected function prepareNonCacheableUserFunction($typoScript) - { - $configuration = [ - 'userFunc' => 'TYPO3\\CMS\\Extbase\\Core\\Bootstrap->run', - 'pluginName' => 'Form', - 'extensionName' => 'Form', - 'vendorName' => 'TYPO3\\CMS', - 'controller' => 'Frontend', - 'action' => 'show', - 'settings' => ['typoscript' => $typoScript], - 'persistence' => [], - 'view' => [], - ]; - - $this->cObj->setUserObjectType(ContentObjectRenderer::OBJECTTYPE_USER_INT); - $substKey = 'INT_SCRIPT.' . $this->getTypoScriptFrontendController()->uniqueHash(); - $content = '<!--' . $substKey . '-->'; - $this->getTypoScriptFrontendController()->config['INTincScript'][$substKey] = [ - 'conf' => $configuration, - 'cObj' => serialize($this->cObj), - 'type' => 'FUNC' - ]; - $this->cObj->setUserObjectType(false); - return $content; - } - - /** - * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController - */ - protected function getTypoScriptFrontendController() - { - return $GLOBALS['TSFE']; - } -} diff --git a/typo3/sysext/form/Classes/Controller/AbstractBackendController.php b/typo3/sysext/form/Classes/Controller/AbstractBackendController.php new file mode 100644 index 0000000000000000000000000000000000000000..0f028e4982f70080295e4f900dee480996b930ca --- /dev/null +++ b/typo3/sysext/form/Classes/Controller/AbstractBackendController.php @@ -0,0 +1,91 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\PathUtility; +use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; +use TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface; + +/** + * The abstract form backend controller + * + * Scope: backend + */ +abstract class AbstractBackendController extends ActionController +{ + + /** + * @var array + */ + protected $formSettings; + + /** + * @var \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface + */ + protected $formPersistenceManager; + + /** + * @param \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager + * @return void + * @internal + */ + public function injectFormPersistenceManager(\TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager) + { + $this->formPersistenceManager = $formPersistenceManager; + } + + /** + * @internal + */ + public function initializeObject() + { + $this->formSettings = $this->objectManager->get(ConfigurationManagerInterface::class) + ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_YAML_SETTINGS, 'form'); + } + + /** + * Convert arrays with EXT: resource paths to web paths + * + * Input: + * [ + * 100 => 'EXT:form/Resources/Public/Css/form.css' + * ] + * + * Output: + * + * [ + * 0 => 'typo3/sysext/form/Resources/Public/Css/form.css' + * ] + * + * @param array $resourcePaths + * @return array + */ + protected function resolveResourcePaths(array $resourcePaths): array + { + $return = []; + foreach ($resourcePaths as $resourcePath) { + $fullResourcePath = GeneralUtility::getFileAbsFileName($resourcePath); + $resourcePath = PathUtility::getAbsoluteWebPath($fullResourcePath); + if (empty($resourcePath)) { + continue; + } + $return[] = $resourcePath; + } + + return $return; + } +} diff --git a/typo3/sysext/form/Classes/Controller/FormEditorController.php b/typo3/sysext/form/Classes/Controller/FormEditorController.php new file mode 100644 index 0000000000000000000000000000000000000000..756015cd4019a4ef816a1f9ef2db05d95e955cdd --- /dev/null +++ b/typo3/sysext/form/Classes/Controller/FormEditorController.php @@ -0,0 +1,445 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Backend\Template\Components\ButtonBar; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\BackendTemplateView; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Utility\ArrayUtility as CoreArrayUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\View\StandaloneView; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Domain\Exception\RenderingException; +use TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException; +use TYPO3\CMS\Form\Service\TranslationService; +use TYPO3\CMS\Form\Utility\ArrayUtility; +use TYPO3\CMS\Lang\LanguageService; + +/** + * The form editor controller + * + * Scope: backend + */ +class FormEditorController extends AbstractBackendController +{ + + /** + * Default View Container + * + * @var BackendTemplateView + */ + protected $defaultViewObjectName = BackendTemplateView::class; + + /** + * @var array + */ + protected $prototypeConfiguration; + + /** + * Displays the form editor + * + * @param string $formPersistenceIdentifier + * @param string $prototypeName + * @return void + * @throws PersistenceManagerException + * @internal + */ + public function indexAction(string $formPersistenceIdentifier, string $prototypeName = null) + { + $this->registerDocheaderButtons(); + $this->view->getModuleTemplate()->setModuleName($this->request->getPluginName() . '_' . $this->request->getControllerName()); + $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue()); + + if ( + strpos($formPersistenceIdentifier, 'EXT:') === 0 + && !$this->formSettings['persistenceManager']['allowSaveToExtensionPaths'] + ) { + throw new PersistenceManagerException('Edit a extension formDefinition is not allowed.', 1478265661); + } + + $formDefinition = $this->formPersistenceManager->load($formPersistenceIdentifier); + $formDefinition = ArrayUtility::stripTagsFromValuesRecursive($formDefinition); + if (empty($prototypeName)) { + $prototypeName = isset($formDefinition['prototypeName']) ? $formDefinition['prototypeName'] : 'standard'; + } + $formDefinition['prototypeName'] = $prototypeName; + + $configurationService = $this->objectManager->get(ConfigurationService::class); + $this->prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName); + + $formEditorDefinitions = $this->getFormEditorDefinitions(); + + $formEditorAppInitialData = [ + 'formEditorDefinitions' => $formEditorDefinitions, + 'formDefinition' => $formDefinition, + 'formPersistenceIdentifier' => $formPersistenceIdentifier, + 'prototypeName' => $prototypeName, + 'endpoints' => [ + 'formPageRenderer' => $this->controllerContext->getUriBuilder()->uriFor('renderFormPage'), + 'saveForm' => $this->controllerContext->getUriBuilder()->uriFor('saveForm') + ], + 'additionalViewModelModules' => $this->prototypeConfiguration['formEditor']['dynamicRequireJsModules']['additionalViewModelModules'], + 'maximumUndoSteps' => $this->prototypeConfiguration['formEditor']['maximumUndoSteps'], + ]; + + $this->view->assign('formEditorAppInitialData', json_encode($formEditorAppInitialData)); + $this->view->assign('stylesheets', $this->resolveResourcePaths($this->prototypeConfiguration['formEditor']['stylesheets'])); + $this->view->assign('formEditorTemplates', $this->renderFormEditorTemplates( + $this->prototypeConfiguration['formEditor']['formEditorTemplates'], + $formEditorDefinitions + )); + $this->view->assign('dynamicRequireJsModules', $this->prototypeConfiguration['formEditor']['dynamicRequireJsModules']); + + $popupWindowWidth = 700; + $popupWindowHeight = 750; + $popupWindowSize = ($this->getBackendUser()->getTSConfigVal('options.popupWindowSize')) + ? trim($this->getBackendUser()->getTSConfigVal('options.popupWindowSize')) + : null; + if (!empty($popupWindowSize)) { + list($popupWindowWidth, $popupWindowHeight) = GeneralUtility::intExplode('x', $popupWindowSize); + } + + $addInlineSettings = [ + 'FormEditor' => [ + 'typo3WinBrowserUrl' => BackendUtility::getModuleUrl('wizard_element_browser'), + ], + 'Popup' => [ + 'PopupWindow' => [ + 'width' => $popupWindowWidth, + 'height' => $popupWindowHeight + ], + ] + ]; + + CoreArrayUtility::mergeRecursiveWithOverrule( + $addInlineSettings, + $this->prototypeConfiguration['formEditor']['addInlineSettings'] + ); + $this->view->assign('addInlineSettings', $addInlineSettings); + } + + /** + * Save a formDefinition which was build by the form editor. + * + * @param string $formPersistenceIdentifier + * @param array $formDefinition + * @return string + * @internal + */ + public function saveFormAction(string $formPersistenceIdentifier, array $formDefinition): string + { + $formDefinition = ArrayUtility::stripTagsFromValuesRecursive($formDefinition); + $formDefinition = $this->convertJsonArrayToAssociativeArray($formDefinition); + $this->formPersistenceManager->save($formPersistenceIdentifier, $formDefinition); + return ''; + } + + /** + * Render a page from the formDefinition which was build by the form editor. + * Use the frontend rendering and set the form framework to preview mode. + * + * @param array $formDefinition + * @param int $pageIndex + * @param string $prototypeName + * @return string + * @internal + */ + public function renderFormPageAction(array $formDefinition, int $pageIndex, string $prototypeName = null): string + { + $formDefinition = ArrayUtility::stripTagsFromValuesRecursive($formDefinition); + $formDefinition = $this->convertJsonArrayToAssociativeArray($formDefinition); + if (empty($prototypeName)) { + $prototypeName = isset($formDefinition['prototypeName']) ? $formDefinition['prototypeName'] : 'standard'; + } + + $formFactory = $this->objectManager->get(ArrayFormFactory::class); + $formDefinition = $formFactory->build($formDefinition, $prototypeName); + $formDefinition->setRenderingOption('previewMode', true); + $form = $formDefinition->bind($this->request, $this->response); + $form->overrideCurrentPage($pageIndex); + return $form->render(); + } + + /** + * Prepare the formElements.*.formEditor section from the yaml settings. + * Sort all formElements into groups and add additional data. + * + * @param array $formElementsDefinition + * @return array + */ + protected function getInsertRenderablesPanelConfiguration(array $formElementsDefinition): array + { + $formElementGroups = isset($this->prototypeConfiguration['formEditor']['formElementGroups']) ? $this->prototypeConfiguration['formEditor']['formElementGroups'] : []; + $formElementsByGroup = []; + + foreach ($formElementsDefinition as $formElementName => $formElementConfiguration) { + if (!isset($formElementConfiguration['group'])) { + continue; + } + if (!isset($formElementsByGroup[$formElementConfiguration['group']])) { + $formElementsByGroup[$formElementConfiguration['group']] = []; + } + + $formElementsByGroup[$formElementConfiguration['group']][] = [ + 'key' => $formElementName, + 'cssKey' => preg_replace('/[^a-z0-9]/', '-', strtolower($formElementName)), + 'label' => TranslationService::getInstance()->translate( + $formElementConfiguration['label'], + null, + $this->prototypeConfiguration['formEditor']['translationFile'], + null, + $formElementConfiguration['label'] + ), + 'sorting' => $formElementConfiguration['groupSorting'], + 'iconIdentifier' => $formElementConfiguration['iconIdentifier'], + ]; + } + + $formGroups = []; + foreach ($formElementGroups as $groupName => $groupConfiguration) { + if (!isset($formElementsByGroup[$groupName])) { + continue; + } + + usort($formElementsByGroup[$groupName], function ($a, $b) { + return $a['sorting'] - $b['sorting']; + }); + unset($formElementsByGroup[$groupName]['sorting']); + + $formGroups[] = [ + 'key' => $groupName, + 'elements' => $formElementsByGroup[$groupName], + 'label' => TranslationService::getInstance()->translate( + $groupConfiguration['label'], + null, + $this->prototypeConfiguration['formEditor']['translationFile'], + null, + $groupConfiguration['label'] + ), + ]; + } + + return $formGroups; + } + + /** + * Reduce the Yaml settings by the 'formEditor' keyword. + * + * @return array + */ + protected function getFormEditorDefinitions(): array + { + $formEditorDefinitions = []; + foreach ([$this->prototypeConfiguration, $this->prototypeConfiguration['formEditor']] as $configuration) { + foreach ($configuration as $firstLevelItemKey => $firstLevelItemValue) { + if (substr($firstLevelItemKey, -10) !== 'Definition') { + continue; + } + $reducedKey = substr($firstLevelItemKey, 0, -10); + foreach ($configuration[$firstLevelItemKey] as $formEditorDefinitionKey => $formEditorDefinitionValue) { + if (isset($formEditorDefinitionValue['formEditor'])) { + $formEditorDefinitionValue = array_intersect_key($formEditorDefinitionValue, array_flip(['formEditor'])); + $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue['formEditor']; + } else { + $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue; + } + } + } + } + $formEditorDefinitions = ArrayUtility::reIndexNumericArrayKeysRecursive($formEditorDefinitions); + $formEditorDefinitions = TranslationService::getInstance()->translateValuesRecursive( + $formEditorDefinitions, + $this->prototypeConfiguration['formEditor']['translationFile'] + ); + return $formEditorDefinitions; + } + + /** + * Registers the Icons into the docheader + * + * @throws \InvalidArgumentException + */ + protected function registerDocheaderButtons() + { + /** @var ButtonBar $buttonBar */ + $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); + $getVars = $this->request->getArguments(); + + if (isset($getVars['action']) && $getVars['action'] === 'index') { + $newPageButton = $buttonBar->makeInputButton() + ->setDataAttributes(['action' => 'formeditor-new-page', 'identifier' => 'headerNewPage']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.new_page_button')) + ->setName('formeditor-new-page') + ->setValue('new-page') + ->setClasses('t3-form-element-new-page-button hidden') + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-page-new', Icon::SIZE_SMALL)); + + $closeButton = $buttonBar->makeLinkButton() + ->setDataAttributes(['identifier' => 'closeButton']) + ->setHref(BackendUtility::getModuleUrl('web_FormFormbuilder')) + ->setClasses('t3-form-element-close-form-button hidden') + ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc')) + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL)); + + $saveButton = $buttonBar->makeInputButton() + ->setDataAttributes(['identifier' => 'saveButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.save_button')) + ->setName('formeditor-save-form') + ->setValue('save') + ->setClasses('t3-form-element-save-form-button hidden') + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL)) + ->setShowLabelText(true); + + $undoButton = $buttonBar->makeInputButton() + ->setDataAttributes(['identifier' => 'undoButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.undo_button')) + ->setName('formeditor-undo-form') + ->setValue('undo') + ->setClasses('t3-form-element-undo-form-button hidden disabled') + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-back', Icon::SIZE_SMALL)); + + $redoButton = $buttonBar->makeInputButton() + ->setDataAttributes(['identifier' => 'redoButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.redo_button')) + ->setName('formeditor-redo-form') + ->setValue('redo') + ->setClasses('t3-form-element-redo-form-button hidden disabled') + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-forward', Icon::SIZE_SMALL)); + + $buttonBar->addButton($newPageButton, ButtonBar::BUTTON_POSITION_LEFT, 1); + $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 2); + $buttonBar->addButton($saveButton, ButtonBar::BUTTON_POSITION_LEFT, 3); + $buttonBar->addButton($undoButton, ButtonBar::BUTTON_POSITION_LEFT, 4); + $buttonBar->addButton($redoButton, ButtonBar::BUTTON_POSITION_LEFT, 4); + } + } + + /** + * Some data which is build by the form editor needs a transformation before + * it can be used by the framework. + * Multivalue elements like select elements produce data like: + * + * [ + * _label => 'label' + * _value => 'value' + * ] + * + * This method transform this into: + * + * [ + * 'value' => 'label' + * ] + * + * @param array $input + * @return array + */ + protected function convertJsonArrayToAssociativeArray(array $input): array + { + $output = []; + foreach ($input as $key => $value) { + if (is_integer($key) && is_array($value) && isset($value['_label']) && isset($value['_value'])) { + $key = $value['_value']; + $value = $value['_label']; + } + if (is_array($value)) { + $output[$key] = $this->convertJsonArrayToAssociativeArray($value); + } else { + $output[$key] = $value; + } + } + return $output; + } + + /** + * Render the "text/x-formeditor-template" templates. + * + * @param array $formEditorTemplates + * @param array $formEditorDefinitions + * @return array + */ + protected function renderFormEditorTemplates(array $formEditorTemplates, array $formEditorDefinitions): array + { + if ( + !isset($formEditorTemplates['templateRootPaths']) + || !is_array($formEditorTemplates['templateRootPaths']) + ) { + throw new RenderingException( + 'The option templateRootPaths must be set.', + 1480294720 + ); + } + if ( + !isset($formEditorTemplates['layoutRootPaths']) + || !is_array($formEditorTemplates['layoutRootPaths']) + ) { + throw new RenderingException( + 'The option layoutRootPaths must be set.', + 1480294721 + ); + } + if ( + !isset($formEditorTemplates['partialRootPaths']) + || !is_array($formEditorTemplates['partialRootPaths']) + ) { + throw new RenderingException( + 'The option partialRootPaths must be set.', + 1480294722 + ); + } + + $standaloneView = $this->objectManager->get(StandaloneView::class); + $standaloneView->setTemplateRootPaths($formEditorTemplates['templateRootPaths']); + $standaloneView->setLayoutRootPaths($formEditorTemplates['layoutRootPaths']); + $standaloneView->setPartialRootPaths($formEditorTemplates['partialRootPaths']); + $standaloneView->assignMultiple([ + 'insertRenderablesPanelConfiguration' => $this->getInsertRenderablesPanelConfiguration($formEditorDefinitions['formElements']) + ]); + + unset($formEditorTemplates['templateRootPaths']); + unset($formEditorTemplates['layoutRootPaths']); + unset($formEditorTemplates['partialRootPaths']); + + $renderedFormEditorTemplates = []; + foreach ($formEditorTemplates as $formEditorTemplateName => $formEditorTemplateTemplate) { + $renderedFormEditorTemplates[$formEditorTemplateName] = $standaloneView->render($formEditorTemplateTemplate); + } + + return $renderedFormEditorTemplates; + } + + /** + * Returns the current BE user. + * + * @return BackendUserAuthentication + */ + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * Returns the language service + * + * @return LanguageService + */ + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/typo3/sysext/form/Classes/Controller/FormFrontendController.php b/typo3/sysext/form/Classes/Controller/FormFrontendController.php new file mode 100644 index 0000000000000000000000000000000000000000..41585604ce379999d65597265bb9e65d97fbca29 --- /dev/null +++ b/typo3/sysext/form/Classes/Controller/FormFrontendController.php @@ -0,0 +1,138 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Mvc\Configuration\TypoScriptService; + +/** + * The frontend controller + * + * Scope: frontend + */ +class FormFrontendController extends ActionController +{ + + /** + * @var \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface + */ + protected $formPersistenceManager; + + /** + * @param \TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager + * @return void + * @internal + */ + public function injectFormPersistenceManager(\TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface $formPersistenceManager) + { + $this->formPersistenceManager = $formPersistenceManager; + } + + /** + * Take the form which should be rendered from the plugin settings + * and overlay the formDefinition with additional data from + * flexform and typoscript settings. + * This method is used directly to display the first page from the + * formDefinition because its cached. + * + * @return void + * @internal + */ + public function renderAction() + { + $formDefinition = []; + if (!empty($this->settings['persistenceIdentifier'])) { + $formDefinition = $this->formPersistenceManager->load($this->settings['persistenceIdentifier']); + $formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier']; + $formDefinition = $this->overrideByFlexFormSettings($formDefinition); + $formDefinition = $this->overrideByTypoScriptSettings($formDefinition); + } + $this->view->assign('formConfiguration', $formDefinition); + } + + /** + * This method is used to display all pages / finishers except the + * first page because its non cached. + * + * @return void + * @internal + */ + public function performAction() + { + $this->forward('render'); + } + + /** + * Override the formDefinition with additional data from the Flexform + * settings. For now, only finisher settings are overridable. + * + * @param array $formDefinition + * @return array + */ + protected function overrideByFlexFormSettings(array $formDefinition): array + { + if (isset($formDefinition['finishers'])) { + foreach ($formDefinition['finishers'] as &$finisherValue) { + $finisherIdentifier = $finisherValue['identifier']; + if ($this->settings['overrideFinishers'] && isset($this->settings['finishers'][$finisherIdentifier])) { + $prototypeName = isset($formDefinition['prototypeName']) ? $formDefinition['prototypeName'] : 'standard'; + $configurationService = $this->objectManager->get(ConfigurationService::class); + $prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName); + + foreach ($finisherValue['options'] as $optionKey => $optionValue) { + // If a previous overriden finisher property is excluded at some time + // it is still present in the flexform database row. + // To avoid a override from the time the property is excluded, this check is needed + if (!isset($prototypeConfiguration['finishersDefinition'][$finisherIdentifier]['FormEngine']['elements'][$optionKey])) { + continue; + } + if (isset($this->settings['finishers'][$finisherIdentifier][$optionKey])) { + $finisherValue['options'][$optionKey] = $this->settings['finishers'][$finisherIdentifier][$optionKey]; + } + } + } + } + } + return $formDefinition; + } + + /** + * Every formDefinition setting are overridable by typoscript. + * If the typoscript configuration path + * plugin.tx_form.settings.formDefinitionOverrides.<identifier> + * exists, this settings are merged into the formDefinition. + * + * @param array $formDefinition + * @return array + */ + protected function overrideByTypoScriptSettings(array $formDefinition): array + { + if ( + isset($this->settings['formDefinitionOverrides'][$formDefinition['identifier']]) + && !empty($this->settings['formDefinitionOverrides'][$formDefinition['identifier']]) + ) { + ArrayUtility::mergeRecursiveWithOverrule( + $formDefinition, + $this->settings['formDefinitionOverrides'][$formDefinition['identifier']] + ); + $formDefinition = $this->objectManager->get(TypoScriptService::class) + ->resolvePossibleTypoScriptConfiguration($formDefinition); + } + return $formDefinition; + } +} diff --git a/typo3/sysext/form/Classes/Controller/FormManagerController.php b/typo3/sysext/form/Classes/Controller/FormManagerController.php new file mode 100644 index 0000000000000000000000000000000000000000..a45ada81cc5681f54f2965a8f8b975ea6f42fde2 --- /dev/null +++ b/typo3/sysext/form/Classes/Controller/FormManagerController.php @@ -0,0 +1,463 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Symfony\Component\Yaml\Yaml; +use TYPO3\CMS\Backend\Template\Components\ButtonBar; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\BackendTemplateView; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Messaging\AbstractMessage; +use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\View\JsonView; +use TYPO3\CMS\Form\Exception as FormException; +use TYPO3\CMS\Form\Service\TranslationService; +use TYPO3\CMS\Form\Utility\ArrayUtility; +use TYPO3\CMS\Lang\LanguageService; + +/** + * The form manager controller + * + * Scope: backend + */ +class FormManagerController extends AbstractBackendController +{ + + /** + * Default View Container + * + * @var BackendTemplateView + */ + protected $defaultViewObjectName = BackendTemplateView::class; + + /** + * Initialize the references action. + * This action use the Fluid JsonView::class as view. + * + * @return void + * @internal + */ + public function initializeReferencesAction() + { + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Displays the Form Manager + * + * @return void + * @internal + */ + public function indexAction() + { + $this->registerDocheaderButtons(); + $this->view->getModuleTemplate()->setModuleName($this->request->getPluginName() . '_' . $this->request->getControllerName()); + $this->view->getModuleTemplate()->setFlashMessageQueue($this->controllerContext->getFlashMessageQueue()); + + $this->view->assign('forms', $this->getAvailableFormDefinitions()); + $this->view->assign('stylesheets', $this->resolveResourcePaths($this->formSettings['formManager']['stylesheets'])); + $this->view->assign('dynamicRequireJsModules', $this->formSettings['formManager']['dynamicRequireJsModules']); + $this->view->assign('formManagerAppInitialData', $this->getFormManagerAppInitialData()); + if (!empty($this->formSettings['formManager']['javaScriptTranslationFile'])) { + $this->getPageRenderer()->addInlineLanguageLabelFile($this->formSettings['formManager']['javaScriptTranslationFile']); + } + } + + /** + * Creates a new Form and redirects to the Form Editor + * + * @param string $formName + * @param string $templatePath + * @param string $prototypeName + * @param string $savePath + * @return string + * @throws FormException + * @internal + */ + public function createAction(string $formName, string $templatePath, string $prototypeName, string $savePath): string + { + if (!$this->isValidTemplatePath($prototypeName, $templatePath)) { + throw new FormException(sprintf('The template path "%s" is not allowed', $templatePath), 1329233410); + } + if (empty($formName)) { + throw new FormException(sprintf('No form name', $templatePath), 1472312204); + } + + $templatePath = GeneralUtility::getFileAbsFileName($templatePath); + $form = Yaml::parse(file_get_contents($templatePath)); + $form['label'] = $formName; + $form['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName)); + $form['prototypeName'] = $prototypeName; + + $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($form['identifier'], $savePath); + $this->formPersistenceManager->save($formPersistenceIdentifier, $form); + + return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor'); + } + + /** + * Duplicates a given formDefinition and redirects to the Form Editor + * + * @param string $formName + * @param string $formPersistenceIdentifier persistence identifier of the form to duplicate + * @param string $savePath + * @return string + * @internal + */ + public function duplicateAction(string $formName, string $formPersistenceIdentifier, string $savePath): string + { + $formToDuplicate = $this->formPersistenceManager->load($formPersistenceIdentifier); + $formToDuplicate['label'] = $formName; + $formToDuplicate['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName)); + + $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($formToDuplicate['identifier'], $savePath); + $this->formPersistenceManager->save($formPersistenceIdentifier, $formToDuplicate); + + return $this->controllerContext->getUriBuilder()->uriFor('index', ['formPersistenceIdentifier' => $formPersistenceIdentifier], 'FormEditor'); + } + + /** + * Show references to this persistence identifier + * + * @param string $formPersistenceIdentifier persistence identifier of the form to duplicate + * @return void + * @internal + */ + public function referencesAction(string $formPersistenceIdentifier) + { + $this->view->assign('references', $this->getProcessedReferencesRows($formPersistenceIdentifier)); + $this->view->assign('formPersistenceIdentifier', $formPersistenceIdentifier); + // referencesAction uses the extbase JsonView::class. + // That's why we have to set the view variables in this way. + $this->view->setVariablesToRender([ + 'references', + 'formPersistenceIdentifier' + ]); + } + + /** + * Delete a formDefinition identified by the $formPersistenceIdentifier. + * Only formDefinitions within storage folders are deletable. + * + * @param string $formPersistenceIdentifier persistence identifier to delete + * @return void + * @internal + */ + public function deleteAction(string $formPersistenceIdentifier) + { + if ( + empty($this->getReferences($formPersistenceIdentifier)) + && strpos($formPersistenceIdentifier, 'EXT:') === false + ) { + $this->formPersistenceManager->delete($formPersistenceIdentifier); + } else { + $this->addFlashMessage( + TranslationService::getInstance()->translate( + $this->formSettings['formManager']['controller']['deleteAction']['errorMessage'], + [$formPersistenceIdentifier], + $this->formSettings['formManager']['translationFile'], + null, + $this->formSettings['formManager']['controller']['deleteAction']['errorMessage'] + ), + TranslationService::getInstance()->translate( + $this->formSettings['formManager']['controller']['deleteAction']['errorTitle'], + null, + $this->formSettings['formManager']['translationFile'], + null, + $this->formSettings['formManager']['controller']['deleteAction']['errorTitle'] + ), + AbstractMessage::ERROR, + true + ); + } + $this->redirect('index'); + } + + /** + * Return a list of all accessible file mountpoints. + * + * Only registered mountpoints from + * TYPO3.CMS.Form.persistenceManager.allowedFileMounts + * are listet. This is list will be reduced by the configured + * mountpoints for the current backend user. + * + * @return array + */ + protected function getAccessibleFormStorageFolders(): array + { + $preparedAccessibleFormStorageFolders = []; + foreach ($this->formPersistenceManager->getAccessibleFormStorageFolders() as $identifier => $folder) { + $preparedAccessibleFormStorageFolders[] = [ + 'label' => $folder->getName(), + 'value' => $identifier + ]; + } + return $preparedAccessibleFormStorageFolders; + } + + /** + * Returns the json encoded data which is used by the form editor + * JavaScript app. + * + * @return string + */ + protected function getFormManagerAppInitialData(): string + { + $formManagerAppInitialData = [ + 'selectablePrototypesConfiguration' => $this->formSettings['formManager']['selectablePrototypesConfiguration'], + 'accessibleFormStorageFolders' => $this->getAccessibleFormStorageFolders(), + 'endpoints' => [ + 'create' => $this->controllerContext->getUriBuilder()->uriFor('create'), + 'duplicate' => $this->controllerContext->getUriBuilder()->uriFor('duplicate'), + 'delete' => $this->controllerContext->getUriBuilder()->uriFor('delete'), + 'references' => $this->controllerContext->getUriBuilder()->uriFor('references') + ], + ]; + + $formManagerAppInitialData = ArrayUtility::reIndexNumericArrayKeysRecursive($formManagerAppInitialData); + $formManagerAppInitialData = TranslationService::getInstance()->translateValuesRecursive( + $formManagerAppInitialData, + $this->formSettings['formManager']['translationFile'] + ); + return json_encode($formManagerAppInitialData); + } + + /** + * List all formDefinitions which can be loaded through t form persistence + * manager. Enrich this data by a reference counter. + * @return array + */ + protected function getAvailableFormDefinitions(): array + { + $availableFormDefinitions = []; + foreach ($this->formPersistenceManager->listForms() as $formDefinition) { + $referenceCount = count($this->getReferences($formDefinition['persistenceIdentifier'])); + $formDefinition['referenceCount'] = $referenceCount; + $availableFormDefinitions[] = $formDefinition; + } + return $availableFormDefinitions; + } + + /** + * Returns an array with informations about the references for a + * formDefinition identified by $persistenceIdentifier. + * + * @param string $persistenceIdentifier + * @return array + * @throws \InvalidArgumentException + */ + protected function getProcessedReferencesRows(string $persistenceIdentifier): array + { + if (empty($persistenceIdentifier)) { + throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1477071939); + } + + $references = []; + $iconFactory = GeneralUtility::makeInstance(IconFactory::class); + + $referenceRows = $this->getReferences($persistenceIdentifier); + foreach ($referenceRows as &$referenceRow) { + $record = $this->getBackendUtility()::getRecord($referenceRow['tablename'], $referenceRow['recuid']); + if (!$record) { + continue; + } + $pageRecord = $this->getBackendUtility()::getRecord('pages', $record['pid']); + $urlParameters = [ + 'edit' => [ + $referenceRow['tablename'] => [ + $referenceRow['recuid'] => 'edit' + ] + ], + 'returnUrl' => $this->getBackendUtility()::getModuleUrl('web_FormFormbuilder') + ]; + + $references[] = [ + 'recordPageTitle' => is_array($pageRecord) ? $this->getBackendUtility()::getRecordTitle('pages', $pageRecord) : '', + 'recordTitle' => $this->getBackendUtility()::getRecordTitle($referenceRow['tablename'], $record, true), + 'recordIcon' => $iconFactory->getIconForRecord($referenceRow['tablename'], $record, Icon::SIZE_SMALL)->render(), + 'recordUid' => $referenceRow['recuid'], + 'recordEditUrl' => $this->getBackendUtility()::getModuleUrl('record_edit', $urlParameters), + ]; + } + return $references; + } + + /** + * Returns an array with all sys_refindex database rows which be + * connected to a formDefinition identified by $persistenceIdentifier + * + * @param string $persistenceIdentifier + * @return array + * @throws \InvalidArgumentException + */ + protected function getReferences(string $persistenceIdentifier): array + { + if (empty($persistenceIdentifier)) { + throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1472238493); + } + + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex'); + $referenceRows = $queryBuilder + ->select('*') + ->from('sys_refindex') + ->where( + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier', \PDO::PARAM_STR)), + $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier, \PDO::PARAM_STR)), + $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter('tt_content', \PDO::PARAM_STR)) + ) + ->execute() + ->fetchAll(); + return $referenceRows; + } + + /** + * Check if a given $templatePath for a given $prototypeName is valid + * and accessible. + * + * Valid template paths has to be configured within + * TYPO3.CMS.Form.formManager.selectablePrototypesConfiguration.[('identifier': $prototypeName)].newFormTemplates.[('templatePath': $templatePath)] + * + * @param string $prototypeName + * @param string $templatePath + * @return bool + */ + protected function isValidTemplatePath(string $prototypeName, string $templatePath): bool + { + $isValid = false; + foreach ($this->formSettings['formManager']['selectablePrototypesConfiguration'] as $prototypesConfiguration) { + if ($prototypesConfiguration['identifier'] !== $prototypeName) { + continue; + } + foreach ($prototypesConfiguration['newFormTemplates'] as $templatesConfiguration) { + if ($templatesConfiguration['templatePath'] !== $templatePath) { + continue; + } + $isValid = true; + break; + } + } + + $templatePath = GeneralUtility::getFileAbsFileName($templatePath); + if (!is_file($templatePath)) { + $isValid = false; + } + + return $isValid; + } + + /** + * Registers the Icons into the docheader + * + * @throws \InvalidArgumentException + */ + protected function registerDocheaderButtons() + { + /** @var ButtonBar $buttonBar */ + $buttonBar = $this->view->getModuleTemplate()->getDocHeaderComponent()->getButtonBar(); + $currentRequest = $this->request; + $moduleName = $currentRequest->getPluginName(); + $getVars = $this->request->getArguments(); + + $mayMakeShortcut = $this->getBackendUser()->mayMakeShortcut(); + if ($mayMakeShortcut) { + $extensionName = $currentRequest->getControllerExtensionName(); + if (count($getVars) === 0) { + $modulePrefix = strtolower('tx_' . $extensionName . '_' . $moduleName); + $getVars = ['id', 'M', $modulePrefix]; + } + + $shortcutButton = $buttonBar->makeShortcutButton() + ->setModuleName($moduleName) + ->setDisplayName($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:module.shortcut_name')) + ->setGetVariables($getVars); + $buttonBar->addButton($shortcutButton); + } + + if (isset($getVars['action']) && $getVars['action'] !== 'index') { + $backButton = $buttonBar->makeLinkButton() + ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:back')) + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-view-go-up', Icon::SIZE_SMALL)) + ->setHref($this->getBackendUtility()::getModuleUrl($moduleName)); + $buttonBar->addButton($backButton); + } else { + $addFormButton = $buttonBar->makeLinkButton() + ->setDataAttributes(['identifier' => 'newForm']) + ->setHref('#') + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.create_new_form')) + ->setIcon($this->view->getModuleTemplate()->getIconFactory()->getIcon('actions-document-new', Icon::SIZE_SMALL)); + $buttonBar->addButton($addFormButton, ButtonBar::BUTTON_POSITION_LEFT); + } + } + + /** + * Returns a form identifier which is the lower cased form name. + * + * @param string $formName + * @return string + */ + protected function convertFormNameToIdentifier(string $formName): string + { + $formIdentifier = preg_replace('/[^a-zA-Z0-9-_]/', '', $formName); + $formIdentifier = lcfirst($formIdentifier); + return $formIdentifier; + } + + /** + * Returns the BackendUtility + * This wrapper is needed for unit tests. + * + * @return string + */ + protected function getBackendUtility(): string + { + return BackendUtility::class; + } + + /** + * Returns the current BE user. + * + * @return BackendUserAuthentication + */ + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * Returns the Language Service + * + * @return LanguageService + */ + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } + + /** + * Returns the page renderer + * + * @return PageRenderer + */ + protected function getPageRenderer(): PageRenderer + { + return GeneralUtility::makeInstance(PageRenderer::class); + } +} diff --git a/typo3/sysext/form/Classes/Controller/FrontendController.php b/typo3/sysext/form/Classes/Controller/FrontendController.php deleted file mode 100644 index 43fd2035ea930d435b31fc56fa715d7e7b6e6655..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Controller/FrontendController.php +++ /dev/null @@ -1,342 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Controller; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; -use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -use TYPO3\CMS\Form\Domain\Builder\FormBuilder; -use TYPO3\CMS\Form\Domain\Builder\ValidationBuilder; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Form\Domain\Model\ValidationElement; -use TYPO3\CMS\Form\Mvc\Controller\ControllerContext; -use TYPO3\CMS\Form\Utility\FormUtility; - -/** - * The form wizard controller - */ -class FrontendController extends ActionController -{ - /** - * @var FormBuilder - */ - protected $formBuilder; - - /** - * @var ValidationBuilder - */ - protected $validationBuilder; - - /** - * @var \TYPO3\CMS\Form\Utility\SessionUtility - */ - protected $sessionUtility; - - /** - * @var FormUtility - */ - protected $formUtility; - - /** - * The TypoScript array - * - * @var array - */ - protected $typoscript = []; - - /** - * TRUE if the validation of the form should be skipped - * - * @var bool - */ - protected $skipValidation = false; - - /** - * @var ControllerContext - */ - protected $controllerContext; - - /** - * @var Configuration - */ - protected $configuration; - - /** - * @param \TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility - * @return void - */ - public function injectSessionUtility(\TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility) - { - $this->sessionUtility = $sessionUtility; - } - - /** - * initialize action - * - * @return void - */ - protected function initializeAction() - { - $this->configuration = Configuration::create()->setTypoScript($this->settings['typoscript']); - $this->formUtility = FormUtility::create($this->configuration); - $this->validationBuilder = ValidationBuilder::create($this->configuration); - $this->validationBuilder->setFormUtility($this->formUtility); - $this->formBuilder = FormBuilder::create($this->configuration); - $this->formBuilder->setValidationBuilder($this->validationBuilder); - $this->formBuilder->setFormUtility($this->formUtility); - $this->typoscript = $this->settings['typoscript']; - - // uploaded file storage - $this->sessionUtility->initSession($this->configuration->getPrefix()); - // move the incoming "formPrefix" data to the $model argument - // now we can validate the $model argument - if ($this->request->hasArgument($this->configuration->getPrefix())) { - $this->skipValidation = false; - $argument = $this->request->getArgument($this->configuration->getPrefix()); - $this->request->setArgument('model', $argument); - } else { - // If there are more forms at a page we have to skip - // the validation of not submitted forms - $this->skipValidation = true; - $this->request->setArgument('model', []); - } - } - - /** - * initialize show action - * - * @return void - */ - protected function initializeShowAction() - { - $validationResults = $this->request->getOriginalRequestMappingResults()->forProperty('model'); - $this->validationBuilder->buildRules(); - if ($validationResults->hasErrors()) { - $this->formBuilder->setValidationErrors($validationResults); - } - } - - /** - * initialize the confirmation action - * - * @return void - */ - protected function initializeConfirmationAction() - { - $this->prepareValidations(); - } - - /** - * initialize the process action - * - * @return void - */ - protected function initializeProcessAction() - { - $this->prepareValidations(); - } - - /** - * Builds the controller context by extending - * the Extbase context with custom additions. - * - * @return ControllerContext - */ - protected function buildControllerContext() - { - $controllerContext = ControllerContext::extend(parent::buildControllerContext()) - ->setConfiguration($this->configuration); - $this->formBuilder->setControllerContext($controllerContext); - return $controllerContext; - } - - /** - * Handles show action, presenting the actual form. - * - * @param \TYPO3\CMS\Form\Domain\Model\ValidationElement $incomingData - * @ignorevalidation $incomingData - * @return void - */ - public function showAction(ValidationElement $incomingData = null) - { - if ($incomingData !== null) { - $this->controllerContext->setValidationElement($incomingData); - } - $form = $this->formBuilder->buildModel(); - $this->view->assign('model', $form); - } - - /** - * Handles confirmation action, presenting the user submitted - * data again for final confirmation. - * - * @param \TYPO3\CMS\Form\Domain\Model\ValidationElement $model - * @return void - */ - public function confirmationAction(ValidationElement $model) - { - $this->skipForeignFormProcessing(); - - if (count($model->getIncomingFields()) === 0) { - $this->sessionUtility->destroySession(); - $this->forward('show'); - } - $this->controllerContext->setValidationElement($model); - $form = $this->formBuilder->buildModel(); - // store uploaded files - $this->sessionUtility->storeSession(); - $this->view->assign('model', $form); - - $message = $this->formUtility->renderItem( - $this->typoscript['confirmation.']['message.'], - $this->typoscript['confirmation.']['message'], - LocalizationUtility::translate('tx_form_view_confirmation.message', 'form') - ); - $this->view->assign('message', $message); - } - - /** - * action dispatchConfirmationButtonClick - * - * @param \TYPO3\CMS\Form\Domain\Model\ValidationElement $model - * @return void - */ - public function dispatchConfirmationButtonClickAction(ValidationElement $model) - { - $this->skipForeignFormProcessing(); - - if ($this->request->hasArgument('confirmation-true')) { - $this->forward('process', null, null, [$this->configuration->getPrefix() => $this->request->getArgument('model')]); - } else { - $this->sessionUtility->destroySession(); - $this->forward('show', null, null, ['incomingData' => $this->request->getArgument('model')]); - } - } - - /** - * Handles process action, actually processing the user - * submitted data and forwarding it to post-processors - * (e.g. sending out mail messages). - * - * @param \TYPO3\CMS\Form\Domain\Model\ValidationElement $model - * @return void - */ - public function processAction(ValidationElement $model) - { - $this->skipForeignFormProcessing(); - - $this->controllerContext->setValidationElement($model); - $form = $this->formBuilder->buildModel(); - $postProcessorTypoScript = []; - if (isset($this->typoscript['postProcessor.'])) { - $postProcessorTypoScript = $this->typoscript['postProcessor.']; - } - - /** @var $postProcessor \TYPO3\CMS\Form\PostProcess\PostProcessor */ - $postProcessor = $this->objectManager->get( - \TYPO3\CMS\Form\PostProcess\PostProcessor::class, - $form, $postProcessorTypoScript - ); - $postProcessor->setControllerContext($this->controllerContext); - - // @todo What is happening here? - $content = $postProcessor->process(); - $this->sessionUtility->destroySession(); - $this->forward('afterProcess', null, null, ['postProcessorContent' => $content]); - } - - /** - * action after process - * - * @param string $postProcessorContent - * @return void - */ - public function afterProcessAction($postProcessorContent) - { - $this->view->assign('postProcessorContent', $postProcessorContent); - } - - /** - * Skip the processing of foreign forms. - * If there is more than one form on a page - * we have to be sure that only the submitted form will be - * processed. On data submission, the extbase action "confirmation" or - * "process" is called. The detection which form is submitted - * is done by the form prefix. All forms which do not have any - * submitted data are skipped and forwarded to the show action. - * - * @return void - */ - protected function skipForeignFormProcessing() - { - if ( - !$this->request->hasArgument($this->configuration->getPrefix()) - && !$this->sessionUtility->getSessionData() - ) { - $this->forward('show'); - } - } - - /** - * If the current form should be validated - * then set the dynamic validation - * - * @return void - */ - protected function prepareValidations() - { - if ($this->skipValidation || !$this->arguments->hasArgument('model')) { - return; - } - - $this->validationBuilder->buildRules($this->request->getArgument('model')); - $this->setDynamicValidation($this->validationBuilder->getRules()); - $this->skipValidation = false; - } - - /** - * Sets the dynamic validation rules. - * - * @param array $toValidate - * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException - * @throws \TYPO3\CMS\Extbase\Validation\Exception\NoSuchValidatorException - */ - protected function setDynamicValidation(array $toValidate = []) - { - // build custom validation chain - /** @var \TYPO3\CMS\Extbase\Validation\ValidatorResolver $validatorResolver */ - $validatorResolver = $this->objectManager->get(\TYPO3\CMS\Extbase\Validation\ValidatorResolver::class); - - /** @var \TYPO3\CMS\Form\Domain\Validator\ValidationElementValidator $modelValidator */ - $modelValidator = $validatorResolver->createValidator(\TYPO3\CMS\Form\Domain\Validator\ValidationElementValidator::class); - foreach ($toValidate as $propertyName => $validations) { - foreach ($validations as $validation) { - if (empty($validation['validator'])) { - throw new \TYPO3\CMS\Extbase\Validation\Exception\NoSuchValidatorException('Invalid validate configuration for ' . $propertyName . ': Could not resolve class name for validator "' . $validation['validatorName'] . '".', 1441893777); - } - $modelValidator->addPropertyValidator($propertyName, $validation['validator']); - } - } - - if ($modelValidator->countPropertyValidators()) { - /** @var \TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator $baseConjunctionValidator */ - $baseConjunctionValidator = $this->arguments->getArgument('model')->getValidator(); - if ($baseConjunctionValidator === null) { - $baseConjunctionValidator = $validatorResolver->createValidator(\TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator::class); - $this->arguments->getArgument('model')->setValidator($baseConjunctionValidator); - } - $baseConjunctionValidator->addValidator($modelValidator); - } - } -} diff --git a/typo3/sysext/form/Classes/Controller/WizardController.php b/typo3/sysext/form/Classes/Controller/WizardController.php deleted file mode 100644 index e7185dc80f9a0a8d9c23c029bc01e5e18510aea1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Controller/WizardController.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Controller; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Repository\ContentRepository; - -/** - * The form wizard controller - */ -class WizardController -{ - /** - * The constructor to load the LL file - */ - public function __construct() - { - $this->getLanguageService()->includeLLFile('EXT:form/Resources/Private/Language/locallang_wizard.xlf'); - } - - /** - * The save action called via AJAX - * - * The action which should be taken when the form in the wizard is saved - * - * @param ServerRequestInterface $request - * @param ResponseInterface $response - * @return ResponseInterface returns a 500 error or a valid JSON response - */ - public function saveAction(ServerRequestInterface $request, ResponseInterface $response) - { - $repository = $this->getRepository(); - $typoscript = ''; - $jsonArray = []; - - // Check if the referenced record is available - if ($repository->hasRecord()) { - // Save the data - $typoscript = $repository->save(); - } - - if (!$typoscript) { - $response = $response->withStatus(500); - $message = $this->getLanguageService()->getLL('action_save_message_failed', false); - } else { - $message = $this->getLanguageService()->getLL('action_save_message_saved', false); - $jsonArray['fakeTs'] = $typoscript; - } - - $jsonArray['message'] = $message; - $response->getBody()->write(json_encode($jsonArray)); - return $response - ->withHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT') - ->withHeader('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT') - ->withHeader('Cache-Control', 'no-cache, must-revalidate') - ->withHeader('Pragma', 'no-cache'); - } - - /** - * Gets the repository object. - * - * @return ContentRepository - */ - protected function getRepository() - { - return GeneralUtility::makeInstance(ContentRepository::class); - } - - /** - * Returns an instance of LanguageService - * - * @return \TYPO3\CMS\Lang\LanguageService - */ - protected function getLanguageService() - { - return $GLOBALS['LANG']; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Builder/ElementBuilder.php b/typo3/sysext/form/Classes/Domain/Builder/ElementBuilder.php deleted file mode 100644 index c2b0023ff4fa06c34285bc0c22ba4b04fc5bb5fe..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Builder/ElementBuilder.php +++ /dev/null @@ -1,510 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Builder; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\MathUtility; -use TYPO3\CMS\Form\Domain\Model\Element; - -/** - * Builder for Element domain models. - */ -class ElementBuilder -{ - /** - * @param FormBuilder $formBuilder - * @param Element $element - * @param array $userDefinedTypoScript - * @return ElementBuilder - */ - public static function create(FormBuilder $formBuilder, Element $element, array $userDefinedTypoScript) - { - /** @var ElementBuilder $elementBuilder */ - $elementBuilder = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(self::class); - $elementBuilder->setFormBuilder($formBuilder); - $elementBuilder->setElement($element); - $elementBuilder->setUserConfiguredElementTyposcript($userDefinedTypoScript); - return $elementBuilder; - } - - /** - * @var \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository - */ - protected $typoScriptRepository; - - /** - * @var \TYPO3\CMS\Extbase\Service\TypoScriptService - */ - protected $typoScriptService; - - /** - * @var array - */ - protected $userConfiguredElementTyposcript = []; - - /** - * @var array - */ - protected $htmlAttributes = []; - - /** - * @var array - */ - protected $additionalArguments = []; - - /** - * @var array - */ - protected $wildcardPrefixes = []; - - /** - * @var FormBuilder - */ - protected $formBuilder; - - /** - * @var Element - */ - protected $element; - - /** - * @param \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository - * @return void - */ - public function injectTypoScriptRepository(\TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository) - { - $this->typoScriptRepository = $typoScriptRepository; - } - - /** - * @param \TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService - * @return void - */ - public function injectTypoScriptService(\TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService) - { - $this->typoScriptService = $typoScriptService; - } - - /** - * @param FormBuilder $formBuilder - */ - public function setFormBuilder(FormBuilder $formBuilder) - { - $this->formBuilder = $formBuilder; - } - - /** - * @param Element $element - */ - public function setElement(Element $element) - { - $this->element = $element; - } - - /** - * Set the fluid partial path to the element - * - * @return void - */ - public function setPartialPaths() - { - $this->setElementPartialPath(); - } - - /** - * Set the fluid partial path to the element - * - * @return void - */ - protected function setElementPartialPath() - { - if (!isset($this->userConfiguredElementTyposcript['partialPath'])) { - $partialPath = $this->typoScriptRepository->getDefaultFluidTemplate($this->element->getElementType()); - } else { - $partialPath = $this->userConfiguredElementTyposcript['partialPath']; - unset($this->userConfiguredElementTyposcript['partialPath']); - } - $this->element->setPartialPath($partialPath); - } - - /** - * Set the fluid partial path to the element - * - * @return void - */ - public function setVisibility() - { - $visibility = false; - if ($this->formBuilder->getControllerAction() === 'show') { - if (!isset($this->userConfiguredElementTyposcript['visibleInShowAction'])) { - $visibility = (bool)$this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'visibleInShowAction'); - } else { - $visibility = (bool)$this->userConfiguredElementTyposcript['visibleInShowAction']; - } - } elseif ($this->formBuilder->getControllerAction() === 'confirmation') { - if (!isset($this->userConfiguredElementTyposcript['visibleInConfirmationAction'])) { - $visibility = (bool)$this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'visibleInConfirmationAction'); - } else { - $visibility = (bool)$this->userConfiguredElementTyposcript['visibleInConfirmationAction']; - } - } elseif ($this->formBuilder->getControllerAction() === 'process') { - if (!isset($this->userConfiguredElementTyposcript['visibleInMail'])) { - $visibility = (bool)$this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'visibleInMail'); - } else { - $visibility = (bool)$this->userConfiguredElementTyposcript['visibleInMail']; - } - } - $this->element->setShowElement($visibility); - } - - /** - * Find all prefix-* attributes and return the - * found prefixs. Than delete them from the htmlAttributes array - * - * @return void - */ - public function setHtmlAttributeWildcards() - { - foreach ($this->htmlAttributes as $attributeName => $attributeValue) { - if (strpos($attributeName, '-*') > 0) { - $prefix = substr($attributeName, 0, -1); - $this->wildcardPrefixes[] = $prefix; - unset($this->htmlAttributes[$attributeName]); - } - } - } - - /** - * Overlay user defined html attribute values - * To determine whats a html attribute, the htmlAttributes - * array is used. If a html attribute value is found in userConfiguredElementTyposcript - * this value is set to htmlAttributes and removed from userConfiguredElementTyposcript. - * - * @return void - */ - public function overlayUserdefinedHtmlAttributeValues() - { - foreach ($this->htmlAttributes as $attributeName => $attributeValue) { - $attributeNameWithoutDot = rtrim($attributeName, '.'); - $attributeNameToSet = $attributeNameWithoutDot; - - if ($this->arrayKeyExists($attributeNameWithoutDot, $this->userConfiguredElementTyposcript)) { - $attributeValue = $this->formBuilder->getFormUtility()->renderItem( - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.'], - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot] - ); - $this->htmlAttributes[$attributeNameToSet] = $attributeValue; - } - - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.']); - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot]); - } - - // the prefix-* magic - $ignoreKeys = []; - foreach ($this->userConfiguredElementTyposcript as $attributeName => $attributeValue) { - // ignore child elements - if ( - MathUtility::canBeInterpretedAsInteger($attributeName) - || isset($ignoreKeys[$attributeName]) - ) { - $ignoreKeys[$attributeName . '.'] = true; - continue; - } - - foreach ($this->wildcardPrefixes as $wildcardPrefix) { - if (strpos($attributeName, $wildcardPrefix) !== 0) { - continue; - } - $attributeNameWithoutDot = rtrim($attributeName, '.'); - $attributeValue = $this->formBuilder->getFormUtility()->renderItem( - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.'], - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot] - ); - $this->htmlAttributes[$attributeNameWithoutDot] = $attributeValue; - $ignoreKeys[$attributeNameWithoutDot . '.'] = true; - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.']); - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot]); - break; - } - } - } - - /** - * If fixedHtmlAttributeValues are defined for this element - * then overwrite the html attribute value - * - * @return void - */ - public function overlayFixedHtmlAttributeValues() - { - $fixedHtmlAttributeValues = $this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'fixedHtmlAttributeValues.'); - if (is_array($fixedHtmlAttributeValues)) { - foreach ($fixedHtmlAttributeValues as $attributeName => $attributeValue) { - $this->htmlAttributes[$attributeName] = $attributeValue; - } - } - } - - /** - * Move htmlAttributes to additionalArguments that must be passed - * as a view helper argument - * - * @return void - */ - public function moveHtmlAttributesToAdditionalArguments() - { - $htmlAttributesUsedByTheViewHelperDirectly = $this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'htmlAttributesUsedByTheViewHelperDirectly.'); - if (is_array($htmlAttributesUsedByTheViewHelperDirectly)) { - foreach ($htmlAttributesUsedByTheViewHelperDirectly as $attributeName) { - if (array_key_exists($attributeName, $this->htmlAttributes)) { - $this->additionalArguments[$attributeName] = $this->htmlAttributes[$attributeName]; - unset($this->htmlAttributes[$attributeName]); - } - } - } - } - - /** - * Set the viewhelper default arguments in the additionalArguments array - * - * @return void - */ - public function setViewHelperDefaulArgumentsToAdditionalArguments() - { - $viewHelperDefaultArguments = $this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'viewHelperDefaultArguments.'); - if (is_array($viewHelperDefaultArguments)) { - foreach ($viewHelperDefaultArguments as $viewHelperDefaulArgumentName => $viewHelperDefaulArgumentValue) { - $viewHelperDefaulArgumentNameWithoutDot = rtrim($viewHelperDefaulArgumentName, '.'); - $this->additionalArguments[$viewHelperDefaulArgumentNameWithoutDot] = $viewHelperDefaulArgumentValue; - } - } - unset($this->userConfiguredElementTyposcript['viewHelperDefaultArguments']); - } - - /** - * Move all userdefined properties to the additionalArguments - * array. Ignore the child elements - * - * @return void - */ - public function moveAllOtherUserdefinedPropertiesToAdditionalArguments() - { - $viewHelperDefaultArguments = $this->typoScriptRepository->getModelConfigurationByScope($this->element->getElementType(), 'viewHelperDefaultArguments.'); - $ignoreKeys = []; - - foreach ($this->userConfiguredElementTyposcript as $attributeName => $attributeValue) { - // ignore child elements - if ( - MathUtility::canBeInterpretedAsInteger($attributeName) - || isset($ignoreKeys[$attributeName]) - || $attributeName == 'postProcessor.' - || $attributeName == 'rules.' - || $attributeName == 'filters.' - || $attributeName == 'layout' - ) { - $ignoreKeys[$attributeName . '.'] = true; - continue; - } - $attributeNameWithoutDot = rtrim($attributeName, '.'); - $attributeNameToSet = $attributeNameWithoutDot; - - if ( - isset($viewHelperDefaultArguments[$attributeName]) - || isset($viewHelperDefaultArguments[$attributeNameWithoutDot]) - ) { - $this->formBuilder->getFormUtility()->renderArrayItems($attributeValue); - $attributeValue = $this->typoScriptService->convertTypoScriptArrayToPlainArray($attributeValue); - } else { - $attributeValue = $this->formBuilder->getFormUtility()->renderItem( - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.'], - $this->userConfiguredElementTyposcript[$attributeNameWithoutDot] - ); - } - $this->additionalArguments[$attributeNameToSet] = $attributeValue; - $ignoreKeys[$attributeNameToSet . '.'] = true; - $ignoreKeys[$attributeNameToSet] = true; - - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot . '.']); - unset($this->userConfiguredElementTyposcript[$attributeNameWithoutDot]); - } - // remove "stdWrap." from "additionalArguments" on - // the FORM Element - if ( - !$this->formBuilder->getConfiguration()->getContentElementRendering() - && $this->element->getElementType() == 'FORM' - ) { - unset($this->additionalArguments['stdWrap']); - unset($this->additionalArguments['stdWrap.']); - } - } - - /** - * Set the name and id attribute - * - * @return array - */ - public function setNameAndId() - { - if ( - $this->element->getParentElement() - && (int)$this->typoScriptRepository->getModelConfigurationByScope($this->element->getParentElement()->getElementType(), 'childrenInheritName') == 1 - ) { - $this->htmlAttributes['name'] = $this->element->getParentElement()->getName(); - $this->additionalArguments['multiple'] = '1'; - $name = $this->sanitizeNameAttribute($this->userConfiguredElementTyposcript['name']); - $this->element->setName($name); - } else { - $this->htmlAttributes['name'] = $this->sanitizeNameAttribute($this->htmlAttributes['name']); - $this->element->setName($this->htmlAttributes['name']); - } - $this->htmlAttributes['id'] = $this->sanitizeIdAttribute($this->htmlAttributes['id']); - $this->element->setId($this->htmlAttributes['id']); - } - - /** - * If the name is not defined it is automatically generated - * using the following syntax: id-{element_counter} - * The name attribute will be transformed if it contains some - * non allowed characters: - * - spaces are changed into hyphens - * - remove all characters except a-z A-Z 0-9 _ - - * - * @param string $name - * @return string - */ - public function sanitizeNameAttribute($name) - { - $name = $this->formBuilder->getFormUtility()->sanitizeNameAttribute($name); - if (empty($name)) { - $name = 'id-' . $this->element->getElementCounter(); - } - return $name; - } - - /** - * If the id is not defined it is automatically generated - * using the following syntax: field-{element_counter} - * The id attribute will be transformed if it contains some - * non allowed characters: - * - spaces are changed into hyphens - * - if the id start with a integer then transform it to field-{integer} - * - remove all characters expect a-z A-Z 0-9 _ - : . - * - * @param string $id - * @return string - */ - protected function sanitizeIdAttribute($id) - { - $id = $this->formBuilder->getFormUtility()->sanitizeIdAttribute($id); - if (empty($id)) { - $id = 'field-' . $this->element->getElementCounter(); - } - return $id; - } - - /** - * Check if a needle exists in a array. - * - * @param string $needle - * @param array $haystack - * @return bool TRUE if found - */ - protected function arrayKeyExists($needle, array $haystack = []) - { - return - isset($haystack[$needle]) || isset($haystack[$needle . '.']) - ; - } - - /** - * Get the current html attributes - * - * @return array - */ - public function getHtmlAttributes() - { - return $this->htmlAttributes; - } - - /** - * Set the current html attributes - * - * @param array $htmlAttributes - */ - public function setHtmlAttributes(array $htmlAttributes) - { - $this->htmlAttributes = $htmlAttributes; - } - - /** - * Get the current additional arguments - * - * @return array - */ - public function getAdditionalArguments() - { - return $this->additionalArguments; - } - - /** - * Set the current additional arguments - * - * @param array $additionalArguments - */ - public function setAdditionalArguments(array $additionalArguments) - { - $this->additionalArguments = $additionalArguments; - } - - /** - * Get the current wildcard prefixes - * - * @return array - */ - public function getWildcardPrefixes() - { - return $this->wildcardPrefixes; - } - - /** - * Set the current wildcard prefixes - * - * @param array $wildcardPrefixes - */ - public function setWildcardPrefixes(array $wildcardPrefixes) - { - $this->wildcardPrefixes = $wildcardPrefixes; - } - - /** - * Get the current Element - * - * @return array - */ - public function getUserConfiguredElementTyposcript() - { - return $this->userConfiguredElementTyposcript; - } - - /** - * Set the current Element - * - * @param array $userConfiguredElementTyposcript - */ - public function setUserConfiguredElementTyposcript(array $userConfiguredElementTyposcript) - { - $this->userConfiguredElementTyposcript = $userConfiguredElementTyposcript; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Builder/FormBuilder.php b/typo3/sysext/form/Classes/Domain/Builder/FormBuilder.php deleted file mode 100644 index 9f4ddac0ba683b6d548f41ed407b0a6de7d317dd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Builder/FormBuilder.php +++ /dev/null @@ -1,579 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Builder; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Form\Domain\Model\Element; -use TYPO3\CMS\Form\Domain\Model\ValidationElement; -use TYPO3\CMS\Form\Mvc\Controller\ControllerContext; -use TYPO3\CMS\Form\Utility\FormUtility; - -/** - * TypoScript factory for form - * - * Takes the incoming TypoScript and adds all the necessary form objects - * according to the configuration. - */ -class FormBuilder -{ - /** - * @param Configuration $configuration - * @return FormBuilder - */ - public static function create(Configuration $configuration) - { - /** @var FormBuilder $formBuilder */ - $formBuilder = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(self::class); - $formBuilder->setConfiguration($configuration); - return $formBuilder; - } - - /** - * @var FormUtility - */ - protected $formUtility; - - /** - * @var \TYPO3\CMS\Extbase\Service\TypoScriptService - */ - protected $typoScriptService; - - /** - * @var ValidationBuilder - */ - protected $validationBuilder; - - /** - * @var \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository - */ - protected $typoScriptRepository; - - /** - * @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher - */ - protected $signalSlotDispatcher; - - /** - * @var \TYPO3\CMS\Form\Utility\SessionUtility - */ - protected $sessionUtility; - - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManager - */ - protected $objectManager; - - /** - * @var \TYPO3\CMS\Form\Utility\ElementCounter - */ - protected $elementCounter; - - /** - * @var NULL|\TYPO3\CMS\Extbase\Error\Result - */ - protected $validationErrors = null; - - /** - * @var Configuration; - */ - protected $configuration; - - /** - * @var ControllerContext - */ - protected $controllerContext; - - /** - * @param \TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService - * @return void - */ - public function injectTypoScriptService(\TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService) - { - $this->typoScriptService = $typoScriptService; - } - - /** - * @param \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository - * @return void - */ - public function injectTypoScriptRepository(\TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository) - { - $this->typoScriptRepository = $typoScriptRepository; - } - - /** - * @param \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher - * @return void - */ - public function injectSignalSlotDispatcher(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher) - { - $this->signalSlotDispatcher = $signalSlotDispatcher; - } - - /** - * @param \TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility - * @return void - */ - public function injectSessionUtility(\TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility) - { - $this->sessionUtility = $sessionUtility; - } - - /** - * @param \TYPO3\CMS\Form\Utility\ElementCounter $elementCounter - * @return void - */ - public function injectElementCounter(\TYPO3\CMS\Form\Utility\ElementCounter $elementCounter) - { - $this->elementCounter = $elementCounter; - } - - /** - * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager - * @return void - */ - public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * @return Configuration - */ - public function getConfiguration() - { - return $this->configuration; - } - - /** - * @param Configuration $configuration - */ - public function setConfiguration(Configuration $configuration) - { - $this->configuration = $configuration; - } - - /** - * @return ControllerContext - */ - public function getControllerContext() - { - return $this->controllerContext; - } - - /** - * @param ControllerContext $controllerContext - */ - public function setControllerContext(ControllerContext $controllerContext) - { - $this->controllerContext = $controllerContext; - } - - /** - * @return FormUtility - */ - public function getFormUtility() - { - return $this->formUtility; - } - - /** - * @param FormUtility $formUtility - */ - public function setFormUtility(FormUtility $formUtility) - { - $this->formUtility = $formUtility; - } - - /** - * @return ValidationBuilder - */ - public function getValidationBuilder() - { - return $this->validationBuilder; - } - - /** - * @param ValidationBuilder $validationBuilder - */ - public function setValidationBuilder(ValidationBuilder $validationBuilder) - { - $this->validationBuilder = $validationBuilder; - } - - /** - * Build model from TypoScript - * Needed if more than one form exist at a page - * - * @return NULL|\TYPO3\CMS\Form\Domain\Model\Element The form object containing the child elements - */ - public function buildModel() - { - $userConfiguredFormTypoScript = $this->configuration->getTypoScript(); - $form = $this->createElementObject(); - $this->reviveElement($form, $userConfiguredFormTypoScript, 'FORM'); - $form->setThemeName($this->configuration->getThemeName()); - return $form; - } - - /** - * Create a element - * - * @return \TYPO3\CMS\Form\Domain\Model\Element - */ - protected function createElementObject() - { - $element = GeneralUtility::makeInstance(Element::class); - return $element; - } - - /** - * Revive the domain model of the accordant element. - * - * @param Element $element - * @param array $userConfiguredElementTypoScript The configuration array - * @param string $elementType The element type (e.g BUTTON) - * @return void - */ - protected function reviveElement(Element $element, array $userConfiguredElementTypoScript, $elementType = '') - { - // @todo Check $userConfiguredElementTypoScript - - $element->setElementType($elementType); - $element->setElementCounter($this->elementCounter->getElementId()); - - $elementBuilder = ElementBuilder::create($this, $element, $userConfiguredElementTypoScript); - $elementBuilder->setPartialPaths(); - $elementBuilder->setVisibility(); - - if ($element->getElementType() == 'CONTENTELEMENT') { - $attributeValue = ''; - if ($this->configuration->getContentElementRendering()) { - $attributeValue = $this->formUtility->renderItem( - $userConfiguredElementTypoScript['cObj.'], - $userConfiguredElementTypoScript['cObj'] - ); - } - $element->setAdditionalArguments([ - 'content' => $attributeValue, - ]); - } else { - $this->setAttributes($elementBuilder, $element, $userConfiguredElementTypoScript); - $userConfiguredElementTypoScript = $elementBuilder->getUserConfiguredElementTyposcript(); - $this->setValidationMessages($element); - - $this->signalSlotDispatcher->dispatch( - __CLASS__, - 'txFormAfterElementCreation', - [$element, $this] - ); - // create all child elements - $this->setChildElementsByIntegerKey($element, $userConfiguredElementTypoScript); - } - } - - /** - * Rendering of a "numerical array" of Form objects from TypoScript - * Creates new object for each element found - * - * @param Element $element - * @param array $userConfiguredElementTypoScript The configuration array - * @return void - * @throws \InvalidArgumentException - */ - protected function setChildElementsByIntegerKey(Element $element, array $userConfiguredElementTypoScript) - { - if (is_array($userConfiguredElementTypoScript)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($userConfiguredElementTypoScript); - foreach ($keys as $key) { - if ( - (int)$key - && strpos($key, '.') === false - ) { - $elementType = $userConfiguredElementTypoScript[$key]; - if (isset($userConfiguredElementTypoScript[$key . '.'])) { - $concreteChildElementTypoScript = $userConfiguredElementTypoScript[$key . '.']; - } else { - $concreteChildElementTypoScript = []; - } - $this->distinguishElementType($element, $concreteChildElementTypoScript, $elementType); - } - } - } else { - throw new \InvalidArgumentException('Container element with id=' . $element->getElementCounter() . ' has no configuration which means no children.', 1333754854); - } - } - - /** - * Create and add element by type. - * If its not a registered form element - * try to render it as contentelement with the internal elementType - * CONTENTELEMENT - * - * @param Element $element - * @param array $userConfiguredElementTypoScript The configuration array - * @param string $elementType The element type (e.g BUTTON) - * @return void - */ - protected function distinguishElementType(Element $element, array $userConfiguredElementTypoScript, $elementType = '') - { - if (in_array($elementType, $this->typoScriptRepository->getRegisteredElementTypes())) { - $this->addChildElement($element, $userConfiguredElementTypoScript, $elementType); - } elseif ($this->configuration->getContentElementRendering()) { - $contentObject = [ - 'cObj' => $elementType, - 'cObj.' => $userConfiguredElementTypoScript - ]; - $this->addChildElement($element, $contentObject, 'CONTENTELEMENT'); - } - } - - /** - * Add child object to this element - * - * @param Element $element - * @param array $userConfiguredElementTypoScript The configuration array - * @param string $elementType The element type (e.g BUTTON) - * @return void - */ - protected function addChildElement(Element $element, array $userConfiguredElementTypoScript, $elementType = '') - { - $childElement = $this->createElementObject(); - $childElement->setParentElement($element); - $element->addChildElement($childElement); - $this->reviveElement($childElement, $userConfiguredElementTypoScript, $elementType); - } - - /** - * Set the htmlAttributes and the additionalAttributes - * Remap htmlAttributes to additionalAttributes if needed - * - * @param ElementBuilder $elementBuilder - * @param Element $element - * @return void - */ - protected function setAttributes(ElementBuilder $elementBuilder, Element $element) - { - $htmlAttributes = $this->typoScriptRepository->getModelDefinedHtmlAttributes($element->getElementType()); - $elementBuilder->setHtmlAttributes($htmlAttributes); - $elementBuilder->setHtmlAttributeWildcards(); - $elementBuilder->overlayUserdefinedHtmlAttributeValues(); - $elementBuilder->setNameAndId(); - $elementBuilder->overlayFixedHtmlAttributeValues(); - // remove all NULL values - $htmlAttributes = array_filter($elementBuilder->getHtmlAttributes()); - - $elementBuilder->setHtmlAttributes($htmlAttributes); - $elementBuilder->moveHtmlAttributesToAdditionalArguments(); - $elementBuilder->setViewHelperDefaulArgumentsToAdditionalArguments(); - $elementBuilder->moveAllOtherUserdefinedPropertiesToAdditionalArguments(); - $htmlAttributes = $elementBuilder->getHtmlAttributes(); - $userConfiguredElementTypoScript = $elementBuilder->getUserConfiguredElementTyposcript(); - $additionalArguments = $elementBuilder->getAdditionalArguments(); - $element->setHtmlAttributes($htmlAttributes); - $additionalArguments = $this->typoScriptService->convertTypoScriptArrayToPlainArray($additionalArguments); - $additionalArguments['prefix'] = $this->configuration->getPrefix(); - $element->setAdditionalArguments($additionalArguments); - $this->handleIncomingValues($element, $userConfiguredElementTypoScript); - - if ( - $element->getElementType() === 'FORM' - && $this->getControllerAction() === 'show' - ) { - if (empty($element->getHtmlAttribute('action'))) { - if ( - $element->getAdditionalArgument('confirmation') - && (int)$element->getAdditionalArgument('confirmation') === 1 - ) { - $element->setAdditionalArgument('action', 'confirmation'); - } else { - $element->setAdditionalArgument('action', 'process'); - } - } else { - $element->setAdditionalArgument('pageUid', $element->getHtmlAttribute('action')); - $element->setAdditionalArgument('action', null); - } - } - - // needed if confirmation page is enabled - if ( - $this->sessionUtility->getSessionData($element->getName()) - && $element->getAdditionalArgument('uploadedFiles') === null - ) { - $element->setAdditionalArgument('uploadedFiles', $this->sessionUtility->getSessionData($element->getName())); - } - } - - /** - * Handles the incoming form data - * - * @param Element $element - * @param array $userConfiguredElementTypoScript - * @return array - */ - protected function handleIncomingValues(Element $element, array $userConfiguredElementTypoScript) - { - if (!$this->getIncomingData()) { - return; - } - $elementName = $element->getName(); - if ($element->getHtmlAttribute('value') !== null) { - $modelValue = $element->getHtmlAttribute('value'); - } else { - $modelValue = $element->getAdditionalArgument('value'); - } - - if ($this->getIncomingData()->getIncomingField($elementName) !== null) { - /* filter values and set it back to incoming fields */ - $filters = isset($userConfiguredElementTypoScript['filters.']) ? $userConfiguredElementTypoScript['filters.'] : []; - if (!empty($filters)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($filters); - foreach ($keys as $key) { - $class = $userConfiguredElementTypoScript['filters.'][$key]; - if ( - (int)$key - && strpos($key, '.') === false - ) { - $filterArguments = $userConfiguredElementTypoScript['filters.'][$key . '.']; - $filterClassName = $this->typoScriptRepository->getRegisteredClassName((string)$class, 'registeredFilters'); - if ($filterClassName !== null) { - // toDo: handel array values - if (is_string($this->getIncomingData()->getIncomingField($elementName))) { - if (is_null($filterArguments)) { - $filter = $this->objectManager->get($filterClassName); - } else { - $filter = $this->objectManager->get($filterClassName, $filterArguments); - } - if ($filter) { - $value = $filter->filter($this->getIncomingData()->getIncomingField($elementName)); - $this->getIncomingData()->setIncomingField($elementName, $value); - } else { - throw new \RuntimeException('Class "' . $filterClassName . '" could not be loaded.', 1476122052); - } - } - } else { - throw new \RuntimeException('Class "' . $filterClassName . '" not registered via TypoScript.', 1476048485); - } - } - } - } - - if ($element->getHtmlAttribute('value') !== null) { - $element->setHtmlAttribute('value', $this->getIncomingData()->getIncomingField($elementName)); - } else { - $element->setAdditionalArgument('value', $this->getIncomingData()->getIncomingField($elementName)); - } - } - $this->signalSlotDispatcher->dispatch( - __CLASS__, - 'txFormHandleIncomingValues', - [ - $element, - $this->getIncomingData(), - $modelValue, - $this - ] - ); - } - - /** - * Set the rendered mandatory message - * and the validation error message if available - * - * @param Element $element - * @return void - */ - protected function setValidationMessages(Element $element) - { - $elementName = $element->getName(); - $mandatoryMessages = $this->validationBuilder->getMandatoryValidationMessagesByElementName($elementName); - $element->setMandatoryValidationMessages($mandatoryMessages); - if ( - $this->getValidationErrors() - && $this->getValidationErrors()->forProperty($elementName)->hasErrors() - ) { - /** @var \TYPO3\CMS\Extbase\Error\Error[] $errors */ - $errors = $this->getValidationErrors()->forProperty($elementName)->getErrors(); - $errorMessages = []; - foreach ($errors as $error) { - $errorMessages[] = $error->getMessage(); - } - $element->setValidationErrorMessages($errorMessages); - } - } - - /** - * Return the form prefix - * - * @return string - */ - public function getFormPrefix() - { - return $this->configuration->getPrefix(); - } - - /** - * TRUE if the content element rendering should be disabled. - * - * @return bool - */ - public function getDisableContentElementRendering() - { - return !$this->configuration->getContentElementRendering(); - } - - /** - * TRUE if the content element rendering should be disabled. - * - * @return string - */ - public function getControllerAction() - { - return $this->controllerContext->getRequest()->getControllerActionName(); - } - - /** - * Get the incoming flat form data - * - * @return ValidationElement - */ - public function getIncomingData() - { - return $this->controllerContext->getValidationElement(); - } - - /** - * Set the validation errors - * - * @param \TYPO3\CMS\Extbase\Error\Result $validationErrors - * @return void - */ - public function setValidationErrors(\TYPO3\CMS\Extbase\Error\Result $validationErrors) - { - $this->validationErrors = $validationErrors; - } - - /** - * Get the validation errors - * - * @return NULL|\TYPO3\CMS\Extbase\Error\Result - */ - public function getValidationErrors() - { - return $this->validationErrors; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Builder/ValidationBuilder.php b/typo3/sysext/form/Classes/Domain/Builder/ValidationBuilder.php deleted file mode 100644 index f56bccc9365b4615234b81215120b6f9cad5f2f8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Builder/ValidationBuilder.php +++ /dev/null @@ -1,254 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Builder; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Form\Domain\Validator\AbstractValidator; -use TYPO3\CMS\Form\Utility\FormUtility; - -/** - * Parse and hole all the validation rules - */ -class ValidationBuilder -{ - /** - * @param Configuration $configuration - * @return ValidationBuilder - */ - public static function create(Configuration $configuration) - { - /** @var ValidationBuilder $validationBuilder */ - $validationBuilder = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(self::class); - $validationBuilder->setConfiguration($configuration); - return $validationBuilder; - } - - /** - * @var array|array[] - */ - protected $rules = []; - - /** - * @var string - */ - protected $formPrefix = ''; - - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManager - */ - protected $objectManager; - - /** - * @var \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository - */ - protected $typoScriptRepository; - - /** - * @var FormUtility - */ - protected $formUtility; - - /** - * @var Configuration - */ - protected $configuration; - - /** - * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager - * @return void - */ - public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * @param \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository - * @return void - */ - public function injectTypoScriptRepository(\TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository) - { - $this->typoScriptRepository = $typoScriptRepository; - } - - /** - * @param Configuration $configuration - */ - public function setConfiguration(Configuration $configuration) - { - $this->configuration = $configuration; - } - - /** - * @param FormUtility $formUtility - */ - public function setFormUtility(FormUtility $formUtility) - { - $this->formUtility = $formUtility; - } - - /** - * Build validation rules from typoscript. - * The old breakOnError property are no longer supported - * - * @param array $rawArgument - * @return void - */ - public function buildRules(array $rawArgument = []) - { - $userConfiguredFormTyposcript = $this->configuration->getTypoScript(); - $rulesTyposcript = isset($userConfiguredFormTyposcript['rules.']) ? $userConfiguredFormTyposcript['rules.'] : null; - $this->rules[$this->configuration->getPrefix()] = []; - if (is_array($rulesTyposcript)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($rulesTyposcript); - foreach ($keys as $key) { - $ruleName = $rulesTyposcript[$key]; - $validatorClassName = $this->typoScriptRepository->getRegisteredClassName($ruleName, 'registeredValidators'); - if ($validatorClassName === null) { - throw new \RuntimeException( - 'Class "' . $validatorClassName . '" not registered via typoscript.', - 1476048511 - ); - } - if ( - (int)$key - && strpos($key, '.') === false - ) { - $ruleArguments = $rulesTyposcript[$key . '.']; - $fieldName = $this->formUtility->sanitizeNameAttribute($ruleArguments['element']); - // remove unsupported validator options - $validatorOptions = $ruleArguments; - $validatorOptions['errorMessage'] = [$ruleArguments['error.'], $ruleArguments['error']]; - $keysToRemove = array_flip([ - 'breakOnError', - 'message', - 'message.', - 'error', - 'error.', - 'showMessage', - ]); - $validatorOptions = array_diff_key($validatorOptions, $keysToRemove); - - // Instantiate the validator to check if all required options are assigned - // and to use the validator message rendering function to pre-render the mandatory message - /** @var AbstractValidator $validator */ - $validator = $this->objectManager->get($validatorClassName, $validatorOptions); - - if ($validator instanceof AbstractValidator) { - $validator->setRawArgument($rawArgument); - $validator->setFormUtility($this->formUtility); - - if ((int)$ruleArguments['showMessage'] === 1) { - $mandatoryMessage = $validator->renderMessage($ruleArguments['message.'], $ruleArguments['message']); - } else { - $mandatoryMessage = null; - } - - $this->rules[$this->configuration->getPrefix()][$fieldName][] = [ - 'validator' => $validator, - 'validatorName' => $validatorClassName, - 'validatorOptions' => $validatorOptions, - 'mandatoryMessage' => $mandatoryMessage - ]; - } else { - throw new \RuntimeException( - 'Class "' . $validatorClassName . '" could not be loaded.', - 1476048550 - ); - } - } - } - } - } - - /** - * Set all validation rules - * - * @param array $rules - * @return void - */ - public function setRules(array $rules) - { - $this->rules = $rules[$this->configuration->getPrefix()]; - } - - /** - * Get all validation rules - * - * @return array - */ - public function getRules() - { - return $this->rules[$this->configuration->getPrefix()]; - } - - /** - * Set a validation rule - * - * @param string $key - * @param array $rule - * @return void - */ - public function setRulesByElementName($key = '', array $rule = []) - { - $this->rules[$this->configuration->getPrefix()][$key] = $rule; - } - - /** - * Get a validation rule by key - * - * @param string $key - * @return NULL|array - */ - public function getRulesByElementName($key = '') - { - if (isset($this->rules[$this->configuration->getPrefix()][$key])) { - return $this->rules[$this->configuration->getPrefix()][$key]; - } - return null; - } - - /** - * Remove a validation rule by key - * - * @param string $key - * @return void - */ - public function removeRule($key = '') - { - unset($this->rules[$this->configuration->getPrefix()][$key]); - } - - /** - * Get all mandatory validation messages for a element - * - * @param string $key - * @return array - */ - public function getMandatoryValidationMessagesByElementName($key = '') - { - $mandatoryMessages = []; - if ($this->getRulesByElementName($key)) { - $rules = $this->getRulesByElementName($key); - foreach ($rules as $rule) { - if ($rule['mandatoryMessage']) { - $mandatoryMessages[] = $rule['mandatoryMessage']; - } - } - } - return $mandatoryMessages; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Configuration/ConfigurationService.php b/typo3/sysext/form/Classes/Domain/Configuration/ConfigurationService.php new file mode 100644 index 0000000000000000000000000000000000000000..555e7956593b3859df7170d7c66eb095e2029481 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Configuration/ConfigurationService.php @@ -0,0 +1,61 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Domain\Configuration\Exception\PrototypeNotFoundException; +use TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface; + +/** + * Helper for configuration settings + * + * Scope: frontend / backend + */ +class ConfigurationService +{ + + /** + * @var array + */ + protected $formSettings; + + /** + * @internal + */ + public function initializeObject() + { + $this->formSettings = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ConfigurationManagerInterface::class) + ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_YAML_SETTINGS, 'form'); + } + + /** + * Get the prototype configuration + * + * @param string $prototypeName name of the prototype to get the configuration for + * @return array the prototype configuration + * @throws PrototypeNotFoundException if prototype with the name $prototypeName was not found + * @api + */ + public function getPrototypeConfiguration(string $prototypeName): array + { + if (!isset($this->formSettings['prototypes'][$prototypeName])) { + throw new PrototypeNotFoundException(sprintf('The Prototype "%s" was not found.', $prototypeName), 1475924277); + } + return $this->formSettings['prototypes'][$prototypeName]; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Filter/StripNewLinesFilter.php b/typo3/sysext/form/Classes/Domain/Configuration/Exception/PrototypeNotFoundException.php similarity index 55% rename from typo3/sysext/form/Classes/Domain/Filter/StripNewLinesFilter.php rename to typo3/sysext/form/Classes/Domain/Configuration/Exception/PrototypeNotFoundException.php index 66eca1dd192f05a7ae1a67d31cd25f5e9b33dcb8..90c311f53c222e0741f341f0669ca9795a067f90 100644 --- a/typo3/sysext/form/Classes/Domain/Filter/StripNewLinesFilter.php +++ b/typo3/sysext/form/Classes/Domain/Configuration/Exception/PrototypeNotFoundException.php @@ -1,5 +1,6 @@ <?php -namespace TYPO3\CMS\Form\Domain\Filter; +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Configuration\Exception; /* * This file is part of the TYPO3 CMS project. @@ -14,19 +15,13 @@ namespace TYPO3\CMS\Form\Domain\Filter; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Form\Domain\Exception; + /** - * Strip new lines filter + * This exception is thrown if a form prototype for a given name was not found. + * + * @api */ -class StripNewLinesFilter extends AbstractFilter implements FilterInterface +class PrototypeNotFoundException extends Exception { - /** - * Strip newlines - * - * @param string $value - * @return string - */ - public function filter($value) - { - return str_replace([CRLF, LF, CR], ' ', (string)$value); - } } diff --git a/typo3/sysext/form/Classes/Domain/Filter/FilterInterface.php b/typo3/sysext/form/Classes/Domain/Exception.php similarity index 66% rename from typo3/sysext/form/Classes/Domain/Filter/FilterInterface.php rename to typo3/sysext/form/Classes/Domain/Exception.php index 06222269ed79aa8fa12f777d7f4da944956db129..0fd7c4652cdb3684e79e17a277ac20709af0bce3 100644 --- a/typo3/sysext/form/Classes/Domain/Filter/FilterInterface.php +++ b/typo3/sysext/form/Classes/Domain/Exception.php @@ -1,5 +1,6 @@ <?php -namespace TYPO3\CMS\Form\Domain\Filter; +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain; /* * This file is part of the TYPO3 CMS project. @@ -14,16 +15,13 @@ namespace TYPO3\CMS\Form\Domain\Filter; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Form\Exception as FormException; + /** - * Interface for filters + * A generic Form domain Exception + * + * @api */ -interface FilterInterface +class Exception extends FormException { - /** - * Return filtered value - * - * @param mixed $value - * @return mixed - */ - public function filter($value); } diff --git a/typo3/sysext/form/Classes/Domain/Filter/LowerCaseFilter.php b/typo3/sysext/form/Classes/Domain/Exception/IdentifierNotValidException.php similarity index 55% rename from typo3/sysext/form/Classes/Domain/Filter/LowerCaseFilter.php rename to typo3/sysext/form/Classes/Domain/Exception/IdentifierNotValidException.php index 55c16d470042a30e25ada2058c8bf21d8d224373..8b5d257996f51c31c3cb518ba73e9825c27b6be8 100644 --- a/typo3/sysext/form/Classes/Domain/Filter/LowerCaseFilter.php +++ b/typo3/sysext/form/Classes/Domain/Exception/IdentifierNotValidException.php @@ -1,5 +1,6 @@ <?php -namespace TYPO3\CMS\Form\Domain\Filter; +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Exception; /* * This file is part of the TYPO3 CMS project. @@ -14,19 +15,14 @@ namespace TYPO3\CMS\Form\Domain\Filter; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Form\Domain\Exception; + /** - * Lowercase filter + * This exception is thrown if the "identifier" for a Form, a Page or a Form Element + * is invalid (i.e. empty or not a string) + * + * @api */ -class LowerCaseFilter extends AbstractFilter implements FilterInterface +class IdentifierNotValidException extends Exception { - /** - * Convert alphabetic characters to lowercase - * - * @param string $value - * @return string - */ - public function filter($value) - { - return $this->convertCase($value, 'toLower'); - } } diff --git a/typo3/sysext/form/Classes/Domain/Exception/RenderingException.php b/typo3/sysext/form/Classes/Domain/Exception/RenderingException.php new file mode 100644 index 0000000000000000000000000000000000000000..1430f8a06089cccf0447e37305bb63270da13614 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Exception/RenderingException.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This exception is thrown if a rendering error occurs + * + * @api + */ +class RenderingException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotFoundException.php b/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotFoundException.php new file mode 100644 index 0000000000000000000000000000000000000000..3600a2adf9946089e81a194ca6470d4e5cd2b1b0 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotFoundException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This exception is thrown if a Type Definition for a form element was not found, + * or if the implementationClassName was not set. + * + * @api + */ +class TypeDefinitionNotFoundException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotValidException.php b/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotValidException.php new file mode 100644 index 0000000000000000000000000000000000000000..70b58a4f4d674aac776f89d49d097db1c75e032b --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Exception/TypeDefinitionNotValidException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This exception is thrown if a Type Definition for a form element was not valid, + * i.e. it has properties which are not supported. + * + * @api + */ +class TypeDefinitionNotValidException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Exception/UnknownCompositRenderableException.php b/typo3/sysext/form/Classes/Domain/Exception/UnknownCompositRenderableException.php new file mode 100644 index 0000000000000000000000000000000000000000..9ac5c2071658b7d8b401c98f62f20ae72b8d8a7c --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Exception/UnknownCompositRenderableException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This exception is thrown if the ArrayFormFactory want to create child + * elements within a unknown composit renderable. + * + * @api + */ +class UnknownCompositRenderableException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Factory/AbstractFormFactory.php b/typo3/sysext/form/Classes/Domain/Factory/AbstractFormFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..60c9e26a517f478097f5bdaacaef54b72e3e9d08 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Factory/AbstractFormFactory.php @@ -0,0 +1,65 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Factory; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\FormDefinition; + +/** + * Base class for custom *Form Factories*. A Form Factory is responsible for building + * a {@link TYPO3\CMS\Form\Domain\Model\FormDefinition}. + * + * {@inheritDoc} + * + * Example + * ======= + * + * Generally, you should use this class as follows: + * + * <pre> + * class MyFooBarFactory extends AbstractFormFactory { + * public function build(array $configuration, $prototypeName) { + * $configurationService = GeneralUtility::makeInstance(ObjectManager::class)->get(ConfigurationService::class); + * $prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName); + * $formDefinition = GeneralUtility::makeInstance(ObjectManager::class)->get(FormDefinition::class, 'nameOfMyForm', $prototypeConfiguration); + * + * // now, you should call methods on $formDefinition to add pages and form elements + * + * return $formDefinition; + * } + * } + * </pre> + * + * Scope: frontend / backend + * **This class is meant to be sub classed by developers.** + * @api + */ +abstract class AbstractFormFactory implements FormFactoryInterface +{ + /** + * Helper to be called by every AbstractFormFactory after everything has been built to trigger the "onBuildingFinished" + * template method on all form elements. + * + * @param FormDefinition $form + * @return void + * @api + */ + protected function triggerFormBuildingFinished(FormDefinition $form) + { + foreach ($form->getRenderablesRecursively() as $renderable) { + $renderable->onBuildingFinished(); + } + } +} diff --git a/typo3/sysext/form/Classes/Domain/Factory/ArrayFormFactory.php b/typo3/sysext/form/Classes/Domain/Factory/ArrayFormFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..4b08561b4b48246de2b27b833387a6cdf91d61b2 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Factory/ArrayFormFactory.php @@ -0,0 +1,120 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Factory; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException; +use TYPO3\CMS\Form\Domain\Exception\UnknownCompositRenderableException; +use TYPO3\CMS\Form\Domain\Model\FormDefinition; +use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection; +use TYPO3\CMS\Form\Domain\Model\Renderable\CompositeRenderableInterface; + +/** + * A factory that creates a FormDefinition from an array + * + * Scope: frontend / backend + */ +class ArrayFormFactory extends AbstractFormFactory +{ + + /** + * Build a form definition, depending on some configuration. + * + * @param array $configuration + * @param string $prototypeName + * @return FormDefinition + * @internal + */ + public function build(array $configuration, string $prototypeName = null): FormDefinition + { + if (empty($prototypeName)) { + $prototypeName = isset($configuration['prototypeName']) ? $configuration['prototypeName'] : 'standard'; + } + $persistenceIdentifier = (isset($configuration['persistenceIdentifier'])) ? $configuration['persistenceIdentifier'] : null; + + $prototypeConfiguration = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ConfigurationService::class) + ->getPrototypeConfiguration($prototypeName); + + $form = GeneralUtility::makeInstance(ObjectManager::class)->get( + FormDefinition::class, + $configuration['identifier'], + $prototypeConfiguration, + 'Form', + $persistenceIdentifier + ); + if (isset($configuration['renderables'])) { + foreach ($configuration['renderables'] as $pageConfiguration) { + $this->addNestedRenderable($pageConfiguration, $form); + } + } + + unset($configuration['persistenceIdentifier']); + unset($configuration['prototypeName']); + unset($configuration['renderables']); + unset($configuration['type']); + unset($configuration['identifier']); + unset($configuration['label']); + $form->setOptions($configuration); + + $this->triggerFormBuildingFinished($form); + + return $form; + } + + /** + * Add form elements to the $parentRenderable + * + * @param array $nestedRenderableConfiguration + * @param CompositeRenderableInterface CompositeRenderableInterface $parentRenderable + * @return mixed + * @throws IdentifierNotValidException + * @throws UnknownCompositRenderableException + */ + protected function addNestedRenderable(array $nestedRenderableConfiguration, CompositeRenderableInterface $parentRenderable) + { + if (!isset($nestedRenderableConfiguration['identifier'])) { + throw new IdentifierNotValidException('Identifier not set.', 1329289436); + } + if ($parentRenderable instanceof FormDefinition) { + $renderable = $parentRenderable->createPage($nestedRenderableConfiguration['identifier'], $nestedRenderableConfiguration['type']); + } elseif ($parentRenderable instanceof AbstractSection) { + $renderable = $parentRenderable->createElement($nestedRenderableConfiguration['identifier'], $nestedRenderableConfiguration['type']); + } else { + throw new UnknownCompositRenderableException('Unknown composit renderable "' . get_class($parentRenderable) . '"', 1479593622); + } + + if (isset($nestedRenderableConfiguration['renderables']) && is_array($nestedRenderableConfiguration['renderables'])) { + $childRenderables = $nestedRenderableConfiguration['renderables']; + } else { + $childRenderables = []; + } + + unset($nestedRenderableConfiguration['type']); + unset($nestedRenderableConfiguration['identifier']); + unset($nestedRenderableConfiguration['renderables']); + + $renderable->setOptions($nestedRenderableConfiguration); + + foreach ($childRenderables as $elementConfiguration) { + $this->addNestedRenderable($elementConfiguration, $renderable); + } + + return $renderable; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Factory/FormFactoryInterface.php b/typo3/sysext/form/Classes/Domain/Factory/FormFactoryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1ccb06cfcba5490464d8b8c5c6a380cb5916a3ac --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Factory/FormFactoryInterface.php @@ -0,0 +1,46 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Factory; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\FormDefinition; + +/** + * A Form Factory is responsible for building a {@link TYPO3\CMS\Form\Domain\Model\FormDefinition}. + * **Instead of implementing this interface, subclassing {@link AbstractFormFactory} is more appropriate + * in most cases**. + * + * A Form Factory can be called anytime a FormDefinition should be built; in most cases + * it is done through an invocation of a Form Rendering ViewHelper. + * + * Scope: frontend / backend + * @api + */ +interface FormFactoryInterface +{ + + /** + * Build a form definition, depending on some configuration. + * + * The configuration array is factory-specific; for example a YAML or JSON factory + * could retrieve the path to the YAML / JSON file via the configuration array. + * + * @param array $configuration factory-specific configuration array + * @param string $prototypeName The name of the "PrototypeName" to use; it is factory-specific to implement this. + * @return FormDefinition a newly built form definition + * @api + */ + public function build(array $configuration, string $prototypeName = null): FormDefinition; +} diff --git a/typo3/sysext/form/Classes/Domain/Factory/JsonToTypoScript.php b/typo3/sysext/form/Classes/Domain/Factory/JsonToTypoScript.php deleted file mode 100644 index b10f8a575b51805e98def0e83a6317ba2eb0941b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Factory/JsonToTypoScript.php +++ /dev/null @@ -1,591 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Factory; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Json to Typoscript converter - * - * Takes the incoming Json and converts it to Typoscipt - */ -class JsonToTypoScript -{ - /** - * Internal counter for the elements - * - * @var int - */ - protected $elementId = 0; - - /** - * Storage for the validation rules - * In TypoScript they are set in the form, in the wizard on the elements - * - * @var array - */ - protected $validationRules = []; - - /** - * Internal counter for the validation rules - * - * @var int - */ - protected $validationRulesCounter = 1; - - /** - * Convert JSON to TypoScript - * - * First a TypoScript array is constructed, - * which will be converted to a formatted string - * - * @param string $json Json containing all configuration for the form - * @return string The typoscript for the form - */ - public function convert($json) - { - $elements = json_decode((string)$json, true); - $typoscriptArray = []; - $typoscript = null; - $this->convertToTyposcriptArray($elements, $typoscriptArray); - if ($typoscriptArray['10.'] && is_array($typoscriptArray['10.']) && !empty($typoscriptArray['10.'])) { - $typoscript = $this->typoscriptArrayToString($typoscriptArray['10.']); - } - return $typoscript; - } - - /** - * Converts the JSON array for each element to a TypoScript array - * and adds this Typoscript array to the parent - * - * @param array $elements The JSON array - * @param array $parent The parent element - * @param bool $childrenWithParentName Indicates if the children use the parent name - * @return void - */ - protected function convertToTyposcriptArray(array $elements, array &$parent, $childrenWithParentName = false) - { - if (is_array($elements)) { - $elementCounter = 10; - foreach ($elements as $element) { - if ($element['xtype']) { - $this->elementId++; - switch ($element['xtype']) { - case 'typo3-form-wizard-elements-basic-button': - - case 'typo3-form-wizard-elements-basic-checkbox': - - case 'typo3-form-wizard-elements-basic-fileupload': - - case 'typo3-form-wizard-elements-basic-hidden': - - case 'typo3-form-wizard-elements-basic-password': - - case 'typo3-form-wizard-elements-basic-radio': - - case 'typo3-form-wizard-elements-basic-reset': - - case 'typo3-form-wizard-elements-basic-select': - - case 'typo3-form-wizard-elements-basic-submit': - - case 'typo3-form-wizard-elements-basic-textarea': - - case 'typo3-form-wizard-elements-basic-textline': - - case 'typo3-form-wizard-elements-predefined-email': - - case 'typo3-form-wizard-elements-content-header': - - case 'typo3-form-wizard-elements-content-textblock': - $this->getDefaultElementSetup($element, $parent, $elementCounter, $childrenWithParentName); - break; - case 'typo3-form-wizard-elements-basic-fieldset': - - case 'typo3-form-wizard-elements-predefined-name': - $this->getDefaultElementSetup($element, $parent, $elementCounter); - $this->getContainer($element, $parent, $elementCounter); - break; - case 'typo3-form-wizard-elements-predefined-checkboxgroup': - - case 'typo3-form-wizard-elements-predefined-radiogroup': - $this->getDefaultElementSetup($element, $parent, $elementCounter); - $this->getContainer($element, $parent, $elementCounter, true); - break; - case 'typo3-form-wizard-elements-basic-form': - $this->getDefaultElementSetup($element, $parent, $elementCounter); - $this->getContainer($element, $parent, $elementCounter); - $this->getForm($element, $parent, $elementCounter); - break; - default: - - } - } - $elementCounter = $elementCounter + 10; - } - } - } - - /** - * Called for elements are a container for other elements like FORM and FIELDSET - * - * @param array $element The JSON array for this element - * @param array $parent The parent element - * @param bool $childrenWithParentName Indicates if the children use the parent name - * @param int $elementCounter The element counter - * @return void - */ - protected function getContainer(array $element, array &$parent, $elementCounter, $childrenWithParentName = false) - { - if ($element['elementContainer'] && $element['elementContainer']['items']) { - $this->convertToTyposcriptArray($element['elementContainer']['items'], $parent[$elementCounter . '.'], $childrenWithParentName); - } - } - - /** - * Only called for the type FORM - * - * Adds the validation rules to the form. In the wizard they are added to - * each element. In this script the validation rules are stored in a - * separate array to add them to the form at a later point. - * - * @param array $element The JSON array for this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function getForm(array $element, array &$parent, $elementCounter) - { - // @todo Put at the top of the form - if (!empty($this->validationRules)) { - $parent[$elementCounter . '.']['rules'] = $this->validationRules; - } - } - - /** - * Called for each element - * - * Adds the content object type to the parent array and starts adding the - * configuration for the element - * - * @param array $element The JSON array for this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @param bool $childrenWithParentName Indicates if the children use the parent name - * @return void - */ - protected function getDefaultElementSetup(array $element, array &$parent, $elementCounter, $childrenWithParentName = false) - { - $contentObjectType = $this->getContentObjectType($element); - if (is_null($contentObjectType) === false) { - $parent[$elementCounter] = $contentObjectType; - $parent[$elementCounter . '.'] = []; - if ($element['configuration']) { - $this->setConfiguration($element, $parent, $elementCounter, $childrenWithParentName); - } - } - } - - /** - * Returns the content object type which is related to the ExtJS xtype - * - * @param array $element The JSON array for this element - * @return string The Content Object Type - */ - protected function getContentObjectType(array $element) - { - $contentObjectType = null; - $shortXType = str_replace('typo3-form-wizard-elements-', '', $element['xtype']); - list($category, $type) = explode('-', $shortXType); - switch ($category) { - case 'basic': - $contentObjectType = strtoupper($type); - break; - case 'predefined': - switch ($type) { - case 'checkboxgroup': - - case 'radiogroup': - $contentObjectType = strtoupper($type); - break; - case 'email': - $contentObjectType = 'TEXTLINE'; - break; - case 'name': - $contentObjectType = 'FIELDSET'; - } - break; - case 'content': - switch ($type) { - case 'header': - - case 'textblock': - $contentObjectType = strtoupper($type); - } - default: - - } - return $contentObjectType; - } - - /** - * Iterates over the various configuration settings and calls the - * appropriate function for each setting - * - * @param array $element The JSON array for this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @param bool $childrenWithParentName Indicates if the children use the parent name - * @return void - */ - protected function setConfiguration(array $element, array &$parent, $elementCounter, $childrenWithParentName = false) - { - foreach ($element['configuration'] as $key => $value) { - switch ($key) { - case 'attributes': - $this->setAttributes($value, $parent, $elementCounter, $childrenWithParentName); - break; - case 'confirmation': - $this->setConfirmation($value, $parent, $elementCounter); - break; - case 'filters': - $this->setFilters($value, $parent, $elementCounter); - break; - case 'label': - $this->setLabel($value, $parent, $elementCounter); - break; - case 'layout': - $this->setLayout($element, $value, $parent, $elementCounter); - break; - case 'legend': - $this->setLegend($value, $parent, $elementCounter); - break; - case 'options': - $this->setOptions($element, $value, $parent, $elementCounter); - break; - case 'postProcessor': - $this->setPostProcessor($value, $parent, $elementCounter); - break; - case 'prefix': - $this->setPrefix($value, $parent, $elementCounter); - break; - case 'validation': - $this->setValidationRules($element, $value); - break; - case 'various': - $this->setVarious($element, $value, $parent, $elementCounter); - break; - default: - - } - } - } - - /** - * Set the attributes for the element - * - * @param array $attributes The JSON array for the attributes of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @param bool $childrenWithParentName Indicates if the children use the parent name - * @return void - */ - protected function setAttributes(array $attributes, array &$parent, $elementCounter, $childrenWithParentName = false) - { - foreach ($attributes as $key => $value) { - if ($key === 'name' && $value === '' && !$childrenWithParentName) { - $value = $this->elementId; - } - if ($value != '') { - $parent[$elementCounter . '.'][$key] = $value; - } - } - } - - /** - * Set the confirmation for the element FORM - * - * The confirmation indicates a confirmation screen has to be displayed - * - * @param bool $confirmation TRUE when confirmation screen - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setConfirmation($confirmation, array &$parent, $elementCounter) - { - $parent[$elementCounter . '.']['confirmation'] = $confirmation; - } - - /** - * Set the filters for the element - * - * @param array $filters The JSON array for the filters of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setFilters(array $filters, array &$parent, $elementCounter) - { - if (!empty($filters)) { - $parent[$elementCounter . '.']['filters'] = []; - $filterCounter = 1; - foreach ($filters as $name => $filterConfiguration) { - $parent[$elementCounter . '.']['filters'][$filterCounter] = $name; - $parent[$elementCounter . '.']['filters'][$filterCounter . '.'] = $filterConfiguration; - $filterCounter++; - } - } - } - - /** - * Set the label for the element - * - * @param array $label The JSON array for the label of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setLabel(array $label, array &$parent, $elementCounter) - { - if ($label['value'] != '') { - $parent[$elementCounter . '.']['label.']['value'] = $label['value']; - } - } - - /** - * Changes the layout of some elements when this has been set in the wizard - * - * The wizard only uses 'back' or 'front' to set the layout. The TypoScript - * of the form uses a XML notation for the position of the label to the - * field. - * - * @param array $element The JSON array for this element - * @param string $value The layout setting, back or front - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setLayout(array $element, $value, array &$parent, $elementCounter) - { - switch ($element['xtype']) { - case 'typo3-form-wizard-elements-basic-button': - - case 'typo3-form-wizard-elements-basic-fileupload': - - case 'typo3-form-wizard-elements-basic-password': - - case 'typo3-form-wizard-elements-basic-reset': - - case 'typo3-form-wizard-elements-basic-submit': - - case 'typo3-form-wizard-elements-basic-textline': - if ($value === 'back') { - $parent[$elementCounter . '.']['layout'] = '<input />' . LF . '<label />'; - } - break; - case 'typo3-form-wizard-elements-basic-checkbox': - - case 'typo3-form-wizard-elements-basic-radio': - if ($value === 'front') { - $parent[$elementCounter . '.']['layout'] = '<label />' . LF . '<input />'; - } - break; - case 'typo3-form-wizard-elements-basic-select': - if ($value === 'back') { - $parent[$elementCounter . '.']['layout'] = '<select>' . LF . '<elements />' . LF . '</select>' . LF . '<label />'; - } - break; - case 'typo3-form-wizard-elements-basic-textarea': - if ($value === 'back') { - $parent[$elementCounter . '.']['layout'] = '<textarea />' . LF . '<label />'; - } - break; - default: - - } - } - - /** - * Set the legend for the element - * - * @param array $legend The JSON array for the legend of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setLegend(array $legend, array &$parent, $elementCounter) - { - if ($legend['value'] != '') { - $parent[$elementCounter . '.']['legend.']['value'] = $legend['value']; - } - } - - /** - * Set the options for a SELECT - * - * Although other elements like CHECKBOXGROUP and RADIOGROUP are using the - * option setting as well, they act like containers and are handled - * differently - * - * @param array $element The JSON array for this element - * @param array $options The JSON array for the options of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setOptions(array $element, array $options, array &$parent, $elementCounter) - { - if (is_array($options) && $element['xtype'] === 'typo3-form-wizard-elements-basic-select') { - $optionCounter = 10; - foreach ($options as $option) { - $parent[$elementCounter . '.'][$optionCounter] = 'OPTION'; - $parent[$elementCounter . '.'][$optionCounter . '.']['text'] = $option['text']; - if (isset($option['attributes'])) { - $parent[$elementCounter . '.'][$optionCounter . '.'] += $option['attributes']; - } - $optionCounter = $optionCounter + 10; - } - } - } - - /** - * Set the post processors for the element - * - * @param array $postProcessors The JSON array for the post processors of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setPostProcessor(array $postProcessors, array &$parent, $elementCounter) - { - if (!empty($postProcessors)) { - $parent[$elementCounter . '.']['postProcessor'] = []; - $postProcessorCounter = 1; - foreach ($postProcessors as $name => $postProcessorConfiguration) { - $parent[$elementCounter . '.']['postProcessor'][$postProcessorCounter] = $name; - $parent[$elementCounter . '.']['postProcessor'][$postProcessorCounter . '.'] = $postProcessorConfiguration; - $postProcessorCounter++; - } - } - } - - /** - * Set the prefix for the element FORM - * - * The prefix will be used in the names of all elements in the form - * - * @param string $prefix The prefix for all element names - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setPrefix($prefix, array &$parent, $elementCounter) - { - $parent[$elementCounter . '.']['prefix'] = $prefix; - } - - /** - * Stores the validation rules, set to the elements, in a temporary array - * - * In the wizard the validation rules are added to the element, - * in TypoScript they are added to the form. - * - * @param array $element The JSON array for this element - * @param array $validationRules The temporary storage array for the rules - * @return void - */ - protected function setValidationRules(array $element, array $validationRules) - { - foreach ($validationRules as $name => $ruleConfiguration) { - if (isset($element['configuration']['attributes']['name']) && $element['configuration']['attributes']['name'] != '') { - $ruleConfiguration['element'] = $element['configuration']['attributes']['name']; - } elseif (isset($element['configuration']['various']['name']) && $element['configuration']['various']['name'] != '') { - $ruleConfiguration['element'] = $element['configuration']['various']['name']; - } else { - $ruleConfiguration['element'] = $this->elementId; - } - $this->validationRules[$this->validationRulesCounter] = $name; - $this->validationRules[$this->validationRulesCounter . '.'] = $ruleConfiguration; - $this->validationRulesCounter++; - } - } - - /** - * Set the various configuration of an element - * - * @param array $element The JSON array for this element - * @param array $various The JSON array for the various options of this element - * @param array $parent The parent element - * @param int $elementCounter The element counter - * @return void - */ - protected function setVarious(array $element, array $various, array &$parent, $elementCounter) - { - foreach ($various as $key => $value) { - switch ($key) { - case 'headingSize': - - case 'content': - - case 'text': - - case 'name': - $parent[$elementCounter . '.'][$key] = (string)$value; - break; - } - } - } - - /** - * Converts a TypoScript array to a formatted string - * - * Takes care of indentation, curly brackets and parentheses - * - * @param array $typoscriptArray The TypoScript array - * @param string $addKey Key which has underlying configuration - * @param int $tabCount The amount of tabs for indentation - * @return string The formatted TypoScript string - */ - protected function typoscriptArrayToString(array $typoscriptArray, $addKey = '', $tabCount = -1) - { - $typoscript = ''; - if ($addKey != '') { - $typoscript .= str_repeat(TAB, $tabCount) . str_replace('.', '', $addKey) . ' {' . LF; - } - $tabCount++; - foreach ($typoscriptArray as $key => $value) { - if (!is_array($value)) { - if (strstr($value, LF)) { - $typoscript .= str_repeat(TAB, $tabCount) . $key . ' (' . LF; - if ($key !== 'text') { - $value = str_replace(LF, LF . str_repeat(TAB, ($tabCount + 1)), $value); - $typoscript .= str_repeat(TAB, ($tabCount + 1)) . $value . LF; - } else { - $typoscript .= $value . LF; - } - $typoscript .= str_repeat(TAB, $tabCount) . ')' . LF; - } else { - $typoscript .= str_repeat(TAB, $tabCount) . $key . ' = ' . $value . LF; - } - } else { - $typoscript .= $this->typoscriptArrayToString($value, $key, $tabCount); - } - } - if ($addKey != '') { - $tabCount--; - $typoscript .= str_repeat(TAB, $tabCount) . '}' . LF; - } - return $typoscript; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/AbstractFilter.php b/typo3/sysext/form/Classes/Domain/Filter/AbstractFilter.php deleted file mode 100644 index 073158e6818bba5035ed70debb75f22abdc505c1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/AbstractFilter.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Core\Charset\CharsetConverter; -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * Abstract class for filters. - */ -abstract class AbstractFilter -{ - protected function convertCase($value, $case) - { - return $this->getCharsetConverter()->conv_case( - 'utf-8', - $value, - $case - ); - } - - /** - * @return CharsetConverter - */ - protected function getCharsetConverter() - { - return GeneralUtility::makeInstance(CharsetConverter::class); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/AlphabeticFilter.php b/typo3/sysext/form/Classes/Domain/Filter/AlphabeticFilter.php deleted file mode 100644 index f9f529a3346724e91633d6ca386105a39baf17b7..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/AlphabeticFilter.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Alphabetic filter - */ -class AlphabeticFilter extends AbstractFilter implements FilterInterface -{ - /** - * Allow whitespace - * - * @var bool - */ - protected $allowWhiteSpace; - - /** - * Constructor - * - * @param array $arguments Filter configuration - */ - public function __construct($arguments = []) - { - $this->setAllowWhiteSpace($arguments['allowWhiteSpace']); - } - - /** - * Allow white space in the submitted value - * - * @param bool $allowWhiteSpace True if allowed - * @return void - */ - public function setAllowWhiteSpace($allowWhiteSpace = true) - { - $this->allowWhiteSpace = (bool)$allowWhiteSpace; - } - - /** - * Return filtered value - * Remove all but alphabetic characters - * Allow whitespace by choice - * - * @param string $value - * @return string - */ - public function filter($value) - { - $whiteSpace = $this->allowWhiteSpace ? '\\s' : ''; - $pattern = '/[^\pL' . $whiteSpace . ']/u'; - return preg_replace($pattern, '', (string)$value); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/AlphanumericFilter.php b/typo3/sysext/form/Classes/Domain/Filter/AlphanumericFilter.php deleted file mode 100644 index 0c8c2670c127b98602f5fd7c27bcdf2879d575af..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/AlphanumericFilter.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Alphanumeric filter - */ -class AlphanumericFilter extends AbstractFilter implements FilterInterface -{ - /** - * Allow whitespace - * - * @var bool - */ - protected $allowWhiteSpace; - - /** - * Constructor - * - * @param array $arguments Filter configuration - */ - public function __construct($arguments = []) - { - $this->setAllowWhiteSpace($arguments['allowWhiteSpace']); - } - - /** - * Allow white space in the submitted value - * - * @param bool $allowWhiteSpace True if allowed - * @return void - */ - public function setAllowWhiteSpace($allowWhiteSpace = true) - { - $this->allowWhiteSpace = (bool)$allowWhiteSpace; - } - - /** - * Return filtered value - * Remove all but alphabetic and numeric characters - * Allow whitespace by choice - * - * @param string $value - * @return string - */ - public function filter($value) - { - $whiteSpace = $this->allowWhiteSpace ? '\\s' : ''; - $pattern = '/[^\pL\d' . $whiteSpace . ']/u'; - return preg_replace($pattern, '', (string)$value); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/CurrencyFilter.php b/typo3/sysext/form/Classes/Domain/Filter/CurrencyFilter.php deleted file mode 100644 index 99ae3c229df0133980be8079a585e63cfbf51140..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/CurrencyFilter.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Currency filter - */ -class CurrencyFilter extends AbstractFilter implements FilterInterface -{ - /** - * Separator between group of thousands - * Mostly dot, comma or whitespace - * - * @var string - */ - protected $decimalsPoint; - - /** - * Separator between group of thousands - * Mostly dot, comma or whitespace - * - * @var string - */ - protected $thousandSeparator; - - /** - * Constructor - * - * @param array $arguments Filter configuration - */ - public function __construct($arguments = []) - { - $this->setDecimalsPoint($arguments['decimalPoint']); - $this->setThousandSeparator($arguments['thousandSeparator']); - } - - /** - * Set the decimal point character - * - * @param string $decimalsPoint Character used for decimal point - * @return void - */ - public function setDecimalsPoint($decimalsPoint = '.') - { - if (empty($decimalsPoint)) { - $this->decimalsPoint = '.'; - } else { - $this->decimalsPoint = (string)$decimalsPoint; - } - } - - /** - * Set the thousand separator character - * - * @param string $thousandSeparator Character used for thousand separator - * @return void - */ - public function setThousandSeparator($thousandSeparator = ',') - { - if (empty($thousandSeparator)) { - $this->thousandSeparator = ','; - } elseif ($thousandSeparator === 'space') { - $this->thousandSeparator = ' '; - } elseif ($thousandSeparator === 'none') { - $this->thousandSeparator = ''; - } else { - $this->thousandSeparator = (string)$thousandSeparator; - } - } - - /** - * Change to float with 2 decimals - * Change the dot to comma if requested - * - * @param string $value - * @return string - */ - public function filter($value) - { - $value = str_replace( - [ - $this->thousandSeparator, - $this->decimalsPoint, - ], - [ - '', - '.' - ], - (string)$value - ); - - // replace all non numeric characters, decimalPoint and negativ sign - $value = preg_replace('/[^0-9.-]/', '', $value); - $value = (double)$value; - return number_format($value, 2, $this->decimalsPoint, $this->thousandSeparator); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/RegExpFilter.php b/typo3/sysext/form/Classes/Domain/Filter/RegExpFilter.php deleted file mode 100644 index aace6b2660899c61e9c63f95ca26e71f30e2777f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/RegExpFilter.php +++ /dev/null @@ -1,61 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Regular expression filter - */ -class RegExpFilter extends AbstractFilter implements FilterInterface -{ - /** - * Regular expression for filter - * - * @var bool - */ - protected $regularExpression; - - /** - * Constructor - * - * @param array $arguments Filter configuration - */ - public function __construct(array $arguments = []) - { - $this->setRegularExpression($arguments['expression']); - } - - /** - * Set the regular expression - * - * @param string $expression The regular expression - * @return void - */ - public function setRegularExpression($expression) - { - $this->regularExpression = (string)$expression; - } - - /** - * Return filtered value - * Remove all characters found in regular expression - * - * @param string $value - * @return string - */ - public function filter($value) - { - return preg_replace($this->regularExpression, '', (string)$value); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/RemoveXssFilter.php b/typo3/sysext/form/Classes/Domain/Filter/RemoveXssFilter.php deleted file mode 100644 index 0a97a2bc04fc778c7d8b947040c1de1813de4a54..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/RemoveXssFilter.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * Remove Cross Site Scripting filter - * - * @deprecated since TYPO3 v8, will be removed in TYPO3 v9 - */ -class RemoveXssFilter extends AbstractFilter implements FilterInterface -{ - /** - * Return filtered value - * Removes potential XSS code from the input string. - * - * Using an external class by Travis Puderbaugh <kallahar@quickwired.com> - * - * @param string $value Unfiltered value - * @return string The filtered value - * @deprecated since TYPO3 v8, will be removed in TYPO3 v9 - */ - public function filter($value) - { - $value = stripslashes($value); - $value = html_entity_decode($value, ENT_QUOTES); - $filteredValue = GeneralUtility::removeXSS($value); - return $filteredValue; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/TitleCaseFilter.php b/typo3/sysext/form/Classes/Domain/Filter/TitleCaseFilter.php deleted file mode 100644 index 89ae0c4a287696753e40400c8c7c019fe7e29e68..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/TitleCaseFilter.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Title filter - */ -class TitleCaseFilter extends AbstractFilter implements FilterInterface -{ - /** - * Convert alphabetic characters to title case - * - * @param string $value - * @return string - */ - public function filter($value) - { - $lower = $this->convertCase($value, 'toLower'); - return ucwords($lower); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/TrimFilter.php b/typo3/sysext/form/Classes/Domain/Filter/TrimFilter.php deleted file mode 100644 index cf36b9d3437c1639b6ffd94d6dd2b9d192d75575..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/TrimFilter.php +++ /dev/null @@ -1,70 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Trim filter - */ -class TrimFilter extends AbstractFilter implements FilterInterface -{ - /** - * Characters used by trim filter - * - * @var string - */ - protected $characterList; - - /** - * Constructor - * - * @param array $arguments Filter configuration - */ - public function __construct(array $arguments = []) - { - $this->setCharacterList($arguments['characterList']); - } - - /** - * Set the characters that need to be stripped from the - * beginning or the end of the input, - * in addition to the default trim characters - * - * @param string $characterList - * @return void - */ - public function setCharacterList($characterList) - { - $this->characterList = $characterList; - } - - /** - * Return filtered value - * Strip characters from the beginning and the end - * - * @param string $value - * @return string - */ - public function filter($value) - { - if ( - $this->characterList === null - || $this->characterList === '' - ) { - return trim((string)$value); - } else { - return trim((string)$value, $this->characterList); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Filter/UpperCaseFilter.php b/typo3/sysext/form/Classes/Domain/Filter/UpperCaseFilter.php deleted file mode 100644 index d24b96758d663ce1aad648137c3a30389e9dd682..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Filter/UpperCaseFilter.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Uppercase filter - */ -class UpperCaseFilter extends AbstractFilter implements FilterInterface -{ - /** - * Convert alphabetic characters to uppercase - * - * @param string $value - * @return string - */ - public function filter($value) - { - return $this->convertCase($value, 'toUpper'); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/AbstractFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/AbstractFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..f88c5187e3627ab5a48b10350f23530403c03d21 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/AbstractFinisher.php @@ -0,0 +1,208 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Reflection\ObjectAccess; +use TYPO3\CMS\Extbase\Utility\ArrayUtility; +use TYPO3\CMS\Form\Service\TranslationService; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * Finisher base class. + * + * Scope: frontend + * **This class is meant to be sub classed by developers** + */ +abstract class AbstractFinisher implements FinisherInterface +{ + + /** + * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface + */ + protected $objectManager; + + /** + * @var string + */ + protected $finisherIdentifier = ''; + + /** + * The options which have been set from the outside. Instead of directly + * accessing them, you should rather use parseOption(). + * + * @var array + */ + protected $options = []; + + /** + * These are the default options of the finisher. + * Override them in your concrete implementation. + * Default options should not be changed from "outside" + * + * @var array + */ + protected $defaultOptions = []; + + /** + * @var \TYPO3\CMS\Form\Domain\Finishers\FinisherContext + */ + protected $finisherContext; + + /** + * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager + * @internal + */ + public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * @param array $options configuration options in the format ['option1' => 'value1', 'option2' => 'value2', ...] + * @return void + * @api + */ + public function setOptions(array $options) + { + $this->options = $options; + } + + /** + * Sets a single finisher option (@see setOptions()) + * + * @param string $optionName name of the option to be set + * @param mixed $optionValue value of the option + * @return void + * @api + */ + public function setOption(string $optionName, $optionValue) + { + $this->options[$optionName] = $optionValue; + } + + /** + * Executes the finisher + * + * @param FinisherContext $finisherContext The Finisher context that contains the current Form Runtime and Response + * @return void + * @api + */ + final public function execute(FinisherContext $finisherContext) + { + $this->finisherIdentifier = (new \ReflectionClass($this))->getShortName(); + $this->finisherContext = $finisherContext; + $this->executeInternal(); + } + + /** + * This method is called in the concrete finisher whenever self::execute() is called. + * + * Override and fill with your own implementation! + * + * @return void + * @api + */ + abstract protected function executeInternal(); + + /** + * Read the option called $optionName from $this->options, and parse {...} + * as object accessors. + * + * Then translate the value. + * + * If $optionName was not found, the corresponding default option is returned (from $this->defaultOptions) + * + * @param string $optionName + * @return string|array|null + * @api + */ + protected function parseOption(string $optionName) + { + if ($optionName === 'translation') { + return null; + } + + $optionValue = ArrayUtility::getValueByPath($this->options, $optionName); + $defaultValue = ArrayUtility::getValueByPath($this->defaultOptions, $optionName); + + if ($optionValue === null && $defaultValue !== null) { + $optionValue = $defaultValue; + } + + if ($optionValue === null) { + return null; + } + + if (is_array($optionValue)) { + return $optionValue; + } + + $formRuntime = $this->finisherContext->getFormRuntime(); + $optionToCompare = $optionValue; + + // You can encapsulate a option value with {}. + // This enables you to access every getable property from the + // TYPO3\CMS\Form\Domain\Runtime. + // + // For example: {formState.formValues.<elemenIdentifier>} + // This is equal to "$formRuntime->getFormState()->getFormValues()[<elemenIdentifier>]" + $optionValue = preg_replace_callback('/{([^}]+)}/', function ($match) use ($formRuntime) { + return ObjectAccess::getPropertyPath($formRuntime, $match[1]); + }, $optionValue); + + if ($optionToCompare === $optionValue) { + + // This is just a shortcut for a {formState.formValues.<elementIdentifier>} notation. + // If one of the finisher option values is equal + // to a identifier from the form definition then + // the value of the submitted form element is used + // insteed. + // Lets say you have a textfield in your form with the + // identifier "Text1". If you put "Text1" + // in the email finisher option "subject" then the submited value + // from the "Text1" element is used as the email subject. + $formValues = $this->finisherContext->getFormValues(); + if (!is_bool($optionValue) && array_key_exists($optionValue, $formValues)) { + $optionValue = $formRuntime[$optionValue]; + } + } + + if (isset($this->options['translation']['translationFile'])) { + $optionValue = TranslationService::getInstance()->translateFinisherOption( + $formRuntime, + $this->finisherIdentifier, + $optionName, + $optionValue, + $this->options['translation'] + ); + } + + if (empty($optionValue)) { + if ($defaultValue !== null) { + $optionValue = $defaultValue; + } + } + return $optionValue; + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController() + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/ClosureFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/ClosureFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..b4d20cf73f66f325a3d04c08231532cf065b123a --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/ClosureFinisher.php @@ -0,0 +1,64 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException; + +/** + * A simple finisher that invokes a closure when executed + * + * Usage: + * //... + * $closureFinisher = $this->objectManager->get(ClosureFinisher::class); + * $closureFinisher->setOption('closure', function($finisherContext) { + * $formRuntime = $finisherContext->getFormRuntime(); + * // ... + * }); + * $formDefinition->addFinisher($closureFinisher); + * // ... + * + * Scope: frontend + */ +class ClosureFinisher extends AbstractFinisher +{ + + /** + * @var array + */ + protected $defaultOptions = [ + 'closure' => null + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + * @throws FinisherException + */ + protected function executeInternal() + { + /** @var $closure \Closure */ + $closure = $this->parseOption('closure'); + if ($closure === null) { + return; + } + if (!$closure instanceof \Closure) { + throw new FinisherException(sprintf('The option "closure" must be of type Closure, "%s" given.', gettype($closure)), 1332155239); + } + $closure($this->finisherContext); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/ConfirmationFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/ConfirmationFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..722dfbb171159af57b9b3b8e9056cfbf5e0e929e --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/ConfirmationFinisher.php @@ -0,0 +1,63 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException; + +/** + * A simple finisher that outputs a given text + * + * Options: + * + * - message: A hard-coded message to be rendered + * + * Usage: + * //... + * $confirmationFinisher = $this->objectManager->get(ConfirmationFinisher::class); + * $confirmationFinisher->setOptions( + * [ + * 'message' => 'foo', + * ] + * ); + * $formDefinition->addFinisher($confirmationFinisher); + * // ... + * + * Scope: frontend + */ +class ConfirmationFinisher extends AbstractFinisher +{ + + /** + * @var array + */ + protected $defaultOptions = [ + 'message' => 'The form has been submitted.', + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + * @throws FinisherException + */ + protected function executeInternal() + { + $formRuntime = $this->finisherContext->getFormRuntime(); + $message = $this->parseOption('message'); + $formRuntime->getResponse()->setContent($message); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/DeleteUploadsFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/DeleteUploadsFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..43dcd1363e94e86e27afe1a9289c799388c31778 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/DeleteUploadsFinisher.php @@ -0,0 +1,57 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload; + +/** + * This finisher remove the submited files. + * Use this e.g after the email finisher if you dont want + * to keep the files online. + * + * Scope: frontend + */ +class DeleteUploadsFinisher extends AbstractFinisher +{ + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + */ + protected function executeInternal() + { + $formRuntime = $this->finisherContext->getFormRuntime(); + + $elements = $formRuntime->getFormDefinition()->getRenderablesRecursively(); + foreach ($elements as $element) { + if (!$element instanceof FileUpload) { + continue; + } + $file = $formRuntime[$element->getIdentifier()]; + if (!$file) { + continue; + } + + if ($file instanceof FileReference) { + $file = $file->getOriginalResource(); + } + $file->getStorage()->deleteFile($file); + } + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/EmailFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/EmailFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..c2070b49535f51b1fd93b8d95724192a1dc071d8 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/EmailFinisher.php @@ -0,0 +1,187 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Mail\MailMessage; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Fluid\View\StandaloneView; +use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException; +use TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload; +use TYPO3\CMS\Form\Service\TranslationService; + +/** + * This finisher sends an email to one recipient + * + * Options: + * + * - templatePathAndFilename (mandatory): Template path and filename for the mail body + * - layoutRootPath: root path for the layouts + * - partialRootPath: root path for the partials + * - variables: associative array of variables which are available inside the Fluid template + * + * The following options control the mail sending. In all of them, placeholders in the form + * of {...} are replaced with the corresponding form value; i.e. {email} as recipientAddress + * makes the recipient address configurable. + * + * - subject (mandatory): Subject of the email + * - recipientAddress (mandatory): Email address of the recipient + * - recipientName: Human-readable name of the recipient + * - senderAddress (mandatory): Email address of the sender + * - senderName: Human-readable name of the sender + * - replyToAddress: Email address of to be used as reply-to email (use multiple addresses with an array) + * - carbonCopyAddress: Email address of the copy recipient (use multiple addresses with an array) + * - blindCarbonCopyAddress: Email address of the blind copy recipient (use multiple addresses with an array) + * - format: format of the email (one of the FORMAT_* constants). By default mails are sent as HTML + * + * Scope: frontend + */ +class EmailFinisher extends AbstractFinisher +{ + const FORMAT_PLAINTEXT = 'plaintext'; + const FORMAT_HTML = 'html'; + + /** + * @var array + */ + protected $defaultOptions = [ + 'recipientName' => '', + 'senderName' => '', + 'format' => self::FORMAT_HTML, + 'attachUploads' => true + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + * @throws FinisherException + */ + protected function executeInternal() + { + $formRuntime = $this->finisherContext->getFormRuntime(); + $standaloneView = $this->initializeStandaloneView(); + $standaloneView->assign('form', $formRuntime); + + $translationService = TranslationService::getInstance(); + if (isset($this->options['translation']['language']) && !empty($this->options['translation']['language'])) { + $languageBackup = $translationService->getLanguage(); + $translationService->setLanguage($this->options['translation']['language']); + } + $message = $standaloneView->render(); + if (!empty($languageBackup)) { + $translationService->setLanguage($languageBackup); + } + + $subject = $this->parseOption('subject'); + $recipientAddress = $this->parseOption('recipientAddress'); + $recipientName = $this->parseOption('recipientName'); + $senderAddress = $this->parseOption('senderAddress'); + $senderName = $this->parseOption('senderName'); + $replyToAddress = $this->parseOption('replyToAddress'); + $carbonCopyAddress = $this->parseOption('carbonCopyAddress'); + $blindCarbonCopyAddress = $this->parseOption('blindCarbonCopyAddress'); + $format = $this->parseOption('format'); + $attachUploads = $this->parseOption('attachUploads'); + + if (empty($subject)) { + throw new FinisherException('The option "subject" must be set for the EmailFinisher.', 1327060320); + } + if (empty($recipientAddress)) { + throw new FinisherException('The option "recipientAddress" must be set for the EmailFinisher.', 1327060200); + } + if (empty($senderAddress)) { + throw new FinisherException('The option "senderAddress" must be set for the EmailFinisher.', 1327060210); + } + + $mail = $this->objectManager->get(MailMessage::class); + + $mail->setFrom([$senderAddress => $senderName]) + ->setTo([$recipientAddress => $recipientName]) + ->setSubject($subject); + + if (!empty($replyToAddress)) { + $mail->setReplyTo($replyToAddress); + } + + if (!empty($carbonCopyAddress)) { + $mail->setCc($carbonCopyAddress); + } + + if (!empty($blindCarbonCopyAddress)) { + $mail->setBcc($blindCarbonCopyAddress); + } + + if ($format === self::FORMAT_PLAINTEXT) { + $mail->setBody($message, 'text/plain'); + } else { + $mail->setBody($message, 'text/html'); + } + + $elements = $formRuntime->getFormDefinition()->getRenderablesRecursively(); + + if ($attachUploads) { + foreach ($elements as $element) { + if (!$element instanceof FileUpload) { + continue; + } + $file = $formRuntime[$element->getIdentifier()]; + if ($file) { + if ($file instanceof FileReference) { + $file = $file->getOriginalResource(); + } + + $mail->attach(\Swift_Attachment::newInstance($file->getContents(), $file->getName(), $file->getMimeType())); + } + } + } + + $mail->send(); + } + + /** + * @return StandaloneView + * @throws FinisherException + */ + protected function initializeStandaloneView(): StandaloneView + { + if (!isset($this->options['templatePathAndFilename'])) { + throw new FinisherException('The option "templatePathAndFilename" must be set for the EmailFinisher.', 1327058829); + } + + $format = ucfirst($this->parseOption('format')); + + $this->options['templatePathAndFilename'] = strtr($this->options['templatePathAndFilename'], [ + '{@format}' => $format + ]); + + $standaloneView = $this->objectManager->get(StandaloneView::class); + $standaloneView->setTemplatePathAndFilename($this->options['templatePathAndFilename']); + + if (isset($this->options['partialRootPaths']) && is_array($this->options['partialRootPaths'])) { + $standaloneView->setPartialRootPaths($this->options['partialRootPaths']); + } + + if (isset($this->options['layoutRootPaths']) && is_array($this->options['layoutRootPaths'])) { + $standaloneView->setLayoutRootPaths($this->options['layoutRootPaths']); + } + + if (isset($this->options['variables'])) { + $standaloneView->assignMultiple($this->options['variables']); + } + return $standaloneView; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/Exception/FinisherException.php b/typo3/sysext/form/Classes/Domain/Finishers/Exception/FinisherException.php new file mode 100644 index 0000000000000000000000000000000000000000..7464f2181088a720c85a035a5ad2fdcf5e0c95ac --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/Exception/FinisherException.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This exception is thrown in Form Finishers + * + * @api + */ +class FinisherException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/FinisherContext.php b/typo3/sysext/form/Classes/Domain/Finishers/FinisherContext.php new file mode 100644 index 0000000000000000000000000000000000000000..80a40fb0e961fcbcb6177dc7647a34ac37f88461 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/FinisherContext.php @@ -0,0 +1,115 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * The context that is passed to each finisher when executed. + * It acts like an EventObject that is able to stop propagation. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +class FinisherContext +{ + + /** + * If TRUE further finishers won't be invoked + * + * @var bool + */ + protected $cancelled = false; + + /** + * A reference to the Form Runtime that the finisher belongs to + * + * @var \TYPO3\CMS\Form\Domain\Runtime\FormRuntime + */ + protected $formRuntime; + + /** + * The assigned controller context which might be needed by the finisher. + * + * @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext + */ + protected $controllerContext; + + /** + * @param FormRuntime $formRuntime + * @internal + */ + public function __construct(FormRuntime $formRuntime, ControllerContext $controllerContext) + { + $this->formRuntime = $formRuntime; + $this->controllerContext = $controllerContext; + } + + /** + * Cancels the finisher invocation after the current finisher + * + * @return void + * @api + */ + public function cancel() + { + $this->cancelled = true; + } + + /** + * TRUE if no futher finishers should be invoked. Defaults to FALSE + * + * @return bool + * @internal + */ + public function isCancelled(): bool + { + return $this->cancelled; + } + + /** + * The Form Runtime that is associated with the current finisher + * + * @return FormRuntime + * @api + */ + public function getFormRuntime(): FormRuntime + { + return $this->formRuntime; + } + + /** + * The values of the submitted form (after validation and property mapping) + * + * @return array + * @api + */ + public function getFormValues(): array + { + return $this->formRuntime->getFormState()->getFormValues(); + } + + /** + * @return ControllerContext + * @api + */ + public function getControllerContext(): ControllerContext + { + return $this->controllerContext; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/FinisherInterface.php b/typo3/sysext/form/Classes/Domain/Finishers/FinisherInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c5c9683973a088da889213ae8321bbc33d958331 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/FinisherInterface.php @@ -0,0 +1,52 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Finisher that can be attached to a form in order to be invoked + * as soon as the complete form is submitted + * + * Scope: frontend + */ +interface FinisherInterface +{ + + /** + * Executes the finisher + * + * @param FinisherContext $finisherContext The Finisher context that contains the current Form Runtime and Response + * @return void + * @api + */ + public function execute(FinisherContext $finisherContext); + + /** + * @param array $options configuration options in the format ['option1' => 'value1', 'option2' => 'value2', ...] + * @return void + * @api + */ + public function setOptions(array $options); + + /** + * Sets a single finisher option (@see setOptions()) + * + * @param string $optionName name of the option to be set + * @param mixed $optionValue value of the option + * @return void + * @api + */ + public function setOption(string $optionName, $optionValue); +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/FlashMessageFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/FlashMessageFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..5856a0988fa03cf5ec302041b45cdc62ffce02e1 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/FlashMessageFinisher.php @@ -0,0 +1,97 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Messaging\AbstractMessage; +use TYPO3\CMS\Core\Messaging\FlashMessage; +use TYPO3\CMS\Extbase\Error\Error; +use TYPO3\CMS\Extbase\Error\Message; +use TYPO3\CMS\Extbase\Error\Notice; +use TYPO3\CMS\Extbase\Error\Warning; +use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException; + +/** + * A simple finisher that adds a message to the FlashMessageContainer + * + * Usage: + * //... + * $flashMessageFinisher = $this->objectManager->get(FlashMessageFinisher::class); + * $flashMessageFinisher->setOptions( + * [ + * 'messageBody' => 'Some message body', + * 'messageTitle' => 'Some message title', + * 'messageArguments' => ['foo' => 'bar'], + * 'severity' => \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR + * ] + * ); + * $formDefinition->addFinisher($flashMessageFinisher); + * // ... + * + * Scope: frontend + */ +class FlashMessageFinisher extends AbstractFinisher +{ + + /** + * @var array + */ + protected $defaultOptions = [ + 'messageBody' => null, + 'messageTitle' => '', + 'messageArguments' => [], + 'messageCode' => null, + 'severity' => AbstractMessage::OK, + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + * @throws FinisherException + */ + protected function executeInternal() + { + $messageBody = $this->parseOption('messageBody'); + if (!is_string($messageBody)) { + throw new FinisherException(sprintf('The message body must be of type string, "%s" given.', gettype($messageBody)), 1335980069); + } + $messageTitle = $this->parseOption('messageTitle'); + $messageArguments = $this->parseOption('messageArguments'); + $messageCode = $this->parseOption('messageCode'); + $severity = $this->parseOption('severity'); + switch ($severity) { + case AbstractMessage::NOTICE: + $message = $this->objectManager->get(Notice::class, $messageBody, $messageCode, $messageArguments, $messageTitle); + break; + case AbstractMessage::WARNING: + $message = $this->objectManager->get(Warning::class, $messageBody, $messageCode, $messageArguments, $messageTitle); + break; + case AbstractMessage::ERROR: + $message = $this->objectManager->get(Error::class, $messageBody, $messageCode, $messageArguments, $messageTitle); + break; + default: + $message = $this->objectManager->get(Message::class, $messageBody, $messageCode, $messageArguments, $messageTitle); + break; + } + + $flashMessage = $this->objectManager->get(FlashMessage::class, + $message->render(), $message->getTitle(), $severity, true + ); + + $this->finisherContext->getControllerContext()->getFlashMessageQueue()->addMessage($flashMessage); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/RedirectFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/RedirectFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..0d20268f11b5b1890172b9d1c319c5f4bb17f0d8 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/RedirectFinisher.php @@ -0,0 +1,151 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; +use TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException; +use TYPO3\CMS\Extbase\Mvc\Web\Request; +use TYPO3\CMS\Extbase\Mvc\Web\Response; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; + +/** + * This finisher redirects to another Controller. + * + * Scope: frontend + */ +class RedirectFinisher extends AbstractFinisher +{ + + /** + * @var array + */ + protected $defaultOptions = [ + 'pageUid' => 1, + 'additionalParameters' => '', + 'delay' => 0, + 'statusCode' => 303, + ]; + + /** + * @var \TYPO3\CMS\Extbase\Mvc\Web\Request + */ + protected $request; + + /** + * @var \TYPO3\CMS\Extbase\Mvc\Web\Response + */ + protected $response; + + /** + * @var \TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder + */ + protected $uriBuilder; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + */ + protected function executeInternal() + { + $formRuntime = $this->finisherContext->getFormRuntime(); + $this->request = $formRuntime->getRequest(); + $this->response = $formRuntime->getResponse(); + $this->uriBuilder = $this->objectManager->get(UriBuilder::class); + $this->uriBuilder->setRequest($this->request); + + $pageUid = (int)str_replace('pages_', '', $this->parseOption('pageUid')); + $additionalParameters = $this->parseOption('additionalParameters'); + $additionalParameters = '&' . ltrim($additionalParameters, '&'); + $delay = (int)$this->parseOption('delay'); + $statusCode = (int)$this->parseOption('statusCode'); + + $this->finisherContext->cancel(); + $this->redirect($pageUid, $additionalParameters, $delay, $statusCode); + } + + /** + * Redirects the request to another page. + * + * Redirect will be sent to the client which then performs another request to the new URI. + * + * NOTE: This method only supports web requests and will thrown an exception + * if used with other request types. + * + * @param int $pageUid Target page uid. If NULL, the current page uid is used + * @param string $additionalParameters + * @param int $delay (optional) The delay in seconds. Default is no delay. + * @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other + * @return void + * @throws UnsupportedRequestTypeException If the request is not a web request + * @see forward() + */ + protected function redirect(int $pageUid = 1, string $additionalParameters = '', int $delay = 0, int $statusCode = 303) + { + if (!$this->request instanceof Request) { + throw new UnsupportedRequestTypeException('redirect() only supports web requests.', 1471776457); + } + + $typolinkConfiguration = [ + 'parameter' => $pageUid, + 'additionalParams' => $additionalParameters, + ]; + $redirectUri = $this->getTypoScriptFrontendController()->cObj->typoLink_URL($typolinkConfiguration); + $this->redirectToUri($redirectUri, $delay, $statusCode); + } + + /** + * Redirects the web request to another uri. + * + * NOTE: This method only supports web requests and will thrown an exception if used with other request types. + * + * @param string $uri A string representation of a URI + * @param int $delay (optional) The delay in seconds. Default is no delay. + * @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other + * @throws UnsupportedRequestTypeException If the request is not a web request + * @throws StopActionException + */ + protected function redirectToUri(string $uri, int $delay = 0, int $statusCode = 303) + { + if (!$this->request instanceof Request) { + throw new UnsupportedRequestTypeException('redirect() only supports web requests.', 1471776458); + } + + $uri = $this->addBaseUriIfNecessary($uri); + $escapedUri = htmlentities($uri, ENT_QUOTES, 'utf-8'); + + $this->response->setContent('<html><head><meta http-equiv="refresh" content="' . (int)$delay . ';url=' . $escapedUri . '"/></head></html>'); + if ($this->response instanceof \TYPO3\CMS\Extbase\Mvc\Web\Response) { + $this->response->setStatus($statusCode); + $this->response->setHeader('Location', (string)$uri); + } + echo $this->response->shutdown(); + throw new StopActionException('redirectToUri', 1477070964); + } + + /** + * Adds the base uri if not already in place. + * + * @param string $uri The URI + * @return string + */ + protected function addBaseUriIfNecessary(string $uri): string + { + return GeneralUtility::locationHeaderUrl((string)$uri); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php b/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php new file mode 100644 index 0000000000000000000000000000000000000000..bb7eb27a7f16bfeb3d93b26d9edc03fba5621ba8 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Finishers/SaveToDatabaseFinisher.php @@ -0,0 +1,100 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Finishers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Form\Domain\Finishers\Exception\FinisherException; +use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface; + +/** + * This finisher saves the data from a submitted form into + * a database table. + * + * Scope: frontend + */ +class SaveToDatabaseFinisher extends AbstractFinisher +{ + + /** + * @var array + */ + protected $defaultOptions = [ + 'table' => null, + 'elements' => [], + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @return void + * @throws FinisherException + */ + protected function executeInternal() + { + $table = $this->parseOption('table'); + $elementsConfiguration = $this->parseOption('elements'); + + $databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table); + $schemaManager = $databaseConnection->getSchemaManager(); + + if ($schemaManager->tablesExist([$table]) === false) { + throw new FinisherException('The table "' . $table . '" does not exist.', 1476362091); + } + + $databaseColumns = $schemaManager->listTableColumns($table); + foreach ($elementsConfiguration as $elementIdentifier => $elementConfiguration) { + if (!array_key_exists($elementConfiguration['mapOnDatabaseColumn'], $databaseColumns)) { + throw new FinisherException('The column "' . $elementConfiguration['mapOnDatabaseColumn'] . '" does not exist in table "' . $table . '".', 1476362572); + } + } + + $formRuntime = $this->finisherContext->getFormRuntime(); + + $insertData = []; + foreach ($this->finisherContext->getFormValues() as $elementIdentifier => $elementValue) { + $element = $formRuntime->getFormDefinition()->getElementByIdentifier($elementIdentifier); + if ( + !$element instanceof FormElementInterface + || !isset($elementsConfiguration[$elementIdentifier]) + || !isset($elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']) + ) { + continue; + } + + if ($elementValue instanceof FileReference) { + if (isset($elementsConfiguration[$elementIdentifier]['saveFileIdentifierInsteadOfUid'])) { + $saveFileIdentifierInsteadOfUid = (bool)$elementsConfiguration[$elementIdentifier]['saveFileIdentifierInsteadOfUid']; + } else { + $saveFileIdentifierInsteadOfUid = false; + } + + if ($saveFileIdentifierInsteadOfUid) { + $elementValue = $elementValue->getOriginalResource()->getCombinedIdentifier(); + } else { + $elementValue = $elementValue->getOriginalResource()->getProperty('uid_local'); + } + } + $insertData[$elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']] = $elementValue; + } + + if (!empty($insertData)) { + $databaseConnection->insert($table, $insertData); + } + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Configuration.php b/typo3/sysext/form/Classes/Domain/Model/Configuration.php deleted file mode 100644 index f923ab8e35fca8bb51ee4544c3c28d442f954016..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Configuration.php +++ /dev/null @@ -1,174 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * The Configuration model is a high-level API - * for the underlying TypoScript configuration. - */ -class Configuration -{ - /** - * @var string - */ - const DISABLE_CONTENT_ELEMENT_RENDERING = 'disableContentElement'; - - /** - * @var string - */ - const DEFAULT_THEME_NAME = 'Default'; - - /** - * @return Configuration - */ - public static function create() - { - return \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(self::class); - } - - /** - * @var array - */ - protected $typoScript = []; - - /** - * @var bool - */ - protected $contentElementRendering = false; - - /** - * @var string - */ - protected $prefix = 'form'; - - /** - * @var string - */ - protected $themeName = ''; - - /** - * @var \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository - */ - protected $typoScriptRepository; - - /** - * @param \TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository - * @return void - */ - public function injectTypoScriptRepository(\TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository $typoScriptRepository) - { - $this->typoScriptRepository = $typoScriptRepository; - } - - /** - * @return array - */ - public function getTypoScript() - { - return $this->typoScript; - } - - /** - * @param array $typoScript - * @return Configuration - */ - public function setTypoScript(array $typoScript) - { - $this->typoScript = $typoScript; - $this->update(); - return $this; - } - - public function getContentElementRendering() - { - return $this->contentElementRendering; - } - - /** - * @param $contentElementRendering - * @return Configuration - */ - public function setContentElementRendering($contentElementRendering) - { - $this->contentElementRendering = (bool)$contentElementRendering; - return $this; - } - - /** - * @return string - */ - public function getPrefix() - { - return $this->prefix; - } - - /** - * @param string $prefix - * @return Configuration - */ - public function setPrefix($prefix) - { - $this->prefix = (string)$prefix; - return $this; - } - - /** - * @return string - */ - public function getThemeName() - { - return $this->themeName; - } - - /** - * @param string $themeName - * @return Configuration - */ - public function setThemeName($themeName = '') - { - if ($themeName === '') { - $themeName = static::DEFAULT_THEME_NAME; - } - $this->themeName = $themeName; - return $this; - } - - /** - * Updates the local properties - called after - * new TypoScript has been assigned in this object. - */ - protected function update() - { - // Determine content rendering mode. If activated, cObject and stdWrap can be - // used to execute various processes that must not be allowed on TypoScript - // that has been created by non-privileged backend users (= insecure TypoScript) - $this->setContentElementRendering( - empty($this->typoScript[static::DISABLE_CONTENT_ELEMENT_RENDERING]) - ); - // Determine the HTML form element prefix to distinguish - // different form components on the same page in the frontend - if (!empty($this->typoScript['prefix'])) { - $this->setPrefix($this->typoScript['prefix']); - } - // Set the theme name - if (!empty($this->typoScript['themeName'])) { - $this->setThemeName($this->typoScript['themeName']); - } elseif (!empty($this->typoScriptRepository->getModelConfigurationByScope('FORM', 'themeName'))) { - $this->setThemeName($this->typoScriptRepository->getModelConfigurationByScope('FORM', 'themeName')); - } else { - $this->setThemeName(static::DEFAULT_THEME_NAME); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Content.php b/typo3/sysext/form/Classes/Domain/Model/Content.php deleted file mode 100644 index c171aa4664f30ae82d5db58cb505390151e76909..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Content.php +++ /dev/null @@ -1,133 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Content domain model - */ -class Content -{ - /** - * The uid - * - * @var int - */ - protected $uid = 0; - - /** - * The page id - * - * @var int - */ - protected $pageId = 0; - - /** - * The configuration Typoscript - * - * @var array - */ - protected $typoscript = []; - - /** - * The plain bodytext - * - * @var string - */ - protected $bodytext = ''; - - /** - * Sets the uid - * - * @param int $uid The uid - * @return void - */ - public function setUid($uid) - { - $this->uid = (int)$uid; - } - - /** - * Returns the uid - * - * @return int The uid - */ - public function getUid() - { - return $this->uid; - } - - /** - * Sets the page id - * - * @param int $pageId The page id - * @return void - */ - public function setPageId($pageId) - { - $this->pageId = (int)$pageId; - } - - /** - * Returns the page id - * - * @return int The page id - */ - public function getPageId() - { - return $this->pageId; - } - - /** - * Sets the Typoscript configuration - * - * @param array $typoscript The Typoscript configuration - * @return void - */ - public function setTyposcript(array $typoscript) - { - $this->typoscript = (array)$typoscript; - } - - /** - * Returns the Typoscript configuration - * - * @return array The Typoscript configuration - */ - public function getTyposcript() - { - return $this->typoscript; - } - - /** - * Sets the bodytext - * - * @param string $bodytext The bodytext - * @return void - */ - public function setBodytext($bodytext = '') - { - $this->bodytext = $bodytext; - } - - /** - * Returns the bodytext - * - * @return string The bodytext - */ - public function getBodytext() - { - return $this->bodytext; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Element.php b/typo3/sysext/form/Classes/Domain/Model/Element.php deleted file mode 100644 index 6f2941ed7430e26db67204f89aadd80a9541186f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Element.php +++ /dev/null @@ -1,485 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; -use TYPO3\CMS\Extbase\Persistence\ObjectStorage; - -/** - * The Element Domain Model represents the high-level - * view on the user submitted data using a nested hierarchy. - */ -class Element extends AbstractEntity -{ - /** - * This array holds all the additional arguments to use it in the template - * - * @var array - */ - protected $additionalArguments; - - /** - * child elements - * - * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Form\Domain\Model\Element> - */ - protected $childElements; - - /** - * A global counter over all elements - * - * @var int - */ - protected $elementCounter; - - /** - * The element type (e.g BUTTON) - * - * @var string - */ - protected $elementType; - - /** - * The validation error messages - * - * @var array - */ - protected $validationErrorMessages; - - /** - * This array holds all the element html attributes with their values - * - * @var array - */ - protected $htmlAttributes; - - /** - * The id attribute - * - * @var string - */ - protected $id; - - /** - * The mandatory validation messages - * - * @var array - */ - protected $mandatoryValidationMessages; - - /** - * The name attribute - * - * @var string - */ - protected $name; - - /** - * parent element - * - * @var \TYPO3\CMS\Form\Domain\Model\Element - */ - protected $parentElement; - - /** - * The fluid partial for the element - * - * @var string - */ - protected $partialPath; - - /** - * TRUE if the element should be displayed - * - * @var bool - */ - protected $showElement; - - /** - * The theme name - * - * @var string - */ - protected $themeName; - - /** - * Creates an instance. - */ - public function __construct() - { - $this->initStorageObjects(); - } - - /** - * Initializes all ObjectStorage properties. - * - * @return void - */ - protected function initStorageObjects() - { - $this->childElements = new ObjectStorage(); - } - - /** - * Return a array with all the additional arguments to use it in the template - * - * @return array - */ - public function getAdditionalArguments() - { - return $this->additionalArguments; - } - - /** - * Sets a array with all the additional arguments to use it in the template - * - * @param array $additionalArguments - * @return void - */ - public function setAdditionalArguments($additionalArguments = []) - { - $this->additionalArguments = $additionalArguments; - } - - /** - * Get a single attribute value - * - * @param string $key - * @return array - */ - public function getAdditionalArgument($key = '') - { - return $this->additionalArguments[$key]; - } - - /** - * Set a single attribute and value - * - * @param string $key - * @param mixed $value - * @return array - */ - public function setAdditionalArgument($key = '', $value = null) - { - $this->additionalArguments[$key] = $value; - } - - /** - * Adds a child element - * - * @param \TYPO3\CMS\Form\Domain\Model\Element $element - * @return void - */ - public function addChildElement(Element $element) - { - $this->childElements->attach($element); - } - - /** - * Returns the child elements - * - * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Form\Domain\Model\Element> $element - */ - public function getChildElements() - { - return $this->childElements; - } - - /** - * Sets the child elements - * - * @param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Form\Domain\Model\Element> $childElements - * @return void - */ - public function setChildElements(ObjectStorage $childElements) - { - $this->childElements = $childElements; - } - - /** - * Returns the element counter - * - * @return int - */ - public function getElementCounter() - { - return $this->elementCounter; - } - - /** - * Sets the element counter - * - * @param int $elementCounter - * @return void - */ - public function setElementCounter($elementCounter = 0) - { - $this->elementCounter = $elementCounter; - } - - /** - * Returns the element type - * - * @return string - */ - public function getElementType() - { - return $this->elementType; - } - - /** - * Returns the element type in lower case - * - * @return string - */ - public function getElementTypeLowerCase() - { - return strtolower($this->elementType); - } - - /** - * Sets the parent element - * - * @param string $elementType - * @return void - */ - public function setElementType($elementType) - { - $this->elementType = (string)$elementType; - } - - /** - * Returns the validation error messages - * - * @return array - */ - public function getValidationErrorMessages() - { - return $this->validationErrorMessages; - } - - /** - * Sets the validation error messages - * - * @param array $validationErrorMessages - * @return void - */ - public function setValidationErrorMessages(array $validationErrorMessages) - { - $this->validationErrorMessages = $validationErrorMessages; - } - - /** - * Returns the element html attributes and values - * - * @return array - */ - public function getHtmlAttributes() - { - return $this->htmlAttributes; - } - - /** - * Sets the element html attributes and values - * - * @param array $htmlAttributes - * @return void - */ - public function setHtmlAttributes($htmlAttributes = []) - { - $this->htmlAttributes = $htmlAttributes; - } - - /** - * Remove a single html attribute - * - * @param string $key - * @return void - */ - public function removeHtmlAttribute($key = '') - { - unset($this->htmlAttributes[$key]); - } - - /** - * Get a single html attribute value - * - * @param string $key - * @return array - */ - public function getHtmlAttribute($key = '') - { - return $this->htmlAttributes[$key]; - } - - /** - * Set a single html attribute and value - * - * @param string $key - * @param mixed $value - * @return array - */ - public function setHtmlAttribute($key = '', $value = null) - { - $this->htmlAttributes[$key] = $value; - } - - /** - * Returns the id attribute - * - * @return string - */ - public function getId() - { - return $this->id; - } - - /** - * Sets the id attribute - * - * @param string $id - * @return void - */ - public function setId($id) - { - $this->id = (string)$id; - } - - /** - * Returns the mandatory validation messages - * - * @return array - */ - public function getMandatoryValidationMessages() - { - return $this->mandatoryValidationMessages; - } - - /** - * Sets the mandatory validation messages - * - * @param array $mandatoryValidationMessages - * @return void - */ - public function setMandatoryValidationMessages(array $mandatoryValidationMessages) - { - $this->mandatoryValidationMessages = $mandatoryValidationMessages; - } - - /** - * Returns the name attribute - * - * @return string - */ - public function getName() - { - return $this->name; - } - - /** - * Sets the name attribute - * - * @param string $name - * @return void - */ - public function setName($name) - { - $this->name = (string)$name; - } - - /** - * Returns the parent element - * - * @return Element - */ - public function getParentElement() - { - return $this->parentElement; - } - - /** - * Sets the parent element - * - * @param \TYPO3\CMS\Form\Domain\Model\Element - * @return void - */ - public function setParentElement(Element $parentElement) - { - $this->parentElement = $parentElement; - } - - /** - * Returns the fluid partial path for the element - * - * @return string - */ - public function getPartialPath() - { - return $this->partialPath; - } - - /** - * Sets the fluid partial path for the element - * - * @param string $partialPath - * @return void - */ - public function setPartialPath($partialPath) - { - $this->partialPath = (string)$partialPath; - } - - /** - * Returns TRUE if the element should be displayed - * - * @return bool - */ - public function getShowElement() - { - return $this->showElement; - } - - /** - * TRUE if the element should be displayed - * - * @param bool $showElement - * @return void - */ - public function setShowElement($showElement = false) - { - $this->showElement = $showElement; - } - - /** - * Set the theme name - * - * @param string - * @return $themeName - */ - public function setThemeName($themeName = 'Default') - { - $this->themeName = $themeName; - } - - /** - * Returns the theme name - * - * @return string - */ - public function getThemeName() - { - return $this->themeName; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Exception.php b/typo3/sysext/form/Classes/Domain/Model/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..5704857b747801855500ece2616df12dd1ba60fb --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Exception.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception as DomainException; + +/** + * A generic Form model Exception + * + * @api + */ +class Exception extends DomainException +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Exception/DuplicateFormElementException.php b/typo3/sysext/form/Classes/Domain/Model/Exception/DuplicateFormElementException.php new file mode 100644 index 0000000000000000000000000000000000000000..83f718abf26e3e39a26bc06042e6cb8103d1c66d --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Exception/DuplicateFormElementException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\Exception; + +/** + * This exception is thrown if two Form Elements with the same Identifier are added + * to a form. + * + * @api + */ +class DuplicateFormElementException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Exception/FinisherPresetNotFoundException.php b/typo3/sysext/form/Classes/Domain/Model/Exception/FinisherPresetNotFoundException.php new file mode 100644 index 0000000000000000000000000000000000000000..5200d0e0cb81d52dfec1e3eb61c27c632740d5d3 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Exception/FinisherPresetNotFoundException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\Exception; + +/** + * This exception is thrown if a Finisher Preset was not found, + * or if the implementationClassName was not set. + * + * @api + */ +class FinisherPresetNotFoundException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Exception/FormDefinitionConsistencyException.php b/typo3/sysext/form/Classes/Domain/Model/Exception/FormDefinitionConsistencyException.php new file mode 100644 index 0000000000000000000000000000000000000000..d04d41cd272be89901c76b6ab488f37bf8d022ed --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Exception/FormDefinitionConsistencyException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\Exception; + +/** + * This exception is thrown if the form definition would get an inconsistent state, like + * adding a page to two different forms + * + * @api + */ +class FormDefinitionConsistencyException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Exception/ValidatorPresetNotFoundException.php b/typo3/sysext/form/Classes/Domain/Model/Exception/ValidatorPresetNotFoundException.php new file mode 100644 index 0000000000000000000000000000000000000000..cfacf8e2e38313d61cdf00fc8397babf1d470667 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Exception/ValidatorPresetNotFoundException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\Exception; + +/** + * This exception is thrown if a Validator Preset was not found, + * or if the implementationClassName was not set. + * + * @api + */ +class ValidatorPresetNotFoundException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormDefinition.php b/typo3/sysext/form/Classes/Domain/Model/FormDefinition.php new file mode 100644 index 0000000000000000000000000000000000000000..d619d70c47e65e0e22cc517597cd6b9af79d72e7 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormDefinition.php @@ -0,0 +1,695 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility as CoreArrayUtility; +use TYPO3\CMS\Extbase\Mvc\Web\Request; +use TYPO3\CMS\Extbase\Mvc\Web\Response; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Reflection\ObjectAccess; +use TYPO3\CMS\Extbase\Utility\ArrayUtility; +use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException; +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotFoundException; +use TYPO3\CMS\Form\Domain\Finishers\FinisherInterface; +use TYPO3\CMS\Form\Domain\Model\Exception\DuplicateFormElementException; +use TYPO3\CMS\Form\Domain\Model\Exception\FinisherPresetNotFoundException; +use TYPO3\CMS\Form\Domain\Model\Exception\FormDefinitionConsistencyException; +use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface; +use TYPO3\CMS\Form\Domain\Model\FormElements\Page; +use TYPO3\CMS\Form\Domain\Model\Renderable\AbstractCompositeRenderable; +use TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; +use TYPO3\CMS\Form\Exception as FormException; +use TYPO3\CMS\Form\Mvc\ProcessingRule; +use TYPO3\CMS\Form\Utility\ArrayUtility as FormArrayUtility; + +/** + * This class encapsulates a complete *Form Definition*, with all of its pages, + * form elements, validation rules which apply and finishers which should be + * executed when the form is completely filled in. + * + * It is *not modified* when the form executes. + * + * The Anatomy Of A Form + * ===================== + * + * A FormDefinition consists of multiple *Page* ({@link Page}) objects. When a + * form is displayed to the user, only one *Page* is visible at any given time, + * and there is a navigation to go back and forth between the pages. + * + * A *Page* consists of multiple *FormElements* ({@link FormElementInterface}, {@link AbstractFormElement}), + * which represent the input fields, textareas, checkboxes shown inside the page. + * + * *FormDefinition*, *Page* and *FormElement* have *identifier* properties, which + * must be unique for each given type (i.e. it is allowed that the FormDefinition and + * a FormElement have the *same* identifier, but two FormElements are not allowed to + * have the same identifier. + * + * Simple Example + * -------------- + * + * Generally, you can create a FormDefinition manually by just calling the API + * methods on it, or you use a *Form Definition Factory* to build the form from + * another representation format such as YAML. + * + * /---code php + * $formDefinition = $this->objectManager->get(FormDefinition::class, 'myForm'); + * + * $page1 = $this->objectManager->get(Page::class, 'page1'); + * $formDefinition->addPage($page); + * + * $element1 = $this->objectManager->get(GenericFormElement::class, 'title', 'Textfield'); # the second argument is the type of the form element + * $page1->addElement($element1); + * \--- + * + * Creating a Form, Using Abstract Form Element Types + * ===================================================== + * + * While you can use the {@link FormDefinition::addPage} or {@link Page::addElement} + * methods and create the Page and FormElement objects manually, it is often better + * to use the corresponding create* methods ({@link FormDefinition::createPage} + * and {@link Page::createElement}), as you pass them an abstract *Form Element Type* + * such as *Text* or *Page*, and the system **automatically + * resolves the implementation class name and sets default values**. + * + * So the simple example from above should be rewritten as follows: + * + * /---code php + * $prototypeConfiguration = []; // We'll talk about this later + * + * $formDefinition = $this->objectManager->get(FormDefinition::class, 'myForm', $prototypeConfiguration); + * $page1 = $formDefinition->createPage('page1'); + * $element1 = $page1->addElement('title', 'Textfield'); + * \--- + * + * Now, you might wonder how the system knows that the element *Textfield* + * is implemented using a GenericFormElement: **This is configured in the $prototypeConfiguration**. + * + * To make the example from above actually work, we need to add some sensible + * values to *$prototypeConfiguration*: + * + * <pre> + * $prototypeConfiguration = [ + * 'formElementsDefinition' => [ + * 'Page' => [ + * 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page' + * ], + * 'Textfield' => [ + * 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement' + * ] + * ] + * ] + * </pre> + * + * For each abstract *Form Element Type* we add some configuration; in the above + * case only the *implementation class name*. Still, it is possible to set defaults + * for *all* configuration options of such an element, as the following example + * shows: + * + * <pre> + * $prototypeConfiguration = [ + * 'formElementsDefinition' => [ + * 'Page' => [ + * 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page', + * 'label' => 'this is the label of the page if nothing is specified' + * ], + * 'Textfield' => [ + * 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement', + * 'label' = >'Default Label', + * 'defaultValue' => 'Default form element value', + * 'properties' => [ + * 'placeholder' => 'Text which is shown if element is empty' + * ] + * ] + * ] + * ] + * </pre> + * + * Using Preconfigured $prototypeConfiguration + * --------------------------------- + * + * Often, it is not really useful to manually create the $prototypeConfiguration array. + * + * Most of it comes pre-configured inside the extensions's yaml settings, + * and the {@link \TYPO3\CMS\Form\Domain\Configuration\ConfigurationService} contains helper methods + * which return the ready-to-use *$prototypeConfiguration*. + * + * Property Mapping and Validation Rules + * ===================================== + * + * Besides Pages and FormElements, the FormDefinition can contain information + * about the *format of the data* which is inputted into the form. This generally means: + * + * - expected Data Types + * - Property Mapping Configuration to be used + * - Validation Rules which should apply + * + * Background Info + * --------------- + * You might wonder why Data Types and Validation Rules are *not attached + * to each FormElement itself*. + * + * If the form should create a *hierarchical output structure* such as a multi- + * dimensional array or a PHP object, your expected data structure might look as follows: + * <pre> + * - person + * -- firstName + * -- lastName + * -- address + * --- street + * --- city + * </pre> + * + * Now, let's imagine you want to edit *person.address.street* and *person.address.city*, + * but want to validate that the *combination* of *street* and *city* is valid + * according to some address database. + * + * In this case, the form elements would be configured to fill *street* and *city*, + * but the *validator* needs to be attached to the *compound object* *address*, + * as both parts need to be validated together. + * + * Connecting FormElements to the output data structure + * ==================================================== + * + * The *identifier* of the *FormElement* is most important, as it determines + * where in the output structure the value which is entered by the user is placed, + * and thus also determines which validation rules need to apply. + * + * Using the above example, if you want to create a FormElement for the *street*, + * you should use the identifier *person.address.street*. + * + * Rendering a FormDefinition + * ========================== + * + * In order to trigger *rendering* on a FormDefinition, + * the current {@link \TYPO3\CMS\Extbase\Mvc\Web\Request} needs to be bound to the FormDefinition, + * resulting in a {@link \TYPO3\CMS\Form\Domain\Runtime\FormRuntime} object which contains the *Runtime State* of the form + * (such as the currently inserted values). + * + * /---code php + * # $currentRequest and $currentResponse need to be available, f.e. inside a controller you would + * # use $this->request and $this->response; inside a ViewHelper you would use $this->controllerContext->getRequest() + * # and $this->controllerContext->getResponse() + * $form = $formDefinition->bind($currentRequest, $currentResponse); + * + * # now, you can use the $form object to get information about the currently + * # entered values into the form, etc. + * \--- + * + * Refer to the {@link \TYPO3\CMS\Form\Domain\Runtime\FormRuntime} API doc for further information. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +class FormDefinition extends AbstractCompositeRenderable +{ + + /** + * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface + */ + protected $objectManager; + + /** + * The finishers for this form + * + * @var \TYPO3\CMS\Form\Domain\Finishers\FinisherInterface[] + */ + protected $finishers = []; + + /** + * Property Mapping Rules, indexed by element identifier + * + * @var \TYPO3\CMS\Form\Mvc\ProcessingRule[] + */ + protected $processingRules = []; + + /** + * Contains all elements of the form, indexed by identifier. + * Is used as internal cache as we need this really often. + * + * @var \TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface[] + */ + protected $elementsByIdentifier = []; + + /** + * Form element default values in the format ['elementIdentifier' => 'default value'] + * + * @var array + */ + protected $elementDefaultValues = []; + + /** + * @var array + */ + protected $typeDefinitions; + + /** + * @var array + */ + protected $validatorsDefinition; + + /** + * @var array + */ + protected $finishersDefinition; + + /** + * The persistence identifier of the form + * + * @var string + */ + protected $persistenceIdentifier = null; + + /** + * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager + * @internal + */ + public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Constructor. Creates a new FormDefinition with the given identifier. + * + * @param string $identifier The Form Definition's identifier, must be a non-empty string. + * @param array $prototypeConfiguration overrides form defaults of this definition + * @param string $type element type of this form + * @param string $persistenceIdentifier the persistence identifier of the form + * @throws IdentifierNotValidException if the identifier was not valid + * @api + */ + public function __construct( + string $identifier, + array $prototypeConfiguration = [], + string $type = 'Form', + string $persistenceIdentifier = null + ) { + $this->typeDefinitions = isset($prototypeConfiguration['formElementsDefinition']) ? $prototypeConfiguration['formElementsDefinition'] : []; + $this->validatorsDefinition = isset($prototypeConfiguration['validatorsDefinition']) ? $prototypeConfiguration['validatorsDefinition'] : []; + $this->finishersDefinition = isset($prototypeConfiguration['finishersDefinition']) ? $prototypeConfiguration['finishersDefinition'] : []; + + if (!is_string($identifier) || strlen($identifier) === 0) { + throw new IdentifierNotValidException('The given identifier was not a string or the string was empty.', 1477082503); + } + + $this->identifier = $identifier; + $this->type = $type; + $this->persistenceIdentifier = $persistenceIdentifier; + + if ($prototypeConfiguration !== []) { + $this->initializeFromFormDefaults(); + } + } + + /** + * Initialize the form defaults of the current type + * + * @return void + * @throws TypeDefinitionNotFoundException + * @internal + */ + protected function initializeFromFormDefaults() + { + if (!isset($this->typeDefinitions[$this->type])) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $this->type), 1474905835); + } + $typeDefinition = $this->typeDefinitions[$this->type]; + $this->setOptions($typeDefinition); + } + + /** + * Set multiple properties of this object at once. + * Every property which has a corresponding set* method can be set using + * the passed $options array. + * + * @param array $options + * @return void + * @internal + */ + public function setOptions(array $options) + { + if (isset($options['rendererClassName'])) { + $this->setRendererClassName($options['rendererClassName']); + } + if (isset($options['renderingOptions'])) { + foreach ($options['renderingOptions'] as $key => $value) { + if (is_array($value)) { + $currentValue = isset($this->getRenderingOptions()[$key]) ? $this->getRenderingOptions()[$key] : []; + CoreArrayUtility::mergeRecursiveWithOverrule($currentValue, $value); + $this->setRenderingOption($key, $currentValue); + } else { + $this->setRenderingOption($key, $value); + } + } + } + if (isset($options['finishers'])) { + foreach ($options['finishers'] as $finisherConfiguration) { + $this->createFinisher($finisherConfiguration['identifier'], isset($finisherConfiguration['options']) ? $finisherConfiguration['options'] : []); + } + } + + FormArrayUtility::assertAllArrayKeysAreValid($options, ['rendererClassName', 'renderingOptions', 'finishers', 'formEditor']); + } + + /** + * Create a page with the given $identifier and attach this page to the form. + * + * - Create Page object based on the given $typeName + * - set defaults inside the Page object + * - attach Page object to this form + * - return the newly created Page object + * + * @param string $identifier Identifier of the new page + * @param string $typeName Type of the new page + * @return Page the newly created page + * @throws TypeDefinitionNotFoundException + * @api + */ + public function createPage(string $identifier, string $typeName = 'Page'): Page + { + if (!isset($this->typeDefinitions[$typeName])) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $typeName), 1474905953); + } + + $typeDefinition = $this->typeDefinitions[$typeName]; + + if (!isset($typeDefinition['implementationClassName'])) { + throw new TypeDefinitionNotFoundException(sprintf('The "implementationClassName" was not set in type definition "%s".', $typeName), 1477083126); + } + $implementationClassName = $typeDefinition['implementationClassName']; + $page = $this->objectManager->get($implementationClassName, $identifier, $typeName); + + if (isset($typeDefinition['label'])) { + $page->setLabel($typeDefinition['label']); + } + + if (isset($typeDefinition['rendererClassName'])) { + $page->setRendererClassName($typeDefinition['rendererClassName']); + } + + if (isset($typeDefinition['renderingOptions'])) { + foreach ($typeDefinition['renderingOptions'] as $key => $value) { + $page->setRenderingOption($key, $value); + } + } + + FormArrayUtility::assertAllArrayKeysAreValid($typeDefinition, ['implementationClassName', 'label', 'rendererClassName', 'renderingOptions', 'formEditor']); + + $this->addPage($page); + return $page; + } + + /** + * Add a new page at the end of the form. + * + * Instead of this method, you should often use {@link createPage} instead. + * + * @param Page $page + * @return void + * @throws FormDefinitionConsistencyException if Page is already added to a FormDefinition + * @see createPage + * @api + */ + public function addPage(Page $page) + { + $this->addRenderable($page); + } + + /** + * Get the Form's pages + * + * @return array<Page> The Form's pages in the correct order + * @api + */ + public function getPages(): array + { + return $this->renderables; + } + + /** + * Check whether a page with the given $index exists + * + * @param int $index + * @return bool TRUE if a page with the given $index exists, otherwise FALSE + * @api + */ + public function hasPageWithIndex(int $index): bool + { + return isset($this->renderables[$index]); + } + + /** + * Get the page with the passed index. The first page has index zero. + * + * If page at $index does not exist, an exception is thrown. @see hasPageWithIndex() + * + * @param int $index + * @return Page the page, or NULL if none found. + * @throws FormException if the specified index does not exist + * @api + */ + public function getPageByIndex(int $index) + { + if (!$this->hasPageWithIndex($index)) { + throw new FormException(sprintf('There is no page with an index of %d', $index), 1329233627); + } + return $this->renderables[$index]; + } + + /** + * Adds the specified finisher to this form + * + * @param FinisherInterface $finisher + * @return void + * @api + */ + public function addFinisher(FinisherInterface $finisher) + { + $this->finishers[] = $finisher; + } + + /** + * @param string $finisherIdentifier identifier of the finisher as registered in the current form (for example: "Redirect") + * @param array $options options for this finisher in the format ['option1' => 'value1', 'option2' => 'value2', ...] + * @return FinisherInterface + * @throws FinisherPresetNotFoundException + * @api + */ + public function createFinisher(string $finisherIdentifier, array $options = []): FinisherInterface + { + if (isset($this->finishersDefinition[$finisherIdentifier]) && is_array($this->finishersDefinition[$finisherIdentifier]) && isset($this->finishersDefinition[$finisherIdentifier]['implementationClassName'])) { + $implementationClassName = $this->finishersDefinition[$finisherIdentifier]['implementationClassName']; + $defaultOptions = isset($this->finishersDefinition[$finisherIdentifier]['options']) ? $this->finishersDefinition[$finisherIdentifier]['options'] : []; + CoreArrayUtility::mergeRecursiveWithOverrule($defaultOptions, $options); + + $finisher = $this->objectManager->get($implementationClassName); + $finisher->setOptions($defaultOptions); + $this->addFinisher($finisher); + return $finisher; + } else { + throw new FinisherPresetNotFoundException('The finisher preset identified by "' . $finisherIdentifier . '" could not be found, or the implementationClassName was not specified.', 1328709784); + } + } + + /** + * Gets all finishers of this form + * + * @return \TYPO3\CMS\Form\Domain\Finishers\FinisherInterface[] + * @api + */ + public function getFinishers(): array + { + return $this->finishers; + } + + /** + * Add an element to the ElementsByIdentifier Cache. + * + * @param RenderableInterface $renderable + * @return void + * @throws DuplicateFormElementException + * @internal + */ + public function registerRenderable(RenderableInterface $renderable) + { + if ($renderable instanceof FormElementInterface) { + if (isset($this->elementsByIdentifier[$renderable->getIdentifier()])) { + throw new DuplicateFormElementException(sprintf('A form element with identifier "%s" is already part of the form.', $renderable->getIdentifier()), 1325663761); + } + $this->elementsByIdentifier[$renderable->getIdentifier()] = $renderable; + } + } + + /** + * Remove an element from the ElementsByIdentifier cache + * + * @param RenderableInterface $renderable + * @return void + * @internal + */ + public function unregisterRenderable(RenderableInterface $renderable) + { + if ($renderable instanceof FormElementInterface) { + unset($this->elementsByIdentifier[$renderable->getIdentifier()]); + } + } + + /** + * Get a Form Element by its identifier + * + * If identifier does not exist, returns NULL. + * + * @param string $elementIdentifier + * @return FormElementInterface The element with the given $elementIdentifier or NULL if none found + * @api + */ + public function getElementByIdentifier(string $elementIdentifier) + { + return isset($this->elementsByIdentifier[$elementIdentifier]) ? $this->elementsByIdentifier[$elementIdentifier] : null; + } + + /** + * Sets the default value of a form element + * + * @param string $elementIdentifier identifier of the form element. This supports property paths! + * @param mixed $defaultValue + * @return void + * @internal + */ + public function addElementDefaultValue(string $elementIdentifier, $defaultValue) + { + $this->elementDefaultValues = ArrayUtility::setValueByPath($this->elementDefaultValues, $elementIdentifier, $defaultValue); + } + + /** + * returns the default value of the specified form element + * or NULL if no default value was set + * + * @param string $elementIdentifier identifier of the form element. This supports property paths! + * @return mixed The elements default value + * @internal + */ + public function getElementDefaultValueByIdentifier(string $elementIdentifier) + { + return ObjectAccess::getPropertyPath($this->elementDefaultValues, $elementIdentifier); + } + + /** + * Move $pageToMove before $referencePage + * + * @param Page $pageToMove + * @param Page $referencePage + * @return void + * @api + */ + public function movePageBefore(Page $pageToMove, Page $referencePage) + { + $this->moveRenderableBefore($pageToMove, $referencePage); + } + + /** + * Move $pageToMove after $referencePage + * + * @param Page $pageToMove + * @param Page $referencePage + * @return void + * @api + */ + public function movePageAfter(Page $pageToMove, Page $referencePage) + { + $this->moveRenderableAfter($pageToMove, $referencePage); + } + + /** + * Remove $pageToRemove from form + * + * @param Page $pageToRemove + * @return void + * @api + */ + public function removePage(Page $pageToRemove) + { + $this->removeRenderable($pageToRemove); + } + + /** + * Bind the current request & response to this form instance, effectively creating + * a new "instance" of the Form. + * + * @param Request $request + * @param Response $response + * @return FormRuntime + * @api + */ + public function bind(Request $request, Response $response): FormRuntime + { + return $this->objectManager->get(FormRuntime::class, $this, $request, $response); + } + + /** + * @param string $propertyPath + * @return ProcessingRule + * @api + */ + public function getProcessingRule(string $propertyPath): ProcessingRule + { + if (!isset($this->processingRules[$propertyPath])) { + $this->processingRules[$propertyPath] = $this->objectManager->get(ProcessingRule::class); + } + return $this->processingRules[$propertyPath]; + } + + /** + * Get all mapping rules + * + * @return \TYPO3\CMS\Form\Mvc\ProcessingRule[] + * @internal + */ + public function getProcessingRules(): array + { + return $this->processingRules; + } + + /** + * @return array + * @internal + */ + public function getTypeDefinitions(): array + { + return $this->typeDefinitions; + } + + /** + * @return array + * @internal + */ + public function getValidatorsDefinition(): array + { + return $this->validatorsDefinition; + } + + /** + * Get the persistence identifier of the form + * + * @return string + * @internal + */ + public function getPersistenceIdentifier(): string + { + return $this->persistenceIdentifier; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractFormElement.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractFormElement.php new file mode 100644 index 0000000000000000000000000000000000000000..f977a975ada5d3952f41a46fd2c58cf5b095b20f --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractFormElement.php @@ -0,0 +1,168 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator; +use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException; +use TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A base form element, which is the starting point for creating custom (PHP-based) + * Form Elements. + * + * A *FormElement* is a part of a *Page*, which in turn is part of a FormDefinition. + * See {@link FormDefinition} for an in-depth explanation. + * + * Subclassing this class is a good starting-point for implementing custom PHP-based + * Form Elements. + * + * Most of the functionality and API is implemented in {@link \TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable}, so + * make sure to check out this class as well. + * + * Still, it is quite rare that you need to subclass this class; often + * you can just use the {@link \TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement} and replace some templates. + * + * Scope: frontend + * **This class is meant to be sub classed by developers.** + */ +abstract class AbstractFormElement extends AbstractRenderable implements FormElementInterface +{ + + /** + * @var array + */ + protected $properties = []; + + /** + * Constructor. Needs this FormElement's identifier and the FormElement type + * + * @param string $identifier The FormElement's identifier + * @param string $type The Form Element Type + * @throws IdentifierNotValidException + * @api + */ + public function __construct(string $identifier, string $type) + { + if (!is_string($identifier) || strlen($identifier) === 0) { + throw new IdentifierNotValidException('The given identifier was not a string or the string was empty.', 1477082502); + } + $this->identifier = $identifier; + $this->type = $type; + } + + /** + * Override this method in your custom FormElements if needed + * + * @return void + * @api + */ + public function initializeFormElement() + { + } + + /** + * Get the global unique identifier of the element + * + * @return string + * @api + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + $uniqueIdentifier = sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + $uniqueIdentifier = preg_replace('/[^a-zA-Z0-9-_]/', '_', $uniqueIdentifier); + return lcfirst($uniqueIdentifier); + } + + /** + * Get the default value of the element + * + * @return mixed + * @api + */ + public function getDefaultValue() + { + $formDefinition = $this->getRootForm(); + return $formDefinition->getElementDefaultValueByIdentifier($this->identifier); + } + + /** + * Set the default value of the element + * + * @param mixed $defaultValue + * @return void + * @api + */ + public function setDefaultValue($defaultValue) + { + $formDefinition = $this->getRootForm(); + $formDefinition->addElementDefaultValue($this->identifier, $defaultValue); + } + + /** + * Check if the element is required + * + * @return bool + * @api + */ + public function isRequired(): bool + { + foreach ($this->getValidators() as $validator) { + if ($validator instanceof NotEmptyValidator) { + return true; + } + } + return false; + } + + /** + * Set a property of the element + * + * @param string $key + * @param mixed $value + * @return void + * @api + */ + public function setProperty(string $key, $value) + { + $this->properties[$key] = $value; + } + + /** + * Get all properties + * + * @return array + * @api + */ + public function getProperties(): array + { + return $this->properties; + } + + /** + * Override this method in your custom FormElements if needed + * + * @param FormRuntime $formRuntime + * @param mixed $elementValue + * @param array $requestArguments submitted raw request values + * @return void + * @api + */ + public function onSubmit(FormRuntime $formRuntime, &$elementValue, array $requestArguments = []) + { + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractSection.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractSection.php new file mode 100644 index 0000000000000000000000000000000000000000..2754c6d1f7153fc94d95d4b5caaef61dc84ceefe --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/AbstractSection.php @@ -0,0 +1,199 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException; +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotFoundException; +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException; +use TYPO3\CMS\Form\Domain\Model\Exception\FormDefinitionConsistencyException; +use TYPO3\CMS\Form\Domain\Model\Renderable\AbstractCompositeRenderable; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A base class for "section-like" form parts like "Page" or "Section" (which + * is rendered as "Fieldset") + * + * This class contains multiple FormElements ({@link FormElementInterface}). + * + * Please see {@link FormDefinition} for an in-depth explanation. + * + * **This class is NOT meant to be sub classed by developers.** + * Scope: frontend + */ +abstract class AbstractSection extends AbstractCompositeRenderable +{ + + /** + * Constructor. Needs the identifier and type of this element + * + * @param string $identifier The Section identifier + * @param string $type The Section type + * @throws IdentifierNotValidException if the identifier was no non-empty string + * @api + */ + public function __construct(string $identifier, string $type) + { + if (!is_string($identifier) || strlen($identifier) === 0) { + throw new IdentifierNotValidException('The given identifier was not a string or the string was empty.', 1477082501); + } + + $this->identifier = $identifier; + $this->type = $type; + } + + /** + * Get the child Form Elements + * + * @return FormElementInterface[] The Page's elements + * @api + */ + public function getElements(): array + { + return $this->renderables; + } + + /** + * Get the child Form Elements + * + * @return FormElementInterface[] The Page's elements + * @api + */ + public function getElementsRecursively(): array + { + return $this->getRenderablesRecursively(); + } + + /** + * Add a new form element at the end of the section + * + * @param FormElementInterface $formElement The form element to add + * @return void + * @throws FormDefinitionConsistencyException if FormElement is already added to a section + * @api + */ + public function addElement(FormElementInterface $formElement) + { + $this->addRenderable($formElement); + } + + /** + * Create a form element with the given $identifier and attach it to this section/page. + * + * - Create Form Element object based on the given $typeName + * - set defaults inside the Form Element (based on the parent form's field defaults) + * - attach Form Element to this Section/Page + * - return the newly created Form Element object + * + * + * @param string $identifier Identifier of the new form element + * @param string $typeName type of the new form element + * @return FormElementInterface the newly created form element + * @throws TypeDefinitionNotFoundException + * @throws TypeDefinitionNotValidException + * @api + */ + public function createElement(string $identifier, string $typeName): FormElementInterface + { + $formDefinition = $this->getRootForm(); + + $typeDefinitions = $formDefinition->getTypeDefinitions(); + if (isset($typeDefinitions[$typeName])) { + $typeDefinition = $typeDefinitions[$typeName]; + } else { + $element = GeneralUtility::makeInstance(ObjectManager::class) + ->get(UnknownFormElement::class, $identifier, $typeName); + $this->addElement($element); + return $element; + } + + if (!isset($typeDefinition['implementationClassName'])) { + throw new TypeDefinitionNotFoundException(sprintf('The "implementationClassName" was not set in type definition "%s".', $typeName), 1325689855); + } + + $implementationClassName = $typeDefinition['implementationClassName']; + $element = GeneralUtility::makeInstance(ObjectManager::class) + ->get($implementationClassName, $identifier, $typeName); + if (!$element instanceof FormElementInterface) { + throw new TypeDefinitionNotValidException(sprintf('The "implementationClassName" for element "%s" ("%s") does not implement the FormElementInterface.', $identifier, $implementationClassName), 1327318156); + } + unset($typeDefinition['implementationClassName']); + + $this->addElement($element); + $element->setOptions($typeDefinition); + + $element->initializeFormElement(); + return $element; + } + + /** + * Move FormElement $element before $referenceElement. + * + * Both $element and $referenceElement must be direct descendants of this Section/Page. + * + * @param FormElementInterface $elementToMove + * @param FormElementInterface $referenceElement + * @return void + * @api + */ + public function moveElementBefore(FormElementInterface $elementToMove, FormElementInterface $referenceElement) + { + $this->moveRenderableBefore($elementToMove, $referenceElement); + } + + /** + * Move FormElement $element after $referenceElement + * + * Both $element and $referenceElement must be direct descendants of this Section/Page. + * + * @param FormElementInterface $elementToMove + * @param FormElementInterface $referenceElement + * @return void + * @api + */ + public function moveElementAfter(FormElementInterface $elementToMove, FormElementInterface $referenceElement) + { + $this->moveRenderableAfter($elementToMove, $referenceElement); + } + + /** + * Remove $elementToRemove from this Section/Page + * + * @param FormElementInterface $elementToRemove + * @return void + * @api + */ + public function removeElement(FormElementInterface $elementToRemove) + { + $this->removeRenderable($elementToRemove); + } + + /** + * This callback is invoked by the FormRuntime whenever values are mapped and validated + * (after a form page was submitted) + * @see FormRuntime::mapAndValidate() + * + * @param FormRuntime $formRuntime + * @param mixed $elementValue submitted value of the element *before post processing* + * @param array $requestArguments submitted raw request values + * @return void + * @api + */ + public function onSubmit(FormRuntime $formRuntime, &$elementValue, array $requestArguments = []) + { + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/AdvancedPassword.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/AdvancedPassword.php new file mode 100644 index 0000000000000000000000000000000000000000..206abb9fd80e683bc01392757726a6e29d836d7d --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/AdvancedPassword.php @@ -0,0 +1,53 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Error\Error; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A password with confirmation form element + * + * Scope: frontend + */ +class AdvancedPassword extends AbstractFormElement +{ + + /** + * This callback is invoked by the FormRuntime whenever values are mapped and validated + * (after a form page was submitted) + * + * @param FormRuntime $formRuntime + * @param mixed $elementValue submitted value of the element *before post processing* + * @param array $requestArguments submitted raw request values + * @return void + * @see FormRuntime::mapAndValidate() + * @internal + */ + public function onSubmit(FormRuntime $formRuntime, &$elementValue, array $requestArguments = []) + { + if ($elementValue['password'] !== $elementValue['confirmation']) { + $processingRule = $this->getRootForm()->getProcessingRule($this->getIdentifier()); + $processingRule->getProcessingMessages()->addError( + GeneralUtility::makeInstance(ObjectManager::class) + ->get(Error::class, 'Password doesn\'t match confirmation', 1334768052) + ); + } + $elementValue = $elementValue['password']; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Filter/IntegerFilter.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/DatePicker.php similarity index 61% rename from typo3/sysext/form/Classes/Domain/Filter/IntegerFilter.php rename to typo3/sysext/form/Classes/Domain/Model/FormElements/DatePicker.php index 24bc8fe801032e220f50946cf032773b8b9dff36..5aea0b31c05670a8e3e3d22ed18415e4689802d0 100644 --- a/typo3/sysext/form/Classes/Domain/Filter/IntegerFilter.php +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/DatePicker.php @@ -1,5 +1,6 @@ <?php -namespace TYPO3\CMS\Form\Domain\Filter; +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; /* * This file is part of the TYPO3 CMS project. @@ -15,18 +16,19 @@ namespace TYPO3\CMS\Form\Domain\Filter; */ /** - * Integer filter + * A date picker form element + * + * Scope: frontend */ -class IntegerFilter extends AbstractFilter implements FilterInterface +class DatePicker extends AbstractFormElement { + /** - * Cast to integer - * - * @param string $value - * @return string + * @return void + * @internal */ - public function filter($value) + public function initializeFormElement() { - return (int)((string)$value); + $this->setDataType('DateTime'); } } diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/FileUpload.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/FileUpload.php new file mode 100644 index 0000000000000000000000000000000000000000..0bfe7132aa2c4c0677b710f46d4509be70ffd005 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/FileUpload.php @@ -0,0 +1,109 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\ResourceFactory; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\PathUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Mvc\Property\TypeConverter\UploadedFileReferenceConverter; +use TYPO3\CMS\Form\Mvc\Validation\MimeTypeValidator; + +/** + * A generic file upload form element + * + * Scope: frontend + */ +class FileUpload extends AbstractFormElement +{ + + /** + * @return void + * @internal + */ + public function initializeFormElement() + { + $this->setDataType('TYPO3\CMS\Extbase\Domain\Model\FileReference'); + } + + /** + * Set the property mapping configuration for the file upload element. + * * Add the UploadedFileReferenceConverter to convert an uploaded file to an + * FileReference. + * * Add the MimeTypeValidator to the UploadedFileReferenceConverter to + * delete non valid filetypes directly. + * * Setup the storage: + * If the property "saveToFileMount" exist for this element it will be used. + * If this file mount or the property "saveToFileMount" does not exist + * the folder in which the form definition lies (persistence identifier) will be used. + * If the form is generated programmatically and therefore no + * persistence identifier exist the default storage "1:/user_upload/" will be used. + * + * @return void + * @internal + * @todo: could we find a not so ugly solution for that? + */ + public function onBuildingFinished() + { + /** @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration */ + $propertyMappingConfiguration = $this->getRootForm()->getProcessingRule($this->getIdentifier())->getPropertyMappingConfiguration(); + + $mimeTypeValidator = GeneralUtility::makeInstance(ObjectManager::class) + ->get(MimeTypeValidator::class, ['allowedMimeTypes' => $this->properties['allowedMimeTypes']]); + $uploadConfiguration = [ + UploadedFileReferenceConverter::CONFIGURATION_FILE_VALIDATORS => [$mimeTypeValidator], + UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_CONFLICT_MODE => 'rename', + ]; + + $saveToFileMountIdentifier = (isset($this->properties['saveToFileMount'])) ? $this->properties['saveToFileMount'] : null; + if ($this->checkSaveFileMountAccess($saveToFileMountIdentifier)) { + $uploadConfiguration[UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_FOLDER] = $saveToFileMountIdentifier; + } else { + $persistenceIdentifier = $this->getRootForm()->getPersistenceIdentifier(); + if (!empty($persistenceIdentifier)) { + $pathinfo = PathUtility::pathinfo($persistenceIdentifier); + $saveToFileMountIdentifier = $pathinfo['dirname']; + if ($this->checkSaveFileMountAccess($saveToFileMountIdentifier)) { + $uploadConfiguration[UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_FOLDER] = $saveToFileMountIdentifier; + } + } + } + + $propertyMappingConfiguration->setTypeConverterOptions(UploadedFileReferenceConverter::class, $uploadConfiguration); + } + + /** + * @param string $saveToFileMountIdentifier + * @return bool + * @internal + */ + protected function checkSaveFileMountAccess(string $saveToFileMountIdentifier): bool + { + if (empty($saveToFileMountIdentifier)) { + return false; + } + + $resourceFactory = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ResourceFactory::class); + + try { + $resourceFactory->getFolderObjectFromCombinedIdentifier($saveToFileMountIdentifier); + return true; + } catch (\InvalidArgumentException $e) { + return false; + } + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/FormElementInterface.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/FormElementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..15413677133de8b9e36982148548888d6399df2b --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/FormElementInterface.php @@ -0,0 +1,147 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface; +use TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A base form element interface, which can be the starting point for creating + * custom (PHP-based) Form Elements. + * + * A *FormElement* is a part of a *Page*, which in turn is part of a FormDefinition. + * See {@link FormDefinition} for an in-depth explanation. + * + * **Often, you should rather subclass {@link AbstractFormElement} instead of + * implementing this interface.** + * + * Scope: frontend + */ +interface FormElementInterface extends RenderableInterface +{ + + /** + * Will be called as soon as the element is (tried to be) added to a form + * @see registerInFormIfPossible() + * + * @return void + * @internal + */ + public function initializeFormElement(); + + /** + * Returns a unique identifier of this element. + * While element identifiers are only unique within one form, + * this includes the identifier of the form itself, making it "globally" unique + * + * @return string the "globally" unique identifier of this element + * @api + */ + public function getUniqueIdentifier(): string; + + /** + * Get the default value with which the Form Element should be initialized + * during display. + * + * @return mixed the default value for this Form Element + * @api + */ + public function getDefaultValue(); + + /** + * Set the default value with which the Form Element should be initialized + * during display. + * + * @param mixed $defaultValue the default value for this Form Element + * @api + */ + public function setDefaultValue($defaultValue); + + /** + * Set an element-specific configuration property. + * + * @param string $key + * @param mixed $value + * @return void + * @api + */ + public function setProperty(string $key, $value); + + /** + * Get all element-specific configuration properties + * + * @return array + * @api + */ + public function getProperties(): array; + + /** + * Set a rendering option + * + * @param string $key + * @param mixed $value + * @api + */ + public function setRenderingOption(string $key, $value); + + /** + * Returns the child validators of the ConjunctionValidator that is registered for this element + * + * @return \SplObjectStorage<ValidatorInterface> + * @internal + */ + public function getValidators(): \SplObjectStorage; + + /** + * Registers a validator for this element + * + * @param ValidatorInterface $validator + * @return void + * @api + */ + public function addValidator(ValidatorInterface $validator); + + /** + * Set the target data type for this element + * + * @param string $dataType the target data type + * @return void + * @api + */ + public function setDataType(string $dataType); + + /** + * Whether or not this element is required + * + * @return bool + * @api + */ + public function isRequired(): bool; + + /** + * This callback is invoked by the FormRuntime whenever values are mapped and validated + * (after a form page was submitted) + * + * @param FormRuntime $formRuntime + * @param mixed $elementValue submitted value of the element *before post processing* + * @param array $requestArguments submitted raw request values + * @return void + * @see FormRuntime::mapAndValidate() + * @api + */ + public function onSubmit(FormRuntime $formRuntime, &$elementValue, array $requestArguments = []); +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/GenericFormElement.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/GenericFormElement.php new file mode 100644 index 0000000000000000000000000000000000000000..05119f810076cf6d9dbe5ebd897ebf0aefef2369 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/GenericFormElement.php @@ -0,0 +1,26 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * A generic form element + * + * Scope: frontend + * @api + */ +class GenericFormElement extends AbstractFormElement +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/Page.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/Page.php new file mode 100644 index 0000000000000000000000000000000000000000..568c23c3c71fdc2e9ec0dda5e67a293fe74b0fa6 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/Page.php @@ -0,0 +1,68 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\FormDefinition; +use TYPO3\CMS\Form\Domain\Model\Renderable\CompositeRenderableInterface; +use TYPO3\CMS\Form\Exception as FormException; + +/** + * A Page, being part of a bigger FormDefinition. It contains numerous FormElements + * as children. + * + * A FormDefinition consists of multiple Pages, where only one page is visible + * at any given time. + * + * Most of the API of this object is implemented in {@link AbstractSection}, + * so make sure to review this class as well. + * + * Please see {@link FormDefinition} for an in-depth explanation. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +class Page extends AbstractSection +{ + + /** + * Constructor. Needs this Page's identifier + * + * @param string $identifier The Page's identifier + * @param string $type The Page's type + * @throws \TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException if the identifier was no non-empty string + * @api + */ + public function __construct(string $identifier, string $type = 'Page') + { + parent::__construct($identifier, $type); + } + + /** + * Set the parent renderable + * + * @param CompositeRenderableInterface $parentRenderable + * @return void + * @throws FormException + * @api + */ + public function setParentRenderable(CompositeRenderableInterface $parentRenderable) + { + if (!($parentRenderable instanceof FormDefinition)) { + throw new FormException(sprintf('The specified parentRenderable must be a FormDefinition, got "%s"', is_object($parentRenderable) ? get_class($parentRenderable) : gettype($parentRenderable)), 1329233747); + } + parent::setParentRenderable($parentRenderable); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/Section.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/Section.php new file mode 100644 index 0000000000000000000000000000000000000000..61ee7864f71939a3a9e5412164389debf138b7a7 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/Section.php @@ -0,0 +1,166 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator; +use TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface; + +/** + * A Section, being part of a bigger Page + * + * This class contains multiple FormElements ({@link FormElementInterface}). + * + * Please see {@link FormDefinition} for an in-depth explanation. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +class Section extends AbstractSection implements FormElementInterface +{ + + /** + * @var array + */ + protected $properties = []; + + /** + * Will be called as soon as the element is (tried to be) added to a form + * @see registerInFormIfPossible() + * + * @return void + * @internal + */ + public function initializeFormElement() + { + } + + /** + * Returns a unique identifier of this element. + * While element identifiers are only unique within one form, + * this includes the identifier of the form itself, making it "globally" unique + * + * @return string the "globally" unique identifier of this element + * @api + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + return sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + } + + /** + * Get the default value with which the Form Element should be initialized + * during display. + * Note: This is currently not used for section elements + * + * @return mixed the default value for this Form Element + * @api + */ + public function getDefaultValue() + { + return null; + } + + /** + * Set the default value with which the Form Element should be initialized + * during display. + * Note: This is currently ignored for section elements + * + * @param mixed $defaultValue the default value for this Form Element + * @api + */ + public function setDefaultValue($defaultValue) + { + } + + /** + * Get all element-specific configuration properties + * + * @return array + * @api + */ + public function getProperties(): array + { + return $this->properties; + } + + /** + * Set an element-specific configuration property. + * + * @param string $key + * @param mixed $value + * @return void + * @api + */ + public function setProperty(string $key, $value) + { + $this->properties[$key] = $value; + } + + /** + * Set the rendering option $key to $value. + * + * @param string $key + * @param mixed $value + * @return mixed + * @api + */ + public function setRenderingOption(string $key, $value) + { + $this->renderingOptions[$key] = $value; + } + + /** + * Get all validators on the element + * + * @return \SplObjectStorage + * @internal + */ + public function getValidators(): \SplObjectStorage + { + $formDefinition = $this->getRootForm(); + return $formDefinition->getProcessingRule($this->getIdentifier())->getValidators(); + } + + /** + * Add a validator to the element + * + * @param ValidatorInterface $validator + * @return void + * @api + */ + public function addValidator(ValidatorInterface $validator) + { + $formDefinition = $this->getRootForm(); + $formDefinition->getProcessingRule($this->getIdentifier())->addValidator($validator); + } + + /** + * Whether or not this element is required + * + * @return bool + * @api + */ + public function isRequired(): bool + { + foreach ($this->getValidators() as $validator) { + if ($validator instanceof NotEmptyValidator) { + return true; + } + } + return false; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/FormElements/UnknownFormElement.php b/typo3/sysext/form/Classes/Domain/Model/FormElements/UnknownFormElement.php new file mode 100644 index 0000000000000000000000000000000000000000..08ab78e29be04160e39ee73a746b6489e1b2157c --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/FormElements/UnknownFormElement.php @@ -0,0 +1,147 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\FormElements; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception\IdentifierNotValidException; +use TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable; +use TYPO3\CMS\Form\Domain\Renderer\UnknownFormElementRenderer; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A Form Element that has no definition. + * + * Scope: frontend + */ +class UnknownFormElement extends AbstractRenderable implements FormElementInterface +{ + + /** + * Constructor. Needs this FormElement's identifier and the FormElement type + * + * @param string $identifier The FormElement's identifier + * @param string $type The Form Element Type + * @throws IdentifierNotValidException + * @api + */ + public function __construct(string $identifier, string $type) + { + if (!is_string($identifier) || strlen($identifier) === 0) { + throw new IdentifierNotValidException('The given identifier was not a string or the string was empty.', 1382364370); + } + $this->identifier = $identifier; + $this->type = $type; + } + + /** + * Returns a unique identifier of this element. + * While element identifiers are only unique within one form, + * this includes the identifier of the form itself, making it "globally" unique + * + * @return string the "globally" unique identifier of this element + * @api + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + $uniqueIdentifier = sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + $uniqueIdentifier = preg_replace('/[^a-zA-Z0-9-_]/', '_', $uniqueIdentifier); + return lcfirst($uniqueIdentifier); + } + + /** + * Unknown Form Elements are rendered with the UnknownFormElementRenderer + * + * @return string the renderer class name + * @internal + */ + public function getRendererClassName(): string + { + return UnknownFormElementRenderer::class; + } + + /** + * Not used in this implementation + * + * @return void + * @internal + */ + public function initializeFormElement() + { + } + + /** + * @return mixed the default value for this Form Element + * @internal + */ + public function getDefaultValue() + { + return null; + } + + /** + * Not used in this implementation + * + * @param mixed $defaultValue the default value for this Form Element + * @internal + */ + public function setDefaultValue($defaultValue) + { + } + + /** + * Not used in this implementation + * + * @param string $key + * @param mixed $value + * @return void + * @internal + */ + public function setProperty(string $key, $value) + { + } + + /** + * @return array + * @internal + */ + public function getProperties(): array + { + return []; + } + + /** + * @return bool + * @internal + */ + public function isRequired(): bool + { + return false; + } + + /** + * Not used in this implementation + * + * @param FormRuntime $formRuntime + * @param mixed $elementValue submitted value of the element *before post processing* + * @param array $requestArguments submitted raw request values + * @return void + * @see FormRuntime::mapAndValidate() + * @internal + */ + public function onSubmit(FormRuntime $formRuntime, &$elementValue, array $requestArguments = []) + { + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/AbstractJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/AbstractJsonElement.php deleted file mode 100644 index f61431d417c4325a64a99ccf9b308313d26d5544..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/AbstractJsonElement.php +++ /dev/null @@ -1,178 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON element abstract - */ -class AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = ''; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = []; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = []; - - /** - * Child elements allowed withing this element - * - * Some elements like select handle their own child elements - * - * @var bool - */ - protected $childElementsAllowed = true; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - */ - public function setParameters(array $parameters) - { - foreach ($this->configuration as $key => $value) { - switch ($key) { - case 'attributes': - $this->setAttributes($parameters); - break; - case 'filters': - $this->setFilters($parameters); - break; - case 'label': - $this->setLabel($parameters); - break; - case 'layout': - $this->setLayout($parameters); - break; - case 'validation': - $this->setValidation($parameters); - break; - } - } - } - - /** - * Check if child elements are allowed within this element - * - * @return bool TRUE if allowed - */ - public function childElementsAllowed() - { - return $this->childElementsAllowed; - } - - /** - * Set the attributes according to the allowed attributes of this element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setAttributes(array $parameters) - { - foreach ($this->allowedAttributes as $allowedAttribute) { - if (isset($parameters[$allowedAttribute])) { - $this->configuration['attributes'][$allowedAttribute] = $parameters[$allowedAttribute]; - } elseif (!isset($this->configuration['attributes'][$allowedAttribute])) { - $this->configuration['attributes'][$allowedAttribute] = ''; - } - } - } - - /** - * Set the filters of the element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setFilters(array $parameters) - { - if (isset($parameters['filters.']) && is_array($parameters['filters.'])) { - $filters = $parameters['filters.']; - foreach ($filters as $key => $filterName) { - if ((int)$key && strpos($key, '.') === false) { - $filterConfiguration = []; - if (isset($filters[$key . '.'])) { - $filterConfiguration = $filters[$key . '.']; - } - $this->configuration['filters'][$filterName] = $filterConfiguration; - } - } - } else { - $this->configuration['filters'] = new \stdClass(); - } - } - - /** - * Set the label of the element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setLabel(array $parameters) - { - if (isset($parameters['label']) && !isset($parameters['label.'])) { - $this->configuration['label']['value'] = $parameters['label']; - } elseif (!isset($parameters['label']) && isset($parameters['label.'])) { - $this->configuration['label']['value'] = $parameters['label.']['value']; - } - } - - /** - * Set the layout of the element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setLayout(array $parameters) - { - if (isset($parameters['layout'])) { - if ($this->configuration['layout'] === 'front') { - $this->configuration['layout'] = 'back'; - } else { - $this->configuration['layout'] = 'front'; - } - } - } - - /** - * Set the validation rules for the element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setValidation(array $parameters) - { - if (isset($parameters['validation']) && is_array($parameters['validation'])) { - $this->configuration['validation'] = $parameters['validation']; - } else { - $this->configuration['validation'] = new \stdClass(); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/ButtonJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/ButtonJsonElement.php deleted file mode 100644 index 8d1520a680e5f3c1afed729e4f8338e4242b4f5a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/ButtonJsonElement.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON button - */ -class ButtonJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-button'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'button' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'disabled', - 'name', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxGroupJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxGroupJsonElement.php deleted file mode 100644 index f9795d072d9d48f1803e1150d8afa143148e2797..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxGroupJsonElement.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Core\Utility\ArrayUtility; - -/** - * JSON checkboxgroup - */ -class CheckboxGroupJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-predefined-checkboxgroup'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'legend' => [ - 'value' => '' - ], - 'options' => [], - 'various' => [ - 'name' => '' - ], - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setOptions($parameters); - $this->setVarious($parameters); - } - - /** - * Set the options for this object - * - * @param array $parameters Configuration array - * @return void - */ - protected function setOptions(array $parameters) - { - if (is_array($parameters)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($parameters); - foreach ($keys as $key) { - $class = $parameters[$key]; - if ((int)$key && strpos($key, '.') === false) { - if (isset($parameters[$key . '.']) && $class === 'CHECKBOX') { - $childElementArguments = $parameters[$key . '.']; - if (isset($childElementArguments['checked'])) { - $childElementArguments['attributes']['selected'] = 'selected'; - unset($childElementArguments['checked']); - } - if (isset($childElementArguments['value'])) { - $childElementArguments['attributes']['value'] = $childElementArguments['value']; - unset($childElementArguments['value']); - } - if (isset($childElementArguments['label.'])) { - $childElementArguments['text'] = $childElementArguments['label.']['value']; - unset($childElementArguments['label.']); - } - $this->configuration['options'][] = $childElementArguments; - } - } - } - } - } - - /** - * Set the various properties for this object - * - * @param array $parameters Configuration array - * @return void - */ - protected function setVarious(array $parameters) - { - if (isset($parameters['name'])) { - $this->configuration['various']['name'] = $parameters['name']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxJsonElement.php deleted file mode 100644 index 68b38864902c775f0549d0a60368cde65f8a6b6c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/CheckboxJsonElement.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON checkbox - */ -class CheckboxJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-checkbox'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'checkbox' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'back', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'checked', - 'disabled', - 'name', - 'readonly', - 'required', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/ContainerJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/ContainerJsonElement.php deleted file mode 100644 index 32f477f7842fdeb8be664538196fd28d033fb88e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/ContainerJsonElement.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON container abstract - */ -class ContainerJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The items within this container - * - * @var array - */ - public $elementContainer = [ - 'hasDragAndDrop' => true, - 'items' => [] - ]; - - /** - * Add an element to this container - * - * @param \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement $element The element to add - * @return void - */ - public function addElement(\TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement $element) - { - $this->elementContainer['items'][] = $element; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/FieldsetJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/FieldsetJsonElement.php deleted file mode 100644 index 60283e036aefb5c852e5fbdff584b3ea08d8ef07..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/FieldsetJsonElement.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON fieldset - */ -class FieldsetJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\ContainerJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-fieldset'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'legend' => [ - 'value' => '' - ] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setLegend($parameters); - } - - /** - * Set the legend for the element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setLegend(array $parameters) - { - if (isset($parameters['legend']) && !isset($parameters['legend.'])) { - $this->configuration['legend']['value'] = $parameters['legend']; - } elseif (!isset($parameters['legend']) && isset($parameters['legend.'])) { - $this->configuration['legend']['value'] = $parameters['legend.']['value']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/FileuploadJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/FileuploadJsonElement.php deleted file mode 100644 index 50cc8ae2c99a0ed0a47e5457af01251133524835..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/FileuploadJsonElement.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON Fileupload - */ -class FileuploadJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-fileupload'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'file' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'accept', - 'autofocus', - 'disabled', - 'multiple', - 'name', - 'readonly', - 'required', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/FormJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/FormJsonElement.php deleted file mode 100644 index 312ce8bc827ba2198ce5ec8683b5c509e448d683..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/FormJsonElement.php +++ /dev/null @@ -1,141 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON form - */ -class FormJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\ContainerJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-form'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'prefix' => 'tx_form', - 'confirmation' => true, - 'postProcessor' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'accept', - 'accept-charset', - 'action', - 'autocomplete', - 'enctype', - 'method', - 'novalidate' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\ContainerJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setPrefix($parameters); - $this->setConfirmation($parameters); - $this->setPostProcessors($parameters); - } - - /** - * Set the confirmation message boolean - * - * @param array $parameters Configuration array - * @return void - */ - protected function setConfirmation(array $parameters) - { - if (isset($parameters['confirmation'])) { - $this->configuration['confirmation'] = $parameters['confirmation']; - } - } - - /** - * Set the post processors and their configuration - * - * @param array $parameters Configuration array - * @return void - */ - protected function setPostProcessors(array $parameters) - { - if (isset($parameters['postProcessor.']) && is_array($parameters['postProcessor.'])) { - $postProcessors = $parameters['postProcessor.']; - foreach ($postProcessors as $key => $postProcessorName) { - if ((int)$key && strpos($key, '.') === false) { - $postProcessorConfiguration = []; - if (isset($postProcessors[$key . '.'])) { - $postProcessorConfiguration = $postProcessors[$key . '.']; - } - $this->configuration['postProcessor'][$postProcessorName] = $postProcessorConfiguration; - } - } - } else { - $this->configuration['postProcessor'] = [ - 'mail' => [ - 'recipientEmail' => '', - 'senderEmail' => '' - ] - ]; - } - } - - /** - * Set the prefix - * - * @param array $parameters Configuration array - * @return void - */ - protected function setPrefix(array $parameters) - { - if (isset($parameters['prefix'])) { - $this->configuration['prefix'] = $parameters['prefix']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/HeaderJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/HeaderJsonElement.php deleted file mode 100644 index 2461799969f8c1cfe87b29af9f04ce58f0c91c83..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/HeaderJsonElement.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON header - */ -class HeaderJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-content-header'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'various' => [ - 'headingSize' => 'h1', - 'content' => '' - ] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style', - 'title' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setVarious($parameters); - } - - /** - * Set the various properties for the element - * - * For this element this is the headingsize and the value - * - * @param array $parameters Configuration array - * @return void - */ - protected function setVarious(array $parameters) - { - if (isset($parameters['headingSize'])) { - if (preg_match('#^h[1-5]$#', $parameters['headingSize'])) { - $this->configuration['various']['headingSize'] = $parameters['headingSize']; - } - } - if (isset($parameters['content'])) { - $this->configuration['various']['content'] = $parameters['content']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/HiddenJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/HiddenJsonElement.php deleted file mode 100644 index 6c7f61cd554c7805a535e72f19f3a39ea8f436bb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/HiddenJsonElement.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON hidden - */ -class HiddenJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-hidden'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'hidden' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'name', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/NameJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/NameJsonElement.php deleted file mode 100644 index 6f4ba0e573f3281ffdf2ef5d0b2f426a01e11261..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/NameJsonElement.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Core\Utility\ArrayUtility; - -/** - * JSON name - */ -class NameJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-predefined-name'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'legend' => [ - 'value' => '' - ], - 'various' => [ - 'prefix' => false, - 'suffix' => false, - 'middleName' => false - ] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setVarious($parameters); - } - - /** - * Set the various properties for the element - * - * For this element this is the prefix, suffix and middleName if they will - * be shown in the form - * - * @param array $parameters Configuration array - * @return void - */ - protected function setVarious(array $parameters) - { - if (is_array($parameters)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($parameters); - foreach ($keys as $key) { - if ((int)$key && strpos($key, '.') === false) { - if (isset($parameters[$key . '.'])) { - $childElementArguments = $parameters[$key . '.']; - if (in_array($childElementArguments['name'], ['prefix', 'suffix', 'middleName'])) { - $this->configuration['various'][$childElementArguments['name']] = true; - } - } - } - } - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/PasswordJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/PasswordJsonElement.php deleted file mode 100644 index 402d60995e3531b3b40e76721af575681ae1fd56..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/PasswordJsonElement.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON password - */ -class PasswordJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-password'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'password' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autocomplete', - 'autofocus', - 'disabled', - 'maxlength', - 'minlength', - 'name', - 'pattern', - 'placeholder', - 'readonly', - 'required', - 'size', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/RadioGroupJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/RadioGroupJsonElement.php deleted file mode 100644 index 27b6bff0f9eede0ec6daef40dbdc88fe1a2add59..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/RadioGroupJsonElement.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Core\Utility\ArrayUtility; - -/** - * JSON radiogroup - */ -class RadioGroupJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-predefined-radiogroup'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'legend' => [ - 'value' => '' - ], - 'options' => [], - 'various' => [ - 'name' => '' - ], - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\FieldsetJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setOptions($parameters); - $this->setVarious($parameters); - } - - /** - * Set the options for this object - * - * @param array $parameters Configuration array - * @return void - */ - protected function setOptions(array $parameters) - { - if (is_array($parameters)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($parameters); - foreach ($keys as $key) { - $class = $parameters[$key]; - if ((int)$key && strpos($key, '.') === false) { - if (isset($parameters[$key . '.']) && $class === 'RADIO') { - $childElementArguments = $parameters[$key . '.']; - if (isset($childElementArguments['checked'])) { - $childElementArguments['attributes']['selected'] = 'selected'; - unset($childElementArguments['checked']); - } - if (isset($childElementArguments['value'])) { - $childElementArguments['attributes']['value'] = $childElementArguments['value']; - unset($childElementArguments['value']); - } - if (isset($childElementArguments['label.'])) { - $childElementArguments['text'] = $childElementArguments['label.']['value']; - unset($childElementArguments['label.']); - } - $this->configuration['options'][] = $childElementArguments; - } - } - } - } - } - - /** - * Set the various properties for this object - * - * @param array $parameters Configuration array - * @return void - */ - protected function setVarious(array $parameters) - { - if (isset($parameters['name'])) { - $this->configuration['various']['name'] = $parameters['name']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/RadioJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/RadioJsonElement.php deleted file mode 100644 index dec274e5d4729e0624abb5a535110c3cba20ab60..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/RadioJsonElement.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON radio - */ -class RadioJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-radio'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'radio' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'back', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'checked', - 'disabled', - 'name', - 'readonly', - 'required', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/ResetJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/ResetJsonElement.php deleted file mode 100644 index 389f455b4fdd064b4c776f68ac3d8d231f645237..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/ResetJsonElement.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON reset - */ -class ResetJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-reset'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'reset' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'disabled', - 'name', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/SelectJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/SelectJsonElement.php deleted file mode 100644 index 54b62f1f7c392574d40bbb96cc58db32ec83ac56..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/SelectJsonElement.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Core\Utility\ArrayUtility; - -/** - * JSON select - */ -class SelectJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-select'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'options' => [], - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'disabled', - 'multiple', - 'name', - 'required', - 'size' - ]; - - protected $childElementsAllowed = false; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setOptions($parameters); - } - - /** - * Set the options for this object - * - * @param array $parameters Configuration array - * @return void - */ - protected function setOptions(array $parameters) - { - if (is_array($parameters)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($parameters); - foreach ($keys as $key) { - $class = $parameters[$key]; - if ((int)$key && strpos($key, '.') === false) { - if (isset($parameters[$key . '.']) && $class === 'OPTION') { - $childElementArguments = $parameters[$key . '.']; - if (isset($childElementArguments['selected'])) { - $childElementArguments['attributes']['selected'] = $childElementArguments['selected']; - unset($childElementArguments['selected']); - } - if (isset($childElementArguments['value'])) { - $childElementArguments['attributes']['value'] = $childElementArguments['value']; - unset($childElementArguments['value']); - } - $this->configuration['options'][] = $childElementArguments; - } - } - } - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/SubmitJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/SubmitJsonElement.php deleted file mode 100644 index 514e405992844d0a13beb7cb2aaf51090d65ce17..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/SubmitJsonElement.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON submit - */ -class SubmitJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-submit'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'submit' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'disabled', - 'name', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/TextareaJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/TextareaJsonElement.php deleted file mode 100644 index 4a0a8d30657ba5470a00b411fa4cdaab691e37a6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/TextareaJsonElement.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON textarea - */ -class TextareaJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-textarea'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'cols' => 40, - 'rows' => 5 - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autofocus', - 'cols', - 'disabled', - 'inputmode', - 'maxlength', - 'minlength', - 'name', - 'placeholder', - 'readonly', - 'required', - 'rows', - 'selectionDirection', - 'selectionEnd', - 'selectionStart', - 'text', - 'wrap' - ]; - - /** - * Set the attributes according to the allowed attributes of this element - * - * @param array $parameters Configuration array - * @return void - */ - protected function setAttributes(array $parameters) - { - parent::setAttributes($parameters); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/TextblockJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/TextblockJsonElement.php deleted file mode 100644 index 970a5d055bd05cd432ace8685ecbb2b1c9915ce0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/TextblockJsonElement.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON textblock - */ -class TextblockJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-content-textblock'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [], - 'various' => [ - 'text' => '' - ] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'class', - 'dir', - 'id', - 'lang', - 'style', - 'title' - ]; - - /** - * Set all the parameters for this object - * - * @param array $parameters Configuration array - * @return void - * @see \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement::setParameters() - */ - public function setParameters(array $parameters) - { - parent::setParameters($parameters); - $this->setVarious($parameters); - } - - /** - * Set the various properties for the element - * - * For this element this is the headingsize and the value - * - * @param array $parameters Configuration array - * @return void - */ - protected function setVarious(array $parameters) - { - if (isset($parameters['text'])) { - $this->configuration['various']['text'] = $parameters['text']; - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Json/TextlineJsonElement.php b/typo3/sysext/form/Classes/Domain/Model/Json/TextlineJsonElement.php deleted file mode 100644 index f4ea76428c2e4c175f624b64200d5d3435d446be..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/Json/TextlineJsonElement.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model\Json; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * JSON textline - */ -class TextlineJsonElement extends \TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement -{ - /** - * The ExtJS xtype of the element - * - * @var string - */ - public $xtype = 'typo3-form-wizard-elements-basic-textline'; - - /** - * The configuration array for the xtype - * - * @var array - */ - public $configuration = [ - 'attributes' => [ - 'type' => 'text' - ], - 'filters' => [], - 'label' => [ - 'value' => '' - ], - 'layout' => 'front', - 'validation' => [] - ]; - - /** - * Allowed attributes for this object - * - * @var array - */ - protected $allowedAttributes = [ - 'accesskey', - 'class', - 'contenteditable', - 'contextmenu', - 'dir', - 'draggable', - 'dropzone', - 'hidden', - 'id', - 'lang', - 'spellcheck', - 'style', - 'tabindex', - 'title', - 'translate', - /* element specific attributes */ - 'autocomplete', - 'autofocus', - 'disabled', - 'inputmode', - 'list', - 'maxlength', - 'minlength', - 'name', - 'pattern', - 'placeholder', - 'readonly', - 'required', - 'size', - 'type', - 'value' - ]; -} diff --git a/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php b/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php new file mode 100644 index 0000000000000000000000000000000000000000..adda0931a113168023a797ec64c58676ba34fdb1 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php @@ -0,0 +1,210 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Renderable; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Model\Exception\FormDefinitionConsistencyException; + +/** + * Convenience base class which implements common functionality for most + * classes which implement CompositeRenderableInterface, i.e. have **child renderable elements**. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +abstract class AbstractCompositeRenderable extends AbstractRenderable implements CompositeRenderableInterface +{ + + /** + * array of child renderables + * + * @var \TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface[] + */ + protected $renderables = []; + + /** + * Add a renderable to the list of child renderables. + * + * This function will be wrapped by the subclasses, f.e. with an "addPage" + * or "addElement" method with the correct type hint. + * + * @param RenderableInterface $renderable + * @return void + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function addRenderable(RenderableInterface $renderable) + { + if ($renderable->getParentRenderable() !== null) { + throw new FormDefinitionConsistencyException(sprintf('The renderable with identifier "%s" is already added to another element (element identifier: "%s").', $renderable->getIdentifier(), $renderable->getParentRenderable()->getIdentifier()), 1325665144); + } + $renderable->setIndex(count($this->renderables)); + $renderable->setParentRenderable($this); + $this->renderables[] = $renderable; + } + + /** + * Move $renderableToMove before $referenceRenderable + * + * This function will be wrapped by the subclasses, f.e. with an "movePageBefore" + * or "moveElementBefore" method with the correct type hint. + * + * @param RenderableInterface $renderableToMove + * @param RenderableInterface $referenceRenderable + * @return void + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function moveRenderableBefore(RenderableInterface $renderableToMove, RenderableInterface $referenceRenderable) + { + if ($renderableToMove->getParentRenderable() !== $referenceRenderable->getParentRenderable() || $renderableToMove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('Moved renderables need to be part of the same parent element.', 1326089744); + } + + $reorderedRenderables = []; + $i = 0; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToMove) { + continue; + } + + if ($renderable === $referenceRenderable) { + $reorderedRenderables[] = $renderableToMove; + $renderableToMove->setIndex($i); + $i++; + } + $reorderedRenderables[] = $renderable; + $renderable->setIndex($i); + $i++; + } + $this->renderables = $reorderedRenderables; + } + + /** + * Move $renderableToMove after $referenceRenderable + * + * This function will be wrapped by the subclasses, f.e. with an "movePageAfter" + * or "moveElementAfter" method with the correct type hint. + * + * @param RenderableInterface $renderableToMove + * @param RenderableInterface $referenceRenderable + * @return void + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function moveRenderableAfter(RenderableInterface $renderableToMove, RenderableInterface $referenceRenderable) + { + if ($renderableToMove->getParentRenderable() !== $referenceRenderable->getParentRenderable() || $renderableToMove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('Moved renderables need to be part of the same parent element.', 1477083145); + } + + $reorderedRenderables = []; + $i = 0; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToMove) { + continue; + } + + $reorderedRenderables[] = $renderable; + $renderable->setIndex($i); + $i++; + + if ($renderable === $referenceRenderable) { + $reorderedRenderables[] = $renderableToMove; + $renderableToMove->setIndex($i); + $i++; + } + } + $this->renderables = $reorderedRenderables; + } + + /** + * Returns all RenderableInterface instances of this composite renderable recursively + * + * @return RenderableInterface[] + * @internal + */ + public function getRenderablesRecursively(): array + { + $renderables = []; + foreach ($this->renderables as $renderable) { + $renderables[] = $renderable; + if ($renderable instanceof CompositeRenderableInterface) { + $renderables = array_merge($renderables, $renderable->getRenderablesRecursively()); + } + } + return $renderables; + } + + /** + * Remove a renderable from this renderable. + * + * This function will be wrapped by the subclasses, f.e. with an "removePage" + * or "removeElement" method with the correct type hint. + * + * @param RenderableInterface $renderableToRemove + * @return void + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function removeRenderable(RenderableInterface $renderableToRemove) + { + if ($renderableToRemove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('The renderable to be removed must be part of the calling parent renderable.', 1326090127); + } + + $updatedRenderables = []; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToRemove) { + continue; + } + + $updatedRenderables[] = $renderable; + } + $this->renderables = $updatedRenderables; + + $renderableToRemove->onRemoveFromParentRenderable(); + } + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @return void + * @internal + */ + public function registerInFormIfPossible() + { + parent::registerInFormIfPossible(); + foreach ($this->renderables as $renderable) { + $renderable->registerInFormIfPossible(); + } + } + + /** + * This function is called after a renderable has been removed from its parent + * renderable. + * This just passes the event down to all child renderables of this composite renderable. + * + * @return void + * @internal + */ + public function onRemoveFromParentRenderable() + { + foreach ($this->renderables as $renderable) { + $renderable->onRemoveFromParentRenderable(); + } + parent::onRemoveFromParentRenderable(); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractRenderable.php b/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractRenderable.php new file mode 100644 index 0000000000000000000000000000000000000000..9bfbb596e14155265a26e6ec8f9214cba132f922 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Renderable/AbstractRenderable.php @@ -0,0 +1,423 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Renderable; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface; +use TYPO3\CMS\Form\Domain\Model\Exception\FormDefinitionConsistencyException; +use TYPO3\CMS\Form\Domain\Model\Exception\ValidatorPresetNotFoundException; +use TYPO3\CMS\Form\Domain\Model\FormDefinition; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; +use TYPO3\CMS\Form\Utility\ArrayUtility as FormArrayUtility; + +/** + * Convenience base class which implements common functionality for most + * classes which implement RenderableInterface. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +abstract class AbstractRenderable implements RenderableInterface +{ + + /** + * Abstract "type" of this Renderable. Is used during the rendering process + * to determine the template file or the View PHP class being used to render + * the particular element. + * + * @var string + */ + protected $type; + + /** + * The identifier of this renderable + * + * @var string + */ + protected $identifier; + + /** + * The parent renderable + * + * @var CompositeRenderableInterface + */ + protected $parentRenderable; + + /** + * The label of this renderable + * + * @var string + */ + protected $label = ''; + + /** + * associative array of rendering options + * + * @var array + */ + protected $renderingOptions = []; + + /** + * Renderer class name to be used for this renderable. + * + * Is only set if a specific renderer should be used for this renderable, + * if it is NULL the caller needs to determine the renderer or take care + * of the rendering itself. + * + * @var string + */ + protected $rendererClassName = null; + + /** + * The position of this renderable inside the parent renderable. + * + * @var int + */ + protected $index = 0; + + /** + * Get the type of the renderable + * + * @return string + * @api + */ + public function getType(): string + { + return $this->type; + } + + /** + * Get the identifier of the element + * + * @return string + * @api + */ + public function getIdentifier(): string + { + return $this->identifier; + } + + /** + * Set multiple properties of this object at once. + * Every property which has a corresponding set* method can be set using + * the passed $options array. + * + * @param array $options + * @return void + * @api + */ + public function setOptions(array $options) + { + if (isset($options['label'])) { + $this->setLabel($options['label']); + } + + if (isset($options['defaultValue'])) { + $this->setDefaultValue($options['defaultValue']); + } + + if (isset($options['properties'])) { + foreach ($options['properties'] as $key => $value) { + $this->setProperty($key, $value); + } + } + + if (isset($options['rendererClassName'])) { + $this->setRendererClassName($options['rendererClassName']); + } + + if (isset($options['renderingOptions'])) { + foreach ($options['renderingOptions'] as $key => $value) { + if (is_array($value)) { + $currentValue = isset($this->getRenderingOptions()[$key]) ? $this->getRenderingOptions()[$key] : []; + ArrayUtility::mergeRecursiveWithOverrule($currentValue, $value); + $this->setRenderingOption($key, $currentValue); + } else { + $this->setRenderingOption($key, $value); + } + } + } + + if (isset($options['validators'])) { + foreach ($options['validators'] as $validatorConfiguration) { + $this->createValidator($validatorConfiguration['identifier'], isset($validatorConfiguration['options']) ? $validatorConfiguration['options'] : []); + } + } + + FormArrayUtility::assertAllArrayKeysAreValid($options, ['label', 'defaultValue', 'properties', 'rendererClassName', 'renderingOptions', 'validators', 'formEditor']); + } + + /** + * Create a validator for the element + * + * @param string $validatorIdentifier + * @param array $options + * @return mixed + * @throws ValidatorPresetNotFoundException + * @api + */ + public function createValidator(string $validatorIdentifier, array $options = []) + { + $validatorsDefinition = $this->getRootForm()->getValidatorsDefinition(); + if (isset($validatorsDefinition[$validatorIdentifier]) && is_array($validatorsDefinition[$validatorIdentifier]) && isset($validatorsDefinition[$validatorIdentifier]['implementationClassName'])) { + $implementationClassName = $validatorsDefinition[$validatorIdentifier]['implementationClassName']; + $defaultOptions = isset($validatorsDefinition[$validatorIdentifier]['options']) ? $validatorsDefinition[$validatorIdentifier]['options'] : []; + + ArrayUtility::mergeRecursiveWithOverrule($defaultOptions, $options); + + $validator = GeneralUtility::makeInstance(ObjectManager::class) + ->get($implementationClassName, $defaultOptions); + $this->addValidator($validator); + return $validator; + } else { + throw new ValidatorPresetNotFoundException('The validator preset identified by "' . $validatorIdentifier . '" could not be found, or the implementationClassName was not specified.', 1328710202); + } + } + + /** + * Add a validator to the element + * + * @param ValidatorInterface $validator + * @return void + * @api + */ + public function addValidator(ValidatorInterface $validator) + { + $formDefinition = $this->getRootForm(); + $formDefinition->getProcessingRule($this->getIdentifier())->addValidator($validator); + } + + /** + * Get all validators on the element + * + * @return \SplObjectStorage + * @internal + */ + public function getValidators(): \SplObjectStorage + { + $formDefinition = $this->getRootForm(); + return $formDefinition->getProcessingRule($this->getIdentifier())->getValidators(); + } + + /** + * Set the datatype + * + * @param string $dataType + * @return void + * @api + */ + public function setDataType(string $dataType) + { + $formDefinition = $this->getRootForm(); + $formDefinition->getProcessingRule($this->getIdentifier())->setDataType($dataType); + } + + /** + * Set the renderer class name + * + * @param string $rendererClassName + * @return void + * @api + */ + public function setRendererClassName(string $rendererClassName) + { + $this->rendererClassName = $rendererClassName; + } + + /** + * Get the classname of the renderer + * + * @return null|string + * @api + */ + public function getRendererClassName() + { + return $this->rendererClassName; + } + + /** + * Get all rendering options + * + * @return array + * @api + */ + public function getRenderingOptions(): array + { + return $this->renderingOptions; + } + + /** + * Set the rendering option $key to $value. + * + * @param string $key + * @param mixed $value + * @return mixed + * @api + */ + public function setRenderingOption(string $key, $value) + { + $this->renderingOptions[$key] = $value; + } + + /** + * Get the parent renderable + * + * @return null|CompositeRenderableInterface + * @return void + * @api + */ + public function getParentRenderable() + { + return $this->parentRenderable; + } + + /** + * Set the parent renderable + * + * @param CompositeRenderableInterface $parentRenderable + * @return void + * @api + */ + public function setParentRenderable(CompositeRenderableInterface $parentRenderable) + { + $this->parentRenderable = $parentRenderable; + $this->registerInFormIfPossible(); + } + + /** + * Get the root form this element belongs to + * + * @return FormDefinition + * @throws FormDefinitionConsistencyException + * @api + */ + public function getRootForm(): FormDefinition + { + $rootRenderable = $this->parentRenderable; + while ($rootRenderable !== null && !($rootRenderable instanceof FormDefinition)) { + $rootRenderable = $rootRenderable->getParentRenderable(); + } + if ($rootRenderable === null) { + throw new FormDefinitionConsistencyException(sprintf('The form element "%s" is not attached to a parent form.', $this->identifier), 1326803398); + } + + return $rootRenderable; + } + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @return void + * @internal + */ + public function registerInFormIfPossible() + { + try { + $rootForm = $this->getRootForm(); + $rootForm->registerRenderable($this); + } catch (FormDefinitionConsistencyException $exception) { + } + } + + /** + * Triggered when the renderable is removed from it's parent + * + * @return void + * @internal + */ + public function onRemoveFromParentRenderable() + { + try { + $rootForm = $this->getRootForm(); + $rootForm->unregisterRenderable($this); + } catch (FormDefinitionConsistencyException $exception) { + } + $this->parentRenderable = null; + } + + /** + * Get the index of the renderable + * + * @return int + * @internal + */ + public function getIndex(): int + { + return $this->index; + } + + /** + * Set the index of the renderable + * + * @param int $index + * @return void + * @internal + */ + public function setIndex(int $index) + { + $this->index = $index; + } + + /** + * Get the label of the renderable + * + * @return string + * @api + */ + public function getLabel(): string + { + return $this->label; + } + + /** + * Set the label which shall be displayed next to the form element + * + * @param string $label + * @return void + * @api + */ + public function setLabel(string $label) + { + $this->label = $label; + } + + /** + * Override this method in your custom Renderable if needed + * + * @param FormRuntime $formRuntime + * @return void + * @api + */ + public function beforeRendering(FormRuntime $formRuntime) + { + } + + /** + * This is a callback that is invoked by the Form Factory after the whole form has been built. + * It can be used to add new form elements as children for complex form elements. + * + * Override this method in your custom Renderable if needed. + * + * @return void + * @api + */ + public function onBuildingFinished() + { + } +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php b/typo3/sysext/form/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4e15db0f0344f4b65974b67626f52cfdf53afc9a --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php @@ -0,0 +1,35 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Renderable; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Interface which all Form Parts must adhere to **when they have sub elements**. + * This includes especially "FormDefinition" and "Page". + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +interface CompositeRenderableInterface extends RenderableInterface +{ + + /** + * Returns all RenderableInterface instances of this composite renderable recursively + * + * @return \TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface[] + * @internal + */ + public function getRenderablesRecursively(): array; +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Renderable/RenderableInterface.php b/typo3/sysext/form/Classes/Domain/Model/Renderable/RenderableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f473dfad8fa0939155106c26d9801d6b2f83806d --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Renderable/RenderableInterface.php @@ -0,0 +1,92 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Renderable; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Base interface which all Form Parts except the FormDefinition must adhere + * to (i.e. all elements which are NOT the root of a Form). + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +interface RenderableInterface extends RootRenderableInterface +{ + + /** + * Return the parent renderable + * + * @return null|CompositeRenderableInterface the parent renderable + * @internal + */ + public function getParentRenderable(); + + /** + * Set the new parent renderable. You should not call this directly; + * it is automatically called by addRenderable. + * + * This method should also register itself at the parent form, if possible. + * + * @param CompositeRenderableInterface $renderable + * @return void + * @internal + */ + public function setParentRenderable(CompositeRenderableInterface $renderable); + + /** + * Set the index of this renderable inside the parent renderable + * + * @param int $index + * @return void + * @internal + */ + public function setIndex(int $index); + + /** + * Get the index inside the parent renderable + * + * @return int + * @api + */ + public function getIndex(): int; + + /** + * This function is called after a renderable has been removed from its parent + * renderable. The function should make sure to clean up the internal state, + * like reseting $this->parentRenderable or deregistering the renderable + * at the form. + * + * @return void + * @internal + */ + public function onRemoveFromParentRenderable(); + + /** + * This is a callback that is invoked by the Form Factory after the whole form has been built. + * It can be used to add new form elements as children for complex form elements. + * + * @return void + * @api + */ + public function onBuildingFinished(); + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @return void + * @internal + */ + public function registerInFormIfPossible(); +} diff --git a/typo3/sysext/form/Classes/Domain/Model/Renderable/RootRenderableInterface.php b/typo3/sysext/form/Classes/Domain/Model/Renderable/RootRenderableInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e0ece97b35970e0f9a3e8a81933822858f2142d6 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Model/Renderable/RootRenderableInterface.php @@ -0,0 +1,86 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Model\Renderable; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * Base interface which all parts of a form must adhere to. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + */ +interface RootRenderableInterface +{ + + /** + * Abstract "type" of this Renderable. Is used during the rendering process + * to determine the template file or the View PHP class being used to render + * the particular element. + * + * @return string + * @api + */ + public function getType(): string; + + /** + * The identifier of this renderable + * + * @return string + * @api + */ + public function getIdentifier(): string; + + /** + * Get the label which shall be displayed next to the form element + * + * @return string + * @api + */ + public function getLabel(): string; + + /** + * This is a callback that is invoked by the Renderer before the corresponding element is rendered. + * Use this to access previously submitted values and/or modify the $formRuntime before an element + * is outputted to the browser. + * + * @param FormRuntime $formRuntime + * @return void + * @api + */ + public function beforeRendering(FormRuntime $formRuntime); + + /** + * Get the renderer class name to be used to display this renderable; + * must implement RendererInterface + * + * Is only set if a specific renderer should be used for this renderable, + * if it is NULL the caller needs to determine the renderer or take care + * of the renderer itself. + * + * @return null|string the renderer class name + * @api + */ + public function getRendererClassName(); + + /** + * Get all rendering options + * + * @return array associative array of rendering options + * @api + */ + public function getRenderingOptions(): array; +} diff --git a/typo3/sysext/form/Classes/Domain/Model/ValidationElement.php b/typo3/sysext/form/Classes/Domain/Model/ValidationElement.php deleted file mode 100644 index 15812fc2c8c1fdfc860586ded8b73e2e99b74a73..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Model/ValidationElement.php +++ /dev/null @@ -1,89 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Model; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\DomainObject\AbstractEntity; - -/** - * The ValidationElement Domain Model represents the low-level - * view on the user submitted data in a flat hierarchy. - */ -class ValidationElement extends AbstractEntity -{ - /** - * This array holds all the field from the request - * - * @var array - */ - protected $incomingFields; - - /** - * Return a array with all the fields from the request - * - * @return array - */ - public function getIncomingFields() - { - return $this->incomingFields; - } - - /** - * Sets a array with all the fields from the request - * - * @param array $incomingFields - * @return void - */ - public function setIncomingFields($incomingFields = []) - { - $this->incomingFields = $incomingFields; - } - - /** - * Get a single fields from the request - * - * @param string $key - * @return mixed - */ - public function getIncomingField($key = '') - { - return $this->incomingFields[$key]; - } - - /** - * Set a single fields from the request - * - * @param string $key - * @param mixed $value - * @return array - */ - public function setIncomingField($key = '', $value = null) - { - $this->incomingFields[$key] = $value; - } - - /** - * Determines whether a field is part of the incoming fields. - * - * @param string $key The key of the field to be looked up - * @return bool - */ - public function hasIncomingField($key) - { - return - isset($this->incomingFields[$key]) - || array_key_exists($key, $this->incomingFields) - ; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Property/TypeConverter/ArrayToValidationElementConverter.php b/typo3/sysext/form/Classes/Domain/Property/TypeConverter/ArrayToValidationElementConverter.php deleted file mode 100644 index f5e0b1824b9cadb8ec4a127edc8cec22cde0c7c3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Property/TypeConverter/ArrayToValidationElementConverter.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Property\TypeConverter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface; -use TYPO3\CMS\Extbase\Property\TypeConverter\AbstractTypeConverter; -use TYPO3\CMS\Form\Domain\Model\ValidationElement; - -/** - * The form wizard controller - */ -class ArrayToValidationElementConverter extends AbstractTypeConverter -{ - /** - * @var array<string> - */ - protected $sourceTypes = ['array']; - - /** - * @var string - */ - protected $targetType = 'TYPO3\\CMS\\Form\\Domain\\Model\\ValidationElement'; - - /** - * @var int - */ - protected $priority = 1; - - /** - * We can only convert empty strings to array or array to array. - * - * @param mixed $source - * @param string $targetType - * @return bool - */ - public function canConvertFrom($source, $targetType) - { - return is_array($source); - } - - /** - * Convert the incoming array to a ValidationElement - * - * @param array $source - * @param string $targetType - * @param array $convertedChildProperties - * @param PropertyMappingConfigurationInterface $configuration - * @return ValidationElement - * @api - */ - public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null) - { - /** @var ValidationElement $validationElement */ - $validationElement = GeneralUtility::makeInstance(ValidationElement::class); - if (is_array($source)) { - /** - * Find uploaded files. - * - * Extbase has already mapped the $_FILES data into the request - * @see TYPO3\CMS\Extbase\Mvc\Web\Request::build() - * If a $_FILES array is found in the request data ($source), - * set the file mime type with - * \TYPO3\CMS\Core\Type\File\FileInfo - * and write the data back into $source. - */ - foreach ($source as $propertyName => $value) { - if (is_array($value)) { - $uploadedFiles = []; - if ( - isset($value['name']) - && isset($value['type']) - && isset($value['tmp_name']) - && isset($value['size']) - ) { - // if single file upload - cast to array - $uploadedFiles[] = $value; - } elseif ( - isset($value[0]['name']) - && isset($value[0]['type']) - && isset($value[0]['tmp_name']) - && isset($value[0]['size']) - ) { - // multi file upload - $uploadedFiles = $value; - } - - if (!empty($uploadedFiles)) { - foreach ($uploadedFiles as $key => &$file) { - if ( - $file['name'] === '' - && $file['type'] === '' - && $file['tmp_name'] === '' - && $file['size'] === 0 - ) { - unset($uploadedFiles[$key]); - continue; - } - $fileInfo = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Type\File\FileInfo::class, $file['tmp_name']); - $file['type'] = $fileInfo->getMimeType(); - $file['name'] = htmlspecialchars($file['name']); - } - $source[$propertyName] = $uploadedFiles; - } - } - } - $validationElement->setIncomingFields($source); - } - - return $validationElement; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Renderer/AbstractElementRenderer.php b/typo3/sysext/form/Classes/Domain/Renderer/AbstractElementRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..ba766239fc43cd110a6de444076c358e2767cdf0 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Renderer/AbstractElementRenderer.php @@ -0,0 +1,73 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Renderer; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * Abstract renderer which can be used as base class for custom renderers. + * + * Scope: frontend + * **This class is meant to be sub classed by developers**. + * @api + */ +abstract class AbstractElementRenderer implements RendererInterface +{ + + /** + * The assigned controller context which might be needed by the renderer. + * + * @var \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext + * @api + */ + protected $controllerContext; + + /** + * @var \TYPO3\CMS\Form\Domain\Runtime\FormRuntime + * @api + */ + protected $formRuntime; + + /** + * Set the controller context which should be used + * + * @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext + * @api + */ + public function setControllerContext(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext) + { + $this->controllerContext = $controllerContext; + } + + /** + * @param FormRuntime $formRuntime + * @return void + * @api + */ + public function setFormRuntime(FormRuntime $formRuntime) + { + $this->formRuntime = $formRuntime; + } + + /** + * @return FormRuntime + * @api + */ + public function getFormRuntime(): FormRuntime + { + return $this->formRuntime; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Renderer/FluidFormRenderer.php b/typo3/sysext/form/Classes/Domain/Renderer/FluidFormRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..0f2311d6696664e6220dc22254fa62cbb312a5de --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Renderer/FluidFormRenderer.php @@ -0,0 +1,54 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Renderer; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Mvc\View\FormView; + +/** + * A renderer which render all renderables within the $formRuntime. + * All the work is done within FormView::class. + * This is just a proxy class to make the rendering process more clear. + * See the documentation within FormView::class for additional information. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +class FluidFormRenderer extends AbstractElementRenderer implements RendererInterface +{ + + /** + * Initialize the FormView::class and render the this->formRuntime. + * This method is expected to invoke the beforeRendering() callback + * on each $renderable. This is done within FormView::class. + * + * @param RootRenderableInterface $renderable + * @return string the rendered $formRuntime + * @internal + */ + public function render(RootRenderableInterface $renderable): string + { + $formView = GeneralUtility::makeInstance(ObjectManager::class) + ->get(FormView::class); + + $formView->setFormRuntime($this->formRuntime); + $formView->setControllerContext($this->controllerContext); + return $formView->renderRenderable($renderable); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Renderer/RendererInterface.php b/typo3/sysext/form/Classes/Domain/Renderer/RendererInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e67416ee429794c5fba272e8980ba095d34bc791 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Renderer/RendererInterface.php @@ -0,0 +1,62 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Renderer; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * Base interface for Renderers. A Renderer is used to render a renderable. + * + * Scope: frontend + * **This interface is meant to be implemented by developers, although often you + * will subclass AbstractElementRenderer** ({@link AbstractElementRenderer}). + */ +interface RendererInterface +{ + + /** + * Set the controller context which should be used + * + * @param ControllerContext $controllerContext + * @api + */ + public function setControllerContext(ControllerContext $controllerContext); + + /** + * Note: This method is expected to invoke the beforeRendering() callback + * on each $renderable + * + * @param RootRenderableInterface $renderable + * @return string the rendered $formRuntime + * @api + */ + public function render(RootRenderableInterface $renderable): string; + + /** + * @param FormRuntime $formRuntime + * @return void + * @api + */ + public function setFormRuntime(FormRuntime $formRuntime); + + /** + * @return FormRuntime + * @api + */ + public function getFormRuntime(): FormRuntime; +} diff --git a/typo3/sysext/form/Classes/Domain/Renderer/UnknownFormElementRenderer.php b/typo3/sysext/form/Classes/Domain/Renderer/UnknownFormElementRenderer.php new file mode 100644 index 0000000000000000000000000000000000000000..4dfefee55a4d9c63e7f340f5a82e4144d5698856 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Renderer/UnknownFormElementRenderer.php @@ -0,0 +1,72 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Renderer; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotFoundException; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; + +/** + * Renderer for unknown Form Elements + * This is used to render Form Elements without definition depending on the context: + * In "preview mode" (e.g. inside the FormEditor) a div with an error message is rendered + * If previewMode is FALSE this will return an empty string if the rendering Option "skipUnknownElements" is TRUE for + * the form, or throw an Exception otherwise. + * + * Scope: frontend + */ +class UnknownFormElementRenderer extends AbstractElementRenderer +{ + + /** + * This renders the given $renderable depending on the context: + * In preview Mode this returns an error message. Otherwise this throws an exception or returns an empty string + * depending on the "skipUnknownElements" rendering option + * + * @param RootRenderableInterface $renderable + * @return string the rendered $renderable + * @throws TypeDefinitionNotFoundException + * @internal + */ + public function render(RootRenderableInterface $renderable): string + { + $renderingOptions = $this->formRuntime->getRenderingOptions(); + $previewMode = isset($renderingOptions['previewMode']) && $renderingOptions['previewMode'] === true; + if ($previewMode) { + return sprintf('<div class="t3-form-unknown-element" data-element-identifier-path="%s"><em>Unknown Form Element "%s"</em></div>', htmlspecialchars($this->getRenderablePath($renderable)), htmlspecialchars($renderable->getType())); + } + $skipUnknownElements = isset($renderingOptions['skipUnknownElements']) && $renderingOptions['skipUnknownElements'] === true; + if (!$skipUnknownElements) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $renderable->getType()), 1382364019); + } + return ''; + } + + /** + * Returns the path of a $renderable in the format <formIdentifier>/<sectionIdentifier>/<sectionIdentifier>/.../<elementIdentifier> + * + * @param RootRenderableInterface $renderable + * @return string + * @internal + */ + protected function getRenderablePath(RootRenderableInterface $renderable): string + { + $path = $renderable->getIdentifier(); + while ($renderable = $renderable->getParentRenderable()) { + $path = $renderable->getIdentifier() . '/' . $path; + } + return $path; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Repository/ContentRepository.php b/typo3/sysext/form/Classes/Domain/Repository/ContentRepository.php deleted file mode 100644 index ee488067f5292b5ec011fdb41941f8a2388d5be6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Repository/ContentRepository.php +++ /dev/null @@ -1,129 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Repository; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Factory\JsonToTypoScript; -use TYPO3\CMS\Form\Domain\Model\Content; -use TYPO3\CMS\Form\Utility\TypoScriptToJsonConverter; - -/** - * Repository for \TYPO3\CMS\Form\Domain\Model\Content - */ -class ContentRepository -{ - /** - * Get the referenced record from the database - * - * Using the GET or POST variable 'P' - * - * @param null|int $recordId - * @param null|string $table - * @return bool|Content if found, FALSE if not - */ - public function getRecord($recordId = null, $table = null) - { - $record = false; - $getPostVariables = GeneralUtility::_GP('P'); - if (!$table) { - $table = 'tt_content'; - } - - if (!$recordId) { - $recordId = (int)$getPostVariables['uid']; - } - - if ((int)$recordId === 0) { - /** @var $typoScriptParser TypoScriptParser */ - $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class); - $typoScriptParser->parse(''); - /** @var $record Content */ - $record = GeneralUtility::makeInstance(Content::class); - $record->setUid(0); - $record->setPageId(0); - $record->setTyposcript($typoScriptParser->setup); - $record->setBodytext(''); - - return $record; - } - - $row = BackendUtility::getRecord($table, (int)$recordId); - if (is_array($row)) { - // strip off the leading "[Translate to XY]" text after localizing the original record - $languageField = $GLOBALS['TCA']['tt_content']['ctrl']['languageField']; - $transOrigPointerField = $GLOBALS['TCA']['tt_content']['ctrl']['transOrigPointerField']; - if ($row[$languageField] > 0 && $row[$transOrigPointerField] > 0) { - $bodytext = preg_replace('/^\[.*?\] /', '', $row['bodytext'], 1); - } else { - $bodytext = $row['bodytext']; - } - - /** @var $typoScriptParser TypoScriptParser */ - $typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class); - $typoScriptParser->parse($bodytext); - /** @var $record Content */ - $record = GeneralUtility::makeInstance(Content::class); - $record->setUid($row['uid']); - $record->setPageId($row['pid']); - $record->setTyposcript($typoScriptParser->setup); - $record->setBodytext($bodytext); - } - return $record; - } - - /** - * Check if the referenced record exists - * - * @return bool TRUE if record exists, FALSE if not - */ - public function hasRecord() - { - return $this->getRecord() !== false; - } - - /** - * Convert the incoming data of the FORM wizard - * - * @return string $typoscript after conversion - */ - public function save() - { - $json = GeneralUtility::_GP('configuration'); - /** @var $converter JsonToTypoScript */ - $converter = GeneralUtility::makeInstance(JsonToTypoScript::class); - $typoscript = $converter->convert($json); - return $typoscript; - } - - /** - * Read and convert the content record to JSON - * - * @return string The JSON object if record exists, FALSE if not - */ - public function getRecordAsJson() - { - $json = false; - $record = $this->getRecord(); - if ($record) { - $typoscript = $record->getTyposcript(); - /** @var $converter TypoScriptToJsonConverter */ - $converter = GeneralUtility::makeInstance(TypoScriptToJsonConverter::class); - $json = $converter->convert($typoscript); - } - return $json; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Repository/TypoScriptRepository.php b/typo3/sysext/form/Classes/Domain/Repository/TypoScriptRepository.php deleted file mode 100644 index 88964381e5f5a7fcb89f624e45bf80c08e4ad91d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Repository/TypoScriptRepository.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Repository; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\SingletonInterface; -use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser; -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * Provide the TypoScript data-source - */ -class TypoScriptRepository implements SingletonInterface -{ - /** - * @var array - */ - protected $modelDefinitionTypoScript = []; - - /** - * @var array - */ - protected $registeredElementTypes = []; - - /** - * @var \TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser - */ - protected $typoScriptParser; - - /** - * The constructor - */ - public function __construct() - { - $this->typoScriptParser = GeneralUtility::makeInstance(TypoScriptParser::class); - $this->modelDefinitionTypoScript = $this->resolveTypoScriptReferences( - $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_form.'] - ); - $this->setRegisteredElementTypes(); - } - - /** - * Get all registered form elements - * - * @return array - */ - public function getRegisteredElementTypes() - { - return $this->registeredElementTypes; - } - - /** - * Set all registered form elements - * - * @param array $registeredElementTypes - * @return void - * @throws \InvalidArgumentException - */ - public function setRegisteredElementTypes(array $registeredElementTypes = []) - { - if (!empty($registeredElementTypes)) { - $this->registeredElementTypes = $registeredElementTypes; - } else { - if (!isset($this->modelDefinitionTypoScript['settings.']['registeredElements.'])) { - throw new \InvalidArgumentException('There are no registeredElements available.', 1441791615); - } - $registeredElements = $this->modelDefinitionTypoScript['settings.']['registeredElements.']; - foreach ($registeredElements as $registeredElementKey => $value) { - $registeredElementKey = rtrim($registeredElementKey, '.'); - $this->registeredElementTypes[] = $registeredElementKey; - } - } - } - - /** - * Get the html attributes defined by the model - * with their default values - * - * @param string $elementType - * @return array - */ - public function getModelDefinedHtmlAttributes($elementType = '') - { - if ($elementType == '') { - return []; - } - $htmlAttributes = $this->getModelConfigurationByScope($elementType, 'htmlAttributes.'); - if (is_array($htmlAttributes)) { - $htmlAttributes = array_fill_keys($htmlAttributes, null); - } else { - $htmlAttributes = []; - } - $defaultHtmlAttributeValues = $this->getModelConfigurationByScope($elementType, 'defaultHtmlAttributeValues.'); - if (is_array($defaultHtmlAttributeValues)) { - foreach ($defaultHtmlAttributeValues as $defaultHtmlAttributeKey => $defaultHtmlAttributeValue) { - $htmlAttributes[$defaultHtmlAttributeKey] = $defaultHtmlAttributeValue; - } - } elseif (!is_array($htmlAttributes)) { - $htmlAttributes = []; - } - return $htmlAttributes; - } - - /** - * Get the default fluid template for a element. - * - * @param string $elementType - * @param string $partialType - * @return string - */ - public function getDefaultFluidTemplate($elementType, $partialType = 'partialPath') - { - $partialPath = $this->getModelConfigurationByScope($elementType, $partialType); - if ($partialPath) { - return $partialPath; - } - return ''; - } - - /** - * Get the model definition from TypoScript for a specific scope. - * - * @param string $elementType - * @param string $scope - * @return mixed - */ - public function getModelConfigurationByScope($elementType, $scope) - { - if (isset($this->modelDefinitionTypoScript['settings.']['registeredElements.'][$elementType . '.'][$scope])) { - return $this->modelDefinitionTypoScript['settings.']['registeredElements.'][$elementType . '.'][$scope]; - } - return null; - } - - /** - * Get a registered class name by a - * specific scope (validator or filter) - * - * @param string $name - * @param string $scope (registeredValidators, registeredFilters) - * @return mixed - */ - public function getRegisteredClassName($name, $scope) - { - $name = strtolower($name); - if (isset($this->modelDefinitionTypoScript['settings.'][$scope . '.'][$name . '.']['className'])) { - return $this->modelDefinitionTypoScript['settings.'][$scope . '.'][$name . '.']['className']; - } - return null; - } - - /** - * Render a TypoScript and resolve all references (eg. " < plugin.tx_form...") recursively - * - * @param array $typoScript - * @return array - * @todo Extract to core then... - */ - protected function resolveTypoScriptReferences(array $typoScript) - { - $ignoreKeys = []; - foreach ($typoScript as $key => $value) { - if (isset($ignoreKeys[$key])) { - continue; - } - // i am a reference - if ($value[0] === '<') { - if (isset($typoScript[$key . '.'])) { - $oldTypoScript = $typoScript[$key . '.']; - } else { - $oldTypoScript = []; - } - // detect search level - $referencePath = trim(substr($value, 1)); - $dotPosition = strpos($referencePath, '.'); - if ($dotPosition === 0) { - // same position x =< .y - list($flatValue, $arrayValue) = $this->typoScriptParser->getVal(substr($referencePath, 1), $typoScript); - } else { - list($flatValue, $arrayValue) = $this->typoScriptParser->getVal($referencePath, $GLOBALS['TSFE']->tmpl->setup); - } - if (is_array($arrayValue)) { - $typoScript[$key . '.'] = array_replace_recursive($arrayValue, $oldTypoScript); - } - if ($flatValue[0] === '<') { - $temporaryTypoScript = [ - 'temp' => $flatValue, - 'temp.' => $typoScript[$key . '.'], - ]; - $temporaryTypoScript = $this->resolveTypoScriptReferences($temporaryTypoScript); - $arrayValue = array_replace_recursive($temporaryTypoScript['temp.'], $arrayValue, $oldTypoScript); - } - if (is_array($arrayValue)) { - $typoScript[$key . '.'] = array_replace_recursive($arrayValue, $oldTypoScript); - } elseif (isset($flatValue)) { - $typoScript[$key] = $flatValue; - } else { - $typoScript[$key . '.'] = $oldTypoScript; - } - } - // if array, then look deeper - if (isset($typoScript[$key . '.'])) { - $ignoreKeys[$key . '.'] = true; - $typoScript[$key . '.'] = $this->resolveTypoScriptReferences($typoScript[$key . '.']); - } elseif (is_array($typoScript[$key])) { - // if array, then look deeper - $typoScript[$key] = $this->resolveTypoScriptReferences($typoScript[$key]); - } - } - return $typoScript; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Runtime/Exception/PropertyMappingException.php b/typo3/sysext/form/Classes/Domain/Runtime/Exception/PropertyMappingException.php new file mode 100644 index 0000000000000000000000000000000000000000..60a22d53867cdb2f79533c0325c3607553b70081 --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Runtime/Exception/PropertyMappingException.php @@ -0,0 +1,29 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Runtime\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception; + +/** + * This Exception is thrown in the FormRuntime if the PropertyMapper throws + * a \TYPO3\CMS\Extbase\Property\Exception. It adds some more Information to + * better understand why the PropertyMapper failed to map the properties + * + * @api + */ +class PropertyMappingException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php new file mode 100644 index 0000000000000000000000000000000000000000..395f20c0a58fca1bace3b7e120b6362292b825dd --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Runtime/FormRuntime.php @@ -0,0 +1,780 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Runtime; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Error\Result; +use TYPO3\CMS\Extbase\Mvc\Controller\Arguments; +use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; +use TYPO3\CMS\Extbase\Mvc\Web\Request; +use TYPO3\CMS\Extbase\Mvc\Web\Response; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Property\Exception as PropertyException; +use TYPO3\CMS\Extbase\Reflection\PropertyReflection; +use TYPO3\CMS\Extbase\Utility\ArrayUtility; +use TYPO3\CMS\Form\Domain\Exception\RenderingException; +use TYPO3\CMS\Form\Domain\Finishers\FinisherContext; +use TYPO3\CMS\Form\Domain\Model\FormDefinition; +use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface; +use TYPO3\CMS\Form\Domain\Model\FormElements\Page; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Renderer\RendererInterface; +use TYPO3\CMS\Form\Domain\Runtime\Exception\PropertyMappingException; +use TYPO3\CMS\Form\Mvc\Validation\EmptyValidator; +use TYPO3\CMS\Form\Utility\ArrayUtility as FormArrayUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * This class implements the *runtime logic* of a form, i.e. deciding which + * page is shown currently, what the current values of the form are, trigger + * validation and property mapping. + * + * You generally receive an instance of this class by calling {@link \TYPO3\CMS\Form\Domain\Model\FormDefinition::bind}. + * + * Rendering a Form + * ================ + * + * That's easy, just call render() on the FormRuntime: + * + * /---code php + * $form = $formDefinition->bind($request, $response); + * $renderedForm = $form->render(); + * \--- + * + * Accessing Form Values + * ===================== + * + * In order to get the values the user has entered into the form, you can access + * this object like an array: If a form field with the identifier *firstName* + * exists, you can do **$form['firstName']** to retrieve its current value. + * + * You can also set values in the same way. + * + * Rendering Internals + * =================== + * + * The FormRuntime asks the FormDefinition about the configured Renderer + * which should be used ({@link \TYPO3\CMS\Form\Domain\Model\FormDefinition::getRendererClassName}), + * and then trigger render() on this element. + * + * This makes it possible to declaratively define how a form should be rendered. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @api + */ +class FormRuntime implements RootRenderableInterface, \ArrayAccess +{ + const HONEYPOT_NAME_SESSION_IDENTIFIER = 'tx_form_honeypot_name_'; + + /** + * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface + */ + protected $objectManager; + + /** + * @var \TYPO3\CMS\Form\Domain\Model\FormDefinition + */ + protected $formDefinition; + + /** + * @var \TYPO3\CMS\Extbase\Mvc\Web\Request + */ + protected $request; + + /** + * @var \TYPO3\CMS\Extbase\Mvc\Web\Response + */ + protected $response; + + /** + * @var \TYPO3\CMS\Form\Domain\Runtime\FormState + */ + protected $formState; + + /** + * The current page is the page which will be displayed to the user + * during rendering. + * + * If $currentPage is NULL, the *last* page has been submitted and + * finishing actions need to take place. You should use $this->isAfterLastPage() + * instead of explicitely checking for NULL. + * + * @var \TYPO3\CMS\Form\Domain\Model\FormElements\Page + */ + protected $currentPage = null; + + /** + * Reference to the page which has been shown on the last request (i.e. + * we have to handle the submitted data from lastDisplayedPage) + * + * @var \TYPO3\CMS\Form\Domain\Model\FormElements\Page + */ + protected $lastDisplayedPage = null; + + /** + * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService + */ + protected $hashService; + + /** + * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService + * @return void + * @internal + */ + public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService) + { + $this->hashService = $hashService; + } + + /** + * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager + * @internal + */ + public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * @param FormDefinition $formDefinition + * @param Request $request + * @param Response $response + * @api + */ + public function __construct(FormDefinition $formDefinition, Request $request, Response $response) + { + $this->formDefinition = $formDefinition; + $arguments = $request->getArguments(); + $this->request = clone $request; + $formIdentifier = $this->formDefinition->getIdentifier(); + if (isset($arguments[$formIdentifier])) { + $this->request->setArguments($arguments[$formIdentifier]); + } + + $this->response = $response; + } + + /** + * @return void + * @internal + */ + public function initializeObject() + { + $this->initializeFormStateFromRequest(); + $this->initializeCurrentPageFromRequest(); + $this->initializeHoneypotFromRequest(); + + if (!$this->isFirstRequest() && $this->getRequest()->getMethod() === 'POST') { + $this->processSubmittedFormValues(); + } + + $this->renderHoneypot(); + } + + /** + * @return void + */ + protected function initializeFormStateFromRequest() + { + $serializedFormStateWithHmac = $this->request->getInternalArgument('__state'); + if ($serializedFormStateWithHmac === null) { + $this->formState = GeneralUtility::makeInstance(FormState::class); + } else { + $serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac); + $this->formState = unserialize(base64_decode($serializedFormState)); + } + } + + /** + * @return void + */ + protected function initializeCurrentPageFromRequest() + { + if (!$this->formState->isFormSubmitted()) { + $this->currentPage = $this->formDefinition->getPageByIndex(0); + return; + } + $this->lastDisplayedPage = $this->formDefinition->getPageByIndex($this->formState->getLastDisplayedPageIndex()); + + // We know now that lastDisplayedPage is filled + $currentPageIndex = (int)$this->request->getInternalArgument('__currentPage'); + if ($currentPageIndex > $this->lastDisplayedPage->getIndex() + 1) { + // We only allow jumps to following pages + $currentPageIndex = $this->lastDisplayedPage->getIndex() + 1; + } + + // We now know that the user did not try to skip a page + if ($currentPageIndex === count($this->formDefinition->getPages())) { + // Last Page + $this->currentPage = null; + } else { + $this->currentPage = $this->formDefinition->getPageByIndex($currentPageIndex); + } + } + + /** + * @return void + */ + protected function initializeHoneypotFromRequest() + { + $renderingOptions = $this->formDefinition->getRenderingOptions(); + if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') { + return; + } + + FormArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']); + + if (!$this->isFirstRequest()) { + $elementsCount = count($this->lastDisplayedPage->getElements()); + if ($elementsCount === 0) { + return; + } + + $honeypotNameFromSession = $this->getHoneypotNameFromSession($this->lastDisplayedPage); + if ($honeypotNameFromSession) { + $honeypotElement = $this->lastDisplayedPage->createElement($honeypotNameFromSession, $renderingOptions['honeypot']['formElementToUse']); + $validator = $this->objectManager->get(EmptyValidator::class); + $honeypotElement->addValidator($validator); + } + } + } + + /** + * @return void + */ + protected function renderHoneypot() + { + $renderingOptions = $this->formDefinition->getRenderingOptions(); + if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') { + return; + } + + FormArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']); + + if (!$this->isAfterLastPage()) { + $elementsCount = count($this->currentPage->getElements()); + if ($elementsCount === 0) { + return; + } + + if (!$this->isFirstRequest()) { + $honeypotNameFromSession = $this->getHoneypotNameFromSession($this->lastDisplayedPage); + if ($honeypotNameFromSession) { + $honeypotElement = $this->formDefinition->getElementByIdentifier($honeypotNameFromSession); + if ($honeypotElement instanceof FormElementInterface) { + $this->lastDisplayedPage->removeElement($honeypotElement); + } + } + } + + $elementsCount = count($this->currentPage->getElements()); + $randomElementNumber = mt_rand(0, ($elementsCount - 1)); + $honeypotName = substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, mt_rand(5, 26)); + + $referenceElement = $this->currentPage->getElements()[$randomElementNumber]; + $honeypotElement = $this->currentPage->createElement($honeypotName, $renderingOptions['honeypot']['formElementToUse']); + $validator = $this->objectManager->get(EmptyValidator::class); + + $honeypotElement->addValidator($validator); + if (mt_rand(0, 1) === 1) { + $this->currentPage->moveElementAfter($honeypotElement, $referenceElement); + } else { + $this->currentPage->moveElementBefore($honeypotElement, $referenceElement); + } + $this->setHoneypotNameInSession($this->currentPage, $honeypotName); + } + } + + /** + * @param Page $page + * return null|string + */ + protected function getHoneypotNameFromSession(Page $page) + { + if ($this->getTypoScriptFrontendController()->loginUser) { + $honeypotNameFromSession = $this->getTypoScriptFrontendController()->fe_user->getKey( + 'user', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier() + ); + } else { + $honeypotNameFromSession = $this->getTypoScriptFrontendController()->fe_user->getKey( + 'ses', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier() + ); + } + return $honeypotNameFromSession; + } + + /** + * @param Page $page + * @param string $honeypotName + * @return void + */ + protected function setHoneypotNameInSession(Page $page, string $honeypotName) + { + if ($this->getTypoScriptFrontendController()->loginUser) { + $this->getTypoScriptFrontendController()->fe_user->setKey( + 'user', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier(), + $honeypotName + ); + } else { + $this->getTypoScriptFrontendController()->fe_user->setKey( + 'ses', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier(), + $honeypotName + ); + } + } + + /** + * Returns TRUE if the last page of the form has been submitted, otherwise FALSE + * + * @return bool + */ + protected function isAfterLastPage(): bool + { + return $this->currentPage === null; + } + + /** + * Returns TRUE if no previous page is stored in the FormState, otherwise FALSE + * + * @return bool + */ + protected function isFirstRequest(): bool + { + return $this->lastDisplayedPage === null; + } + + /** + * @return void + */ + protected function processSubmittedFormValues() + { + $result = $this->mapAndValidatePage($this->lastDisplayedPage); + if ($result->hasErrors() && !$this->userWentBackToPreviousStep()) { + $this->currentPage = $this->lastDisplayedPage; + $this->request->setOriginalRequestMappingResults($result); + } + } + + /** + * returns TRUE if the user went back to any previous step in the form. + * + * @return bool + */ + protected function userWentBackToPreviousStep(): bool + { + return !$this->isAfterLastPage() && !$this->isFirstRequest() && $this->currentPage->getIndex() < $this->lastDisplayedPage->getIndex(); + } + + /** + * @param Page $page + * @return Result + * @throws PropertyMappingException + */ + protected function mapAndValidatePage(Page $page): Result + { + $result = $this->objectManager->get(Result::class); + $requestArguments = $this->request->getArguments(); + + $propertyPathsForWhichPropertyMappingShouldHappen = []; + $registerPropertyPaths = function ($propertyPath) use (&$propertyPathsForWhichPropertyMappingShouldHappen) { + $propertyPathParts = explode('.', $propertyPath); + $accumulatedPropertyPathParts = []; + foreach ($propertyPathParts as $propertyPathPart) { + $accumulatedPropertyPathParts[] = $propertyPathPart; + $temporaryPropertyPath = implode('.', $accumulatedPropertyPathParts); + $propertyPathsForWhichPropertyMappingShouldHappen[$temporaryPropertyPath] = $temporaryPropertyPath; + } + }; + foreach ($page->getElementsRecursively() as $element) { + $value = ArrayUtility::getValueByPath($requestArguments, $element->getIdentifier()); + $element->onSubmit($this, $value, $requestArguments); + + $this->formState->setFormValue($element->getIdentifier(), $value); + $registerPropertyPaths($element->getIdentifier()); + } + + // The more parts the path has, the more early it is processed + usort($propertyPathsForWhichPropertyMappingShouldHappen, function ($a, $b) { + return substr_count($b, '.') - substr_count($a, '.'); + }); + + $processingRules = $this->formDefinition->getProcessingRules(); + + foreach ($propertyPathsForWhichPropertyMappingShouldHappen as $propertyPath) { + if (isset($processingRules[$propertyPath])) { + $processingRule = $processingRules[$propertyPath]; + $value = $this->formState->getFormValue($propertyPath); + try { + $value = $processingRule->process($value); + } catch (PropertyException $exception) { + throw new PropertyMappingException( + 'Failed to process FormValue at "' . $propertyPath . '" from "' . gettype($value) . '" to "' . $processingRule->getDataType() . '"', + 1480024933, + $exception + ); + } + $result->forProperty($propertyPath)->merge($processingRule->getProcessingMessages()); + $this->formState->setFormValue($propertyPath, $value); + } + } + + return $result; + } + + /** + * Override the current page taken from the request, rendering the page with index $pageIndex instead. + * + * This is typically not needed in production code, but it is very helpful when displaying + * some kind of "preview" of the form. + * + * @param int $pageIndex + * @return void + * @api + */ + public function overrideCurrentPage(int $pageIndex) + { + $this->currentPage = $this->formDefinition->getPageByIndex($pageIndex); + } + + /** + * Render this form. + * + * @return null|string rendered form + * @throws RenderingException + * @api + */ + public function render() + { + if ($this->isAfterLastPage()) { + $this->invokeFinishers(); + return $this->response->getContent(); + } + + $this->formState->setLastDisplayedPageIndex($this->currentPage->getIndex()); + + if ($this->formDefinition->getRendererClassName() === null) { + throw new RenderingException(sprintf('The form definition "%s" does not have a rendererClassName set.', $this->formDefinition->getIdentifier()), 1326095912); + } + $rendererClassName = $this->formDefinition->getRendererClassName(); + $renderer = $this->objectManager->get($rendererClassName); + if (!($renderer instanceof RendererInterface)) { + throw new RenderingException(sprintf('The renderer "%s" des not implement RendererInterface', $rendererClassName), 1326096024); + } + + $controllerContext = $this->getControllerContext(); + + $renderer->setControllerContext($controllerContext); + $renderer->setFormRuntime($this); + return $renderer->render($this); + } + + /** + * Executes all finishers of this form + * + * @return void + */ + protected function invokeFinishers() + { + $finisherContext = $this->objectManager->get(FinisherContext::class, + $this, + $this->getControllerContext() + ); + foreach ($this->formDefinition->getFinishers() as $finisher) { + $finisher->execute($finisherContext); + if ($finisherContext->isCancelled()) { + break; + } + } + } + + /** + * @return string The identifier of underlying form + * @api + */ + public function getIdentifier(): string + { + return $this->formDefinition->getIdentifier(); + } + + /** + * Get the request this object is bound to. + * + * This is mostly relevant inside Finishers, where you f.e. want to redirect + * the user to another page. + * + * @return Request the request this object is bound to + * @api + */ + public function getRequest(): Request + { + return $this->request; + } + + /** + * Get the response this object is bound to. + * + * This is mostly relevant inside Finishers, where you f.e. want to set response + * headers or output content. + * + * @return Response the response this object is bound to + * @api + */ + public function getResponse(): Response + { + return $this->response; + } + + /** + * Returns the currently selected page + * + * @return Page + * @api + */ + public function getCurrentPage(): Page + { + return $this->currentPage; + } + + /** + * Returns the previous page of the currently selected one or NULL if there is no previous page + * + * @return null|Page + * @api + */ + public function getPreviousPage() + { + $previousPageIndex = $this->currentPage->getIndex() - 1; + if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) { + return $this->formDefinition->getPageByIndex($previousPageIndex); + } + return null; + } + + /** + * Returns the next page of the currently selected one or NULL if there is no next page + * + * @return null|Page + * @api + */ + public function getNextPage() + { + $nextPageIndex = $this->currentPage->getIndex() + 1; + if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) { + return $this->formDefinition->getPageByIndex($nextPageIndex); + } + return null; + } + + /** + * @return ControllerContext + */ + protected function getControllerContext(): ControllerContext + { + $uriBuilder = $this->objectManager->get(UriBuilder::class); + $uriBuilder->setRequest($this->request); + $controllerContext = $this->objectManager->get(ControllerContext::class); + $controllerContext->setRequest($this->request); + $controllerContext->setResponse($this->response); + $controllerContext->setArguments($this->objectManager->get(Arguments::class, [])); + $controllerContext->setUriBuilder($uriBuilder); + return $controllerContext; + } + + /** + * Abstract "type" of this Renderable. Is used during the rendering process + * to determine the template file or the View PHP class being used to render + * the particular element. + * + * @return string + * @api + */ + public function getType(): string + { + return $this->formDefinition->getType(); + } + + /** + * @param string $identifier + * @return bool + * @internal + */ + public function offsetExists($identifier) + { + if ($this->getElementValue($identifier) !== null) { + return true; + } + + if (is_callable([$this, 'get' . ucfirst($identifier)])) { + return true; + } + if (is_callable([$this, 'has' . ucfirst($identifier)])) { + return true; + } + if (is_callable([$this, 'is' . ucfirst($identifier)])) { + return true; + } + if (property_exists($this, $identifier)) { + $propertyReflection = new PropertyReflection($this, $identifier); + return $propertyReflection->isPublic(); + } + + return false; + } + + /** + * @param string $identifier + * @return mixed + * @internal + */ + public function offsetGet($identifier) + { + if ($this->getElementValue($identifier) !== null) { + return $this->getElementValue($identifier); + } + $getterMethodName = 'get' . ucfirst($identifier); + if (is_callable([$this, $getterMethodName])) { + return $this->{$getterMethodName}(); + } + return null; + } + + /** + * @param string $identifier + * @param mixed $value + * @return void + * @internal + */ + public function offsetSet($identifier, $value) + { + $this->formState->setFormValue($identifier, $value); + } + + /** + * @param string $identifier + * @return void + * @internal + */ + public function offsetUnset($identifier) + { + $this->formState->setFormValue($identifier, null); + } + + /** + * Returns the value of the specified element + * + * @param string $identifier + * @return mixed + * @api + */ + public function getElementValue(string $identifier) + { + $formValue = $this->formState->getFormValue($identifier); + if ($formValue !== null) { + return $formValue; + } + return $this->formDefinition->getElementDefaultValueByIdentifier($identifier); + } + + /** + * @return array<Page> The Form's pages in the correct order + * @api + */ + public function getPages(): array + { + return $this->formDefinition->getPages(); + } + + /** + * @return FormState + * @internal + */ + public function getFormState(): FormState + { + return $this->formState; + } + + /** + * Get all rendering options + * + * @return array associative array of rendering options + * @api + */ + public function getRenderingOptions(): array + { + return $this->formDefinition->getRenderingOptions(); + } + + /** + * Get the renderer class name to be used to display this renderable; + * must implement RendererInterface + * + * @return string the renderer class name + * @api + */ + public function getRendererClassName(): string + { + return $this->formDefinition->getRendererClassName(); + } + + /** + * Get the label which shall be displayed next to the form element + * + * @return string + * @api + */ + public function getLabel(): string + { + return $this->formDefinition->getLabel(); + } + + /** + * Get the underlying form definition from the runtime + * + * @return FormDefinition + * @api + */ + public function getFormDefinition(): FormDefinition + { + return $this->formDefinition; + } + + /** + * This is a callback that is invoked by the Renderer before the corresponding element is rendered. + * Use this to access previously submitted values and/or modify the $formRuntime before an element + * is outputted to the browser. + * + * @param FormRuntime $formRuntime + * @return void + * @api + */ + public function beforeRendering(FormRuntime $formRuntime) + { + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController() + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/form/Classes/Domain/Runtime/FormState.php b/typo3/sysext/form/Classes/Domain/Runtime/FormState.php new file mode 100644 index 0000000000000000000000000000000000000000..ff6b43733fa00aebf01503983f9e3974951ac28b --- /dev/null +++ b/typo3/sysext/form/Classes/Domain/Runtime/FormState.php @@ -0,0 +1,100 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Domain\Runtime; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Utility\ArrayUtility; + +/** + * The current state of the form which is attached to the {@link FormRuntime} + * and saved in a session or the client. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +class FormState +{ + + /** + * Constant which means that we are currently not on any page; i.e. the form + * has never rendered before. + */ + const NOPAGE = -1; + + /** + * The last displayed page index + * + * @var int + */ + protected $lastDisplayedPageIndex = self::NOPAGE; + + /** + * @var array + */ + protected $formValues = []; + + /** + * @return bool FALSE if the form has never been submitted before, TRUE otherwise + */ + public function isFormSubmitted(): bool + { + return $this->lastDisplayedPageIndex !== self::NOPAGE; + } + + /** + * @return int + */ + public function getLastDisplayedPageIndex(): int + { + return $this->lastDisplayedPageIndex; + } + + /** + * @param int $lastDisplayedPageIndex + * @return void + */ + public function setLastDisplayedPageIndex(int $lastDisplayedPageIndex) + { + $this->lastDisplayedPageIndex = $lastDisplayedPageIndex; + } + + /** + * @return array + */ + public function getFormValues(): array + { + return $this->formValues; + } + + /** + * @param string $propertyPath + * @param mixed $value + * @return void + */ + public function setFormValue(string $propertyPath, $value) + { + $this->formValues = ArrayUtility::setValueByPath($this->formValues, $propertyPath, $value); + } + + /** + * @param string $propertyPath + * @return mixed + */ + public function getFormValue(string $propertyPath) + { + return ArrayUtility::getValueByPath($this->formValues, $propertyPath); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Validator/AbstractValidator.php b/typo3/sysext/form/Classes/Domain/Validator/AbstractValidator.php deleted file mode 100644 index adfb477a54ee3d676a1c6d9e76a9d99c976cfe1d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/AbstractValidator.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -use TYPO3\CMS\Form\Utility\FormUtility; - -abstract class AbstractValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate'; - - /** - * @var FormUtility - */ - protected $formUtility; - - /** - * @var mixed - */ - protected $rawArgument; - - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - ]; - - /** - * This validator always needs to be executed even if the given value is empty. - * See AbstractValidator::validate() - * - * @var bool - */ - protected $acceptsEmptyValues = false; - - /** - * @param mixed $rawArgument - */ - public function setRawArgument($rawArgument) - { - $this->rawArgument = $rawArgument; - } - - /** - * @param FormUtility $formUtility - */ - public function setFormUtility(FormUtility $formUtility) - { - $this->formUtility = $formUtility; - } - - /** - * Substitute makers in the message text - * In some cases this method will be override by rule class - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - return $message; - } - - /** - * Get the local language label(s) for the message - * In some cases this method will be override by rule class - * - * @param string $type The type - * @return string The local language message label - */ - public function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.' . $type; - $message = LocalizationUtility::translate($label, 'form'); - return $message; - } - - /** - * Set the message, like 'required' for the validation rule - * and substitutes markers for values, like %maximum - * - * - * @param mixed $message Message as string or TS - * @param NULL|string $type Name of the cObj - * @param string $messageType message or error - * @return string - */ - public function renderMessage($message = null, $type = null, $messageType = 'message') - { - $message = $this->formUtility->renderItem( - $message, - $type, - $this->getLocalLanguageLabel($messageType) - ); - return $this->substituteMarkers($message); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/AlphabeticValidator.php b/typo3/sysext/form/Classes/Domain/Validator/AlphabeticValidator.php deleted file mode 100644 index 57085725ec6db89c807a1eec683af85a85106a14..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/AlphabeticValidator.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class AlphabeticValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'allowWhiteSpace' => ['', 'Whitespaces are allowed', 'boolean', false], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_alphabetic'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ( - !isset($this->options['allowWhiteSpace']) - || $this->options['allowWhiteSpace'] === '' - || (int)$this->options['allowWhiteSpace'] === 0 - ) { - $this->options['allowWhiteSpace'] = false; - } else { - $this->options['allowWhiteSpace'] = true; - } - - $whiteSpace = $this->options['allowWhiteSpace'] ? '\\s' : ''; - $pattern = '/[^\pL' . $whiteSpace . ']/u'; - $compareValue = preg_replace($pattern, '', (string)$value); - - if ($compareValue !== $value) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442004245 - ); - } - } - - /** - * Get the local language label(s) for the message - * Overrides the abstract - * - * @param string $type The type - * @return string The local language message label - * @see \TYPO3\CMS\Form\Validation\AbstractValidator::_getLocalLanguageLabel() - */ - public function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.message'; - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label, 'form'); - if ($this->options['allowWhiteSpace']) { - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 2, 'form'); - } - $message = implode(', ', $messages); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/AlphanumericValidator.php b/typo3/sysext/form/Classes/Domain/Validator/AlphanumericValidator.php deleted file mode 100644 index 1bd18c8fc97ee0b0700afbbd92f445d3eeb64060..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/AlphanumericValidator.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class AlphanumericValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'allowWhiteSpace' => ['', 'Whitespaces are allowed', 'boolean', false], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_alphanumeric'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ( - !isset($this->options['allowWhiteSpace']) - || $this->options['allowWhiteSpace'] === '' - || (int)$this->options['allowWhiteSpace'] === 0 - ) { - $this->options['allowWhiteSpace'] = false; - } else { - $this->options['allowWhiteSpace'] = true; - } - - $whiteSpace = $this->options['allowWhiteSpace'] ? '\\s' : ''; - $pattern = '/[^\pL\d)' . $whiteSpace . ']/u'; - $compareValue = preg_replace($pattern, '', (string)$value); - - if ($compareValue !== $value) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442004457 - ); - } - } - - /** - * Get the local language label(s) for the message - * Overrides the abstract - * - * @param string $type The type - * @return string The local language message label - * @see \TYPO3\CMS\Form\Validation\AbstractValidator::_getLocalLanguageLabel() - */ - public function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.message'; - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label, 'form'); - if ($this->options['allowWhiteSpace']) { - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 2, 'form'); - } - $message = implode(', ', $messages); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/BetweenValidator.php b/typo3/sysext/form/Classes/Domain/Validator/BetweenValidator.php deleted file mode 100644 index b528845ebeb1085c951dd78e842a2a3bad359958..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/BetweenValidator.php +++ /dev/null @@ -1,109 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class BetweenValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'minimum' => ['', 'The minimum value', 'integer', true], - 'maximum' => ['', 'The maximum value', 'integer', true], - 'inclusive' => ['', 'Minimum and maximum value are inclusive in comparison', 'integer', false], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_between'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ( - !isset($this->options['inclusive']) - || $this->options['inclusive'] === '' - || (int)$this->options['inclusive'] === 0 - ) { - if ($value <= $this->options['minimum'] || $value >= $this->options['maximum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442003544 - ); - } - } else { - if ($value < $this->options['minimum'] || $value > $this->options['maximum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442003545 - ); - } - } - } - - /** - * Get the local language label(s) for the message - * Overrides the abstract - * - * @param string $type The type - * @return string The local language message label - * @see \TYPO3\CMS\Form\Validation\AbstractValidator::_getLocalLanguageLabel() - */ - public function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.' . $type; - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label, 'form'); - if ($this->inclusive) { - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 2, 'form'); - } - $message = implode(', ', $messages); - return $message; - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - return str_replace( - ['%minimum', '%maximum'], - [$this->options['minimum'], $this->options['maximum']], - $message - ); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/DateValidator.php b/typo3/sysext/form/Classes/Domain/Validator/DateValidator.php deleted file mode 100644 index fca3f0d7653965050be75fbcb13b1106c6cc38b1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/DateValidator.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class DateValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'format' => ['', 'The maximum value', 'string', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_date'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ( - $this->options['format'] === null - || $this->options['format'] === '' - ) { - $this->options['format'] = '%e-%m-%Y'; - } - - if (function_exists('strptime')) { - $parsedDate = strptime($value, $this->options['format']); - $parsedDateYear = $parsedDate['tm_year'] + 1900; - $parsedDateMonth = $parsedDate['tm_mon'] + 1; - $parsedDateDay = $parsedDate['tm_mday']; - if (!checkdate($parsedDateMonth, $parsedDateDay, $parsedDateYear)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442001386 - ); - return; - } - } else { - // %a => D : An abbreviated textual representation of the day (conversion works only for english) - // %A => l : A full textual representation of the day (conversion works only for english) - // %d => d : Day of the month, 2 digits with leading zeros - // %e => j : Day of the month, 2 digits without leading zeros - // %j => z : Day of the year, 3 digits with leading zeros - // %b => M : Abbreviated month name, based on the locale (conversion works only for english) - // %B => F : Full month name, based on the locale (conversion works only for english) - // %h => M : Abbreviated month name, based on the locale (an alias of %b) (conversion works only for english) - // %m => m : Two digit representation of the month - // %y => y : Two digit representation of the year - // %Y => Y : Four digit representation for the year - $dateTimeFormat = str_replace( - ['%a', '%A', '%d', '%e', '%j', '%b', '%B', '%h', '%m', '%y', '%Y'], - ['D', 'l', 'd', 'j', 'z', 'M', 'F', 'M', 'm', 'y', 'Y'], - $this->options['format'] - ); - $dateTimeObject = date_create_from_format($dateTimeFormat, $value); - if ($dateTimeObject === false) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442001386 - ); - return; - } - - if ($value !== $dateTimeObject->format($dateTimeFormat)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442001386 - ); - } - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $humanReadableDateFormat = $this->humanReadableDateFormat($this->options['format']); - $message = str_replace('%format', $humanReadableDateFormat, $message); - return $message; - } - - /** - * Converts strftime date format to human readable format - * according to local language. - * - * Example for default language: %e-%m-%Y becomes d-mm-yyyy - * - * @param string $format strftime format - * @return string Human readable format - */ - protected function humanReadableDateFormat($format) - { - $label = self::LOCALISATION_OBJECT_NAME . '.strftime.'; - $pairs = [ - '%A' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'A', 'form'), - '%a' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'a', 'form'), - '%d' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'd', 'form'), - '%e' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'e', 'form'), - '%B' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'B', 'form'), - '%b' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'b', 'form'), - '%m' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'm', 'form'), - '%Y' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'Y', 'form'), - '%y' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'y', 'form'), - '%H' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'H', 'form'), - '%I' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'I', 'form'), - '%M' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'M', 'form'), - '%S' => \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 'S', 'form') - ]; - $humanReadableFormat = str_replace(array_keys($pairs), array_values($pairs), $format); - return $humanReadableFormat; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/DigitValidator.php b/typo3/sysext/form/Classes/Domain/Validator/DigitValidator.php deleted file mode 100644 index 3654bcae4a10739419cd328ba5217b4d833dc694..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/DigitValidator.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class DigitValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_digit'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $compareValue = preg_replace('/[^0-9]/', '', (string)$value); - if ($compareValue !== $value) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442000838 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/EmailValidator.php b/typo3/sysext/form/Classes/Domain/Validator/EmailValidator.php deleted file mode 100644 index edb05fcb18182fc1b9563a4d6a337abc6e9f01a0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/EmailValidator.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -/** - * Class EmailValidator - */ -class EmailValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_email'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (empty($value) || !is_string($value)) { - return; - } - - if (!GeneralUtility::validEmail($value)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442000235 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/EqualsValidator.php b/typo3/sysext/form/Classes/Domain/Validator/EqualsValidator.php deleted file mode 100644 index 4f5ea32b9c8764dd934b295b1d39131f34787f6d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/EqualsValidator.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class EqualsValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'field' => ['', 'The field to be compared', 'string', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_equals'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $comparisonValue = $this->rawArgument[$this->options['field']]; - if ($value !== $comparisonValue) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442005826 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $message = str_replace('%field', $this->options['field'], $message); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/FileAllowedTypesValidator.php b/typo3/sysext/form/Classes/Domain/Validator/FileAllowedTypesValidator.php deleted file mode 100644 index b7b58f245f7d77007dcd205ee874f4ee494a5ffc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/FileAllowedTypesValidator.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -class FileAllowedTypesValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'types' => ['', 'The allowed file types', 'string', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_fileallowedtypes'; - - /** - * Check if the file mime type is allowed. - * - * The mime type is set in the propertymapper - * - * @see TYPO3\CMS\Form\Domain\Property\TypeConverter::convertFrom - * - * @param array $value - * @return void - */ - public function isValid($value) - { - $allowedTypes = strtolower($this->options['types']); - $allowedMimeTypes = GeneralUtility::trimExplode(',', $allowedTypes, true); - $fileMimeType = !empty($value['type']) ? strtolower($value['type']) : ''; - - if (!in_array($fileMimeType, $allowedMimeTypes, true)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442006702 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $allowedTypes = strtolower($this->options['types']); - $allowedMimeTypes = GeneralUtility::trimExplode(',', $allowedTypes); - $allowedTypesStringForDisplay = implode(', ', $allowedMimeTypes); - $message = str_replace('%allowedTypes', $allowedTypesStringForDisplay, $message); - - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/FileMaximumSizeValidator.php b/typo3/sysext/form/Classes/Domain/Validator/FileMaximumSizeValidator.php deleted file mode 100644 index 38d1ba9fb71bad962d1274d662ad4f08e1cc398f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/FileMaximumSizeValidator.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -class FileMaximumSizeValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'maximum' => ['', 'The maximum file size', 'integer', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_filemaximumsize'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $fileValue = $this->rawArgument[$this->options['element']]; - $value = $fileValue['size']; - if ($value > (int)$this->options['maximum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442006702 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $message = str_replace('%maximum', GeneralUtility::formatSize($this->options['maximum']), $message); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/FileMinimumSizeValidator.php b/typo3/sysext/form/Classes/Domain/Validator/FileMinimumSizeValidator.php deleted file mode 100644 index 5aac7591a05ed57551376f98f38bffc16ae25a73..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/FileMinimumSizeValidator.php +++ /dev/null @@ -1,72 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; - -class FileMinimumSizeValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'minimum' => ['', 'The minimum file size', 'integer', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_fileminimumsize'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $fileValue = $this->rawArgument[$this->options['element']]; - $value = $fileValue['size']; - if ($value < (int)$this->options['minimum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442006702 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $message = str_replace('%minimum', GeneralUtility::formatSize($this->options['minimum']), $message); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/FloatValidator.php b/typo3/sysext/form/Classes/Domain/Validator/FloatValidator.php deleted file mode 100644 index 4322d718c497a3da2a22bfbea2e3ee9126a0c90b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/FloatValidator.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class FloatValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_float'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $locale = localeconv(); - $valueFiltered = str_replace( - [ - $locale['thousands_sep'], - $locale['mon_thousands_sep'], - $locale['decimal_point'], - $locale['mon_decimal_point'] - ], - [ - '', - '', - '.', - '.' - ], - $value - ); - if ($value != strval((float)$valueFiltered)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442002070 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/GreaterThanValidator.php b/typo3/sysext/form/Classes/Domain/Validator/GreaterThanValidator.php deleted file mode 100644 index bd35699a9bd77505f498ad29b6d2e6a4d7cef361..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/GreaterThanValidator.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class GreaterThanValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'minimum' => ['', 'The minimum value', 'integer', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_greaterthan'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ((int)$value <= (int)$this->options['minimum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442002213 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $message = str_replace('%minimum', $this->options['minimum'], $message); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/InArrayValidator.php b/typo3/sysext/form/Classes/Domain/Validator/InArrayValidator.php deleted file mode 100644 index ef3c9d3cf90f71f2f443f08c33dcddfb3e6526f0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/InArrayValidator.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Charset\CharsetConverter; -use TYPO3\CMS\Core\Utility\GeneralUtility; - -class InArrayValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'array' => ['', 'The array values from the wizard configuration (array = test1,test2)', 'string', false], - 'array.' => ['', 'The array values from the documented configuration', 'array', false], - 'strict' => ['', 'Compare types', 'boolean', false], - 'ignorecase' => ['', 'Ignore cases', 'boolean', false] - ]; - - /** - * @var CharsetConverter - */ - protected $charsetConverter; - - /** - * Constructor - * - * Creates charsetConverter object if option ignorecase is set - * - * @param array $options - * @throws \TYPO3\CMS\Extbase\Validation\Exception\InvalidValidationOptionsException - */ - public function __construct(array $options) - { - parent::__construct($options); - if (!empty($this->options['ignorecase'])) { - $this->charsetConverter = GeneralUtility::makeInstance(CharsetConverter::class); - } - } - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_inarray'; - - /** - * Check if $value is valid. If it is not valid, add an error to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (empty($value)) { - return; - } - - /** - * A single select results in a string, - * a multiselect in an array. - * In both cases, the operations will be processed on an array. - */ - if (is_string($value)) { - $value = [$value]; - } - - /** - * The form wizard generates the following configuration: - * array = test1,test2 - * In this case the string has to be exploded. - * The following configuration was documented: - * array { - * 1 = TYPO3 4.5 LTS - * 2 = TYPO3 6.2 LTS - * 3 = TYPO3 7 LTS - * } - * In this case there is already an array but the "options" key differs. - */ - $allowedOptionsArray = []; - if (!empty($this->options['array']) && is_string($this->options['array'])) { - $allowedOptionsArray = GeneralUtility::trimExplode(',', $this->options['array'], true); - } elseif (!empty($this->options['array.']) && is_array($this->options['array.'])) { - $allowedOptionsArray = $this->options['array.']; - } - - if (!empty($this->options['ignorecase'])) { - foreach ($value as &$incomingArrayValue) { - $incomingArrayValue = $this->charsetConverter->conv_case('utf-8', $incomingArrayValue, 'toLower'); - } - foreach ($allowedOptionsArray as &$option) { - $option = $this->charsetConverter->conv_case('utf-8', $option, 'toLower'); - } - } - - foreach ($value as $incomingArrayValue) { - if (!in_array($incomingArrayValue, $allowedOptionsArray, !empty($this->options['strict']))) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442002594 - ); - } - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/IntegerValidator.php b/typo3/sysext/form/Classes/Domain/Validator/IntegerValidator.php deleted file mode 100644 index 87106fa9c146ef4a9554a0fc179fb4053b164611..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/IntegerValidator.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class IntegerValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_integer'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $locale = localeconv(); - $valueFiltered = str_replace( - [ - $locale['thousands_sep'], - $locale['mon_thousands_sep'], - $locale['decimal_point'], - $locale['mon_decimal_point'] - ], - [ - '', - '', - '.', - '.' - ], - $value - ); - if (strval((int)$valueFiltered) != $valueFiltered) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1442000119 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/IpValidator.php b/typo3/sysext/form/Classes/Domain/Validator/IpValidator.php deleted file mode 100644 index 9cdebec40b85d0b951f82b14caada45b5c839b53..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/IpValidator.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class IpValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_ip'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (!preg_match('/\\b(([01]?\\d?\\d|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d?\\d|2[0-4]\\d|25[0-5])\\b/', $value)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441999896 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/LengthValidator.php b/typo3/sysext/form/Classes/Domain/Validator/LengthValidator.php deleted file mode 100644 index 5639aa07d56c90e0a8479412b881a075f56cf74a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/LengthValidator.php +++ /dev/null @@ -1,128 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class LengthValidator extends AbstractValidator -{ - /** - * TYPO3 charset encoding object - * - * @var \TYPO3\CMS\Core\Charset\CharsetConverter - */ - protected $charsetConverter = null; - - /** - * @param \TYPO3\CMS\Core\Charset\CharsetConverter $charsetConverter - * @return void - */ - public function injectCharsetConverter(\TYPO3\CMS\Core\Charset\CharsetConverter $charsetConverter) - { - $this->charsetConverter = $charsetConverter; - } - - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'minimum' => ['', 'The minimum value', 'integer', true], - 'maximum' => ['', 'The maximum value', 'integer', false], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_length'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - $length = $this->charsetConverter->strlen('utf-8', $value); - if ($length < (int)$this->options['minimum']) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441999425 - ); - return; - } - if ( - !isset($this->options['maximum']) - || $this->options['maximum'] === '' - ) { - $this->options['maximum'] = null; - } - if ( - $this->options['maximum'] !== null - && $length > (int)$this->options['maximum'] - ) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441999425 - ); - } - } - - /** - * Get the local language label(s) for the message - * Overrides the abstract - * - * @param string $type The type - * @return string The local language message label - * @see \TYPO3\CMS\Form\Validation\AbstractValidator::_getLocalLanguageLabel() - */ - public function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.' . $type; - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label, 'form'); - if ($this->options['maximum'] !== null) { - $messages[] = \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($label . 2, 'form'); - } - $message = implode(', ', $messages); - return $message; - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - return str_replace( - ['%minimum', '%maximum'], - [$this->options['minimum'], $this->options['maximum']], - $message - ); - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/LessThanValidator.php b/typo3/sysext/form/Classes/Domain/Validator/LessThanValidator.php deleted file mode 100644 index 5c5466cabf3b2feeec2062d8cd86964c61175ad5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/LessThanValidator.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class LessThanValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'maximum' => ['', 'The maximum value', 'integer', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_lessthan'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if ($value >= $this->options['maximum'] || !is_numeric($value)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441997981 - ); - } - } - - /** - * Substitute makers in the message text - * Overrides the abstract - * - * @param string $message Message text with markers - * @return string Message text with substituted markers - */ - public function substituteMarkers($message) - { - $message = str_replace('%maximum', $this->options['maximum'], $message); - return $message; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/RegExpValidator.php b/typo3/sysext/form/Classes/Domain/Validator/RegExpValidator.php deleted file mode 100644 index 09857bd17ab5064db85bc8dc83a6e5fcd9e36d28..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/RegExpValidator.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class RegExpValidator extends AbstractValidator -{ - /** - * @var array - */ - protected $supportedOptions = [ - 'element' => ['', 'The name of the element', 'string', true], - 'errorMessage' => ['', 'The error message', 'array', true], - 'expression' => ['', 'The regular expression', 'string', true], - ]; - - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_regexp'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (!preg_match($this->options['expression'], $value)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441997233 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/RequiredValidator.php b/typo3/sysext/form/Classes/Domain/Validator/RequiredValidator.php deleted file mode 100644 index e1c80eface7971c25ccefd133db978d8453f4b2f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/RequiredValidator.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class RequiredValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_required'; - - /** - * @var bool - */ - protected $allFieldsAreEmpty = true; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (is_array($value)) { - array_walk_recursive($value, function ($value, $key, $validator) { - if (!empty($value) || $value === '0' || $value === 0) { - $validator->setAllFieldsAreEmpty(false); - } - }, - $this - ); - if ($this->getAllFieldsAreEmpty()) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441980673 - ); - } - } else { - if ( - empty($value) - && $value !== 0 - && $value !== '0' - ) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 144198067 - ); - } - } - } - - /** - * A helper method for the array_walk_recursive callback in the - * function isValid(). - * If the callback detect a empty value, the - * property allFieldsAreEmpty is set to TRUE. - * - * @param bool $allFieldsAreEmpty - * @return void - */ - protected function setAllFieldsAreEmpty($allFieldsAreEmpty = true) - { - $this->allFieldsAreEmpty = $allFieldsAreEmpty; - } - - /** - * A helper method for the array_walk_recursive callback in the - * function isValid(). - * If the callback detect a empty value, the - * property allFieldsAreEmpty is set to TRUE. - * - * @return bool - */ - protected function getAllFieldsAreEmpty() - { - return $this->allFieldsAreEmpty; - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/UriValidator.php b/typo3/sysext/form/Classes/Domain/Validator/UriValidator.php deleted file mode 100644 index 3d2505c0adcbd7746f5f1c4c357288e171983eda..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/UriValidator.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class UriValidator extends AbstractValidator -{ - /** - * Constant for localisation - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_uri'; - - /** - * Check if $value is valid. If it is not valid, needs to add an error - * to result. - * - * @param mixed $value - * @return void - */ - public function isValid($value) - { - if (!preg_match('/^(?#Protocol)(?:(?:ht|f)tp(?:s?)\\:\\/\\/|~\\/|\\/)?(?#Username:Password)(?:\\w+:\\w+@)?(?#Subdomains)(?:(?:[-\\w]+\\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\\d]{1,5})?(?#Directories)(?:(?:(?:\\/(?:[-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?(?#Query)(?:(?:\\?(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?(?:[-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)(?:&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?(?:[-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*(?#Anchor)(?:#(?:[-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?$/', $value)) { - $this->addError( - $this->renderMessage( - $this->options['errorMessage'][0], - $this->options['errorMessage'][1], - 'error' - ), - 1441997233 - ); - } - } -} diff --git a/typo3/sysext/form/Classes/Domain/Validator/ValidationElementValidator.php b/typo3/sysext/form/Classes/Domain/Validator/ValidationElementValidator.php deleted file mode 100644 index 81d1ca20b7b6a1b05bcea7cdd6025ebafa06ebbf..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Domain/Validator/ValidationElementValidator.php +++ /dev/null @@ -1,257 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Domain\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface; - -/** - * A generic object validator which allows for specifying property validators - */ -class ValidationElementValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator implements \TYPO3\CMS\Extbase\Validation\Validator\ObjectValidatorInterface -{ - /** - * @var \SplObjectStorage[] - */ - protected $propertyValidators = []; - - /** - * @var \TYPO3\CMS\Form\Utility\SessionUtility - */ - protected $sessionUtility; - - /** - * @param \TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility - */ - public function injectSessionUtility(\TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility) - { - $this->sessionUtility = $sessionUtility; - } - - /** - * Checks if the given value is valid according to the validator, and returns - * the Error Messages object which occurred. - * - * @param mixed $value The value that should be validated - * @return \TYPO3\CMS\Extbase\Error\Result - * @api - */ - public function validate($value) - { - $this->result = new \TYPO3\CMS\Extbase\Error\Result(); - if ($this->acceptsEmptyValues === false || $this->isEmpty($value) === false) { - if (!is_object($value)) { - $this->addError('Object expected, %1$s given.', 1241099149, [gettype($value)]); - } elseif ($this->isValidatedAlready($value) === false) { - $this->isValid($value); - } - } - - return $this->result; - } - - /** - * Load the property value to be used for validation. - * - * In case the object is a doctrine proxy, we need to load the real instance first. - * - * @param \TYPO3\CMS\Form\Domain\Model\ValidationElement $validationElement - * @param string $propertyName - * @return mixed - */ - protected function getPropertyValue(\TYPO3\CMS\Form\Domain\Model\ValidationElement $validationElement, $propertyName) - { - /** - * If a confirmation page is set and a fileupload was done before - * there is no incoming data if the process action is called. - * The data is only in the session at this time. - * This results in a negative validation (if a validation is set). - * Therefore, look first in the session. - */ - if ($this->sessionUtility->getSessionData($propertyName)) { - $propertyValue = $this->sessionUtility->getSessionData($propertyName); - } else { - $propertyValue = $validationElement->getIncomingField($propertyName); - } - return $propertyValue; - } - - /** - * Checks if the specified property of the given object is valid, and adds - * found errors to the $messages object. - * - * @param mixed $value The value to be validated - * @param \Traversable $validators The validators to be called on the value - * @param string $propertyName Name of ther property to check - * @return void - */ - protected function checkProperty($value, $validators, $propertyName) - { - /** @var \TYPO3\CMS\Extbase\Error\Result $result */ - $result = null; - foreach ($validators as $validator) { - if ($validator instanceof ObjectValidatorInterface) { - $validator->setValidatedInstancesContainer($this->validatedInstancesContainer); - } - - /** - * File upload validation. - * - * If a $_FILES array is found in the request data, - * iterate over all requested files and validate each - * single file. - */ - if ( - isset($value[0]['name']) - && isset($value[0]['type']) - && isset($value[0]['tmp_name']) - && isset($value[0]['size']) - ) { - foreach ($value as $file) { - $currentResult = $validator->validate($file); - if ($currentResult->hasMessages()) { - if ($result == null) { - $result = $currentResult; - } else { - $result->merge($currentResult); - } - } - } - } else { - $currentResult = $validator->validate($value); - if ($currentResult->hasMessages()) { - if ($result == null) { - $result = $currentResult; - } else { - $result->merge($currentResult); - } - } - } - } - if ($result != null) { - $this->result->forProperty($propertyName)->merge($result); - } - } - - /** - * Checks if the given value is valid according to the property validators. - * - * @param mixed $object The value that should be validated - * @return void - * @api - */ - protected function isValid($object) - { - foreach ($this->propertyValidators as $propertyName => $validators) { - $propertyValue = $this->getPropertyValue($object, $propertyName); - $this->checkProperty($propertyValue, $validators, $propertyName); - } - } - - /** - * Checks the given object can be validated by the validator implementation - * - * @param mixed $object The object to be checked - * @return bool TRUE if the given value can be validated - * @api - */ - public function canValidate($object) - { - if ( - is_object($object) - && $object instanceof \TYPO3\CMS\Form\Domain\Model\ValidationElement - ) { - return true; - } - return false; - } - - /** - * Adds the given validator for validation of the specified property. - * - * @param string $propertyName Name of the property to validate - * @param ValidatorInterface $validator The property validator - * @return void - * @api - */ - public function addPropertyValidator($propertyName, ValidatorInterface $validator) - { - if (!isset($this->propertyValidators[$propertyName])) { - $this->propertyValidators[$propertyName] = new \SplObjectStorage(); - } - $this->propertyValidators[$propertyName]->attach($validator); - } - - /** - * @param object $object - * @return bool - */ - protected function isValidatedAlready($object) - { - if ($this->validatedInstancesContainer === null) { - $this->validatedInstancesContainer = new \SplObjectStorage(); - } - if ($this->validatedInstancesContainer->contains($object)) { - return true; - } else { - $this->validatedInstancesContainer->attach($object); - - return false; - } - } - - /** - * Returns all property validators - or only validators of the specified property - * - * @param string $propertyName Name of the property to return validators for - * @return array An array of validators - */ - public function getPropertyValidators($propertyName = null) - { - if ($propertyName !== null) { - return (isset($this->propertyValidators[$propertyName])) ? $this->propertyValidators[$propertyName] : []; - } else { - return $this->propertyValidators; - } - } - - /** - * @return int - */ - public function countPropertyValidators() - { - $count = 0; - foreach ($this->propertyValidators as $propertyValidators) { - $count += $propertyValidators->count(); - } - return $count; - } - - /** - * @var \SplObjectStorage - */ - protected $validatedInstancesContainer; - - /** - * Allows to set a container to keep track of validated instances. - * - * @param \SplObjectStorage $validatedInstancesContainer A container to keep track of validated instances - * @return void - * @api - */ - public function setValidatedInstancesContainer(\SplObjectStorage $validatedInstancesContainer) - { - $this->validatedInstancesContainer = $validatedInstancesContainer; - } -} diff --git a/typo3/sysext/form/Classes/Exception.php b/typo3/sysext/form/Classes/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..bd686473e717dcbc9888617b8930164313300304 --- /dev/null +++ b/typo3/sysext/form/Classes/Exception.php @@ -0,0 +1,25 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * A generic Form Exception + * + * @api + */ +class Exception extends \Exception +{ +} diff --git a/typo3/sysext/form/Classes/Hooks/DataStructureIdentifierHook.php b/typo3/sysext/form/Classes/Hooks/DataStructureIdentifierHook.php new file mode 100644 index 0000000000000000000000000000000000000000..eefae9dbf731afbfa3626e07d61798e0d4798580 --- /dev/null +++ b/typo3/sysext/form/Classes/Hooks/DataStructureIdentifierHook.php @@ -0,0 +1,249 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Hooks; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility as CoreArrayUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Utility\ArrayUtility as ExtbaseArrayUtility; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface; +use TYPO3\CMS\Form\Service\TranslationService; + +/** + * Hooks into flex form handling of backend for tt_content form elements: + * + * * Adds existing forms to flex form drop down list + * * Adds finisher settings if "override finishers" is active + * + * Scope: backend + * @internal + */ +class DataStructureIdentifierHook +{ + + /** + * The data structure depends on a current form selection (persistenceIdentifier) + * and if the field "overrideFinishers" is active. Add both to the identifier to + * hand these information over to parseDataStructureByIdentifierPostProcess() hook. + * + * @param array $fieldTca Incoming field TCA + * @param string $tableName Handled table + * @param string $fieldName Handled field + * @param array $row Current data row + * @param array $identifier Already calculated identifier + * @return array Modified identifier + */ + public function getDataStructureIdentifierPostProcess( + array $fieldTca, + string $tableName, + string $fieldName, + array $row, + array $identifier + ): array { + if ($tableName === 'tt_content' && $fieldName === 'pi_flexform' && $row['CType'] === 'form_formframework') { + $currentFlexData = []; + if (!is_array($row['pi_flexform']) && !empty($row['pi_flexform'])) { + $currentFlexData = GeneralUtility::xml2array($row['pi_flexform']); + } + + // Add selected form value + $identifier['ext-form-persistenceIdentifier'] = ''; + if (!empty($currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'])) { + $identifier['ext-form-persistenceIdentifier'] = $currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF']; + } + + // Add bool - finisher override active or not + $identifier['ext-form-overrideFinishers'] = false; + if ( + isset($currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF']) + && (int)$currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF'] === 1 + ) { + $identifier['ext-form-overrideFinishers'] = true; + } + } + return $identifier; + } + + /** + * Returns a modified flexform data array. + * + * This adds the list of existing form definitions to the form selection drop down + * and adds sheets to override finisher settings if requested. + * + * @param array $dataStructure + * @param array $identifier + * @return array + */ + public function parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier): array + { + if (isset($identifier['ext-form-persistenceIdentifier'])) { + // Add list of existing forms to drop down if we find our key in the identifier + $formPersistenceManager = GeneralUtility::makeInstance(ObjectManager::class)->get(FormPersistenceManagerInterface::class); + foreach ($formPersistenceManager->listForms() as $form) { + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['TCEforms']['config']['items'][] = [ + $form['name'] . ' (' . $form['persistenceIdentifier'] . ')', + $form['persistenceIdentifier'], + ]; + } + + // If a specific form is selected and if finisher override is active, add finisher sheets + if (!empty($identifier['ext-form-persistenceIdentifier']) + && isset($identifier['ext-form-overrideFinishers']) + && $identifier['ext-form-overrideFinishers'] === true + ) { + $persistenceIdentifier = $identifier['ext-form-persistenceIdentifier']; + $formDefinition = $formPersistenceManager->load($persistenceIdentifier); + $newSheets = $this->getAdditionalFinisherSheets($persistenceIdentifier, $formDefinition); + CoreArrayUtility::mergeRecursiveWithOverrule( + $dataStructure, + $newSheets + ); + } + } + return $dataStructure; + } + + /** + * Returns additional flexform sheets with finisher fields + * + * @param string $persistenceIdentifier Current persistence identifier + * @param array $formDefinition The form definition + * @return array + */ + protected function getAdditionalFinisherSheets(string $persistenceIdentifier, array $formDefinition): array + { + if (!isset($formDefinition['finishers']) || empty($formDefinition['finishers'])) { + return []; + } + + $prototypeName = isset($formDefinition['prototypeName']) ? $formDefinition['prototypeName'] : 'standard'; + $prototypeConfiguration = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ConfigurationService::class) + ->getPrototypeConfiguration($prototypeName); + + if (!isset($prototypeConfiguration['finishersDefinition']) || empty($prototypeConfiguration['finishersDefinition'])) { + return []; + } + + $formIdentifier = $formDefinition['identifier']; + $finishersDefinition = $prototypeConfiguration['finishersDefinition']; + + $sheets = ['sheets' => []]; + foreach ($formDefinition['finishers'] as $finisherValue) { + $finisherIdentifier = $finisherValue['identifier']; + if (!isset($finishersDefinition[$finisherIdentifier]['FormEngine']['elements'])) { + continue; + } + $sheetIdentifier = md5( + implode('', [ + $persistenceIdentifier, + $prototypeName, + $formIdentifier, + $finisherIdentifier + ]) + ); + + $translationFile = $finishersDefinition[$finisherIdentifier]['FormEngine']['translationFile']; + $finishersDefinition[$finisherIdentifier]['FormEngine'] = TranslationService::getInstance()->translateValuesRecursive( + $finishersDefinition[$finisherIdentifier]['FormEngine'], + $translationFile + ); + $finisherLabel = $finishersDefinition[$finisherIdentifier]['FormEngine']['label']; + $sheet = $this->initializeNewSheetArray($sheetIdentifier, $finisherLabel); + + $sheetElements = []; + foreach ($finisherValue['options'] as $optionKey => $optionValue) { + if (is_array($optionValue)) { + $optionKey = $optionKey . '.' . $this->extractDottedPathToLastElement($finisherValue['options'][$optionKey]); + $elementConfiguration = ExtbaseArrayUtility::getValueByPath($finishersDefinition[$finisherIdentifier]['FormEngine']['elements'], $optionKey); + $optionValue = ExtbaseArrayUtility::getValueByPath($finisherValue['options'], $optionKey); + } else { + $elementConfiguration = $finishersDefinition[$finisherIdentifier]['FormEngine']['elements'][$optionKey]; + } + + if (empty($elementConfiguration)) { + continue; + } + + if (empty($optionValue)) { + $elementConfiguration['label'] .= ' (default: "[Empty]")'; + } else { + $elementConfiguration['label'] .= ' (default: "' . $optionValue . '")'; + } + $elementConfiguration['config']['default'] = $optionValue; + $sheetElements['settings.finishers.' . $finisherIdentifier . '.' . $optionKey] = $elementConfiguration; + } + + ksort($sheetElements); + + $sheet[$sheetIdentifier]['ROOT']['el'] = $sheetElements; + CoreArrayUtility::mergeRecursiveWithOverrule($sheets['sheets'], $sheet); + } + if (empty($sheets['sheets'])) { + return []; + } + + return $sheets; + } + + /** + * Boilerplate XML array of a new sheet + * + * @param string $sheetIdentifier + * @param string $finisherName + * @throws \InvalidArgumentException + * @return array + */ + protected function initializeNewSheetArray(string $sheetIdentifier, string $finisherName): array + { + if (empty($sheetIdentifier)) { + throw new \InvalidArgumentException('$sheetIdentifier must not be empty.', 1472060918); + } + if (empty($finisherName)) { + throw new \InvalidArgumentException('$finisherName must not be empty.', 1472060919); + } + + return [ + $sheetIdentifier => [ + 'ROOT' => [ + 'TCEforms' => [ + 'sheetTitle' => $finisherName, + ], + 'type' => 'array', + 'el' => [], + ], + ], + ]; + } + + /** + * Recursive helper to implode a nested array to a dotted path notation + * + * @param array $array + * @return string + */ + protected function extractDottedPathToLastElement(array $array): string + { + $dottedPath = key($array); + foreach ($array as $key => $value) { + if (is_array($value)) { + $dottedPath = $dottedPath . '.' . $this->extractDottedPathToLastElement($value); + } + } + return $dottedPath; + } +} diff --git a/typo3/sysext/form/Classes/Hooks/HandleIncomingFormValues.php b/typo3/sysext/form/Classes/Hooks/HandleIncomingFormValues.php deleted file mode 100644 index aeeeec1477a9c504eeb1852f16877efa42d8cf0a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Hooks/HandleIncomingFormValues.php +++ /dev/null @@ -1,205 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Hooks; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\SingletonInterface; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Builder\FormBuilder; -use TYPO3\CMS\Form\Domain\Model\Element; -use TYPO3\CMS\Form\Domain\Model\ValidationElement; - -/** - * Handle the incoming form data - */ -class HandleIncomingFormValues implements SingletonInterface -{ - /** - * @var \TYPO3\CMS\Form\Utility\SessionUtility - */ - protected $sessionUtility; - - /** - * @param \TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility - * @return void - */ - public function injectSessionUtility(\TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility) - { - $this->sessionUtility = $sessionUtility; - } - - /** - * Handle the incoming form data - * - * @param Element $element The element - * @param ValidationElement $validationElement - * @param mixed $modelValue - * @param FormBuilder $formBuilder - * @return void - */ - public function handleIncomingFormValues(Element $element, ValidationElement $validationElement, $modelValue, FormBuilder $formBuilder) - { - $elementName = $element->getName(); - - if ($element->getElementType() === 'CHECKBOX') { - $groupedElement = false; - if ($element->getParentElement()->getElementType() === 'CHECKBOXGROUP') { - $incomingName = $element->getParentElement()->getName(); - $groupedElement = true; - } else { - $incomingName = $elementName; - } - $incomingData = $formBuilder->getIncomingData()->getIncomingField($incomingName); - $checked = false; - if (is_array($incomingData)) { - if ( - isset($incomingData[$elementName]) - && $incomingData[$elementName] !== '' - ) { - $this->setAttribute($element, 'checked', 'checked'); - $checked = true; - } else { - $this->setAttribute($element, 'checked', null); - } - } else { - if ( - (!empty($modelValue) && $incomingData === $modelValue) - || $incomingData === $incomingName . '-' . $element->getElementCounter() - ) { - $this->setAttribute($element, 'checked', 'checked'); - $checked = true; - } else { - $this->setAttribute($element, 'checked', null); - } - } - if ( - $groupedElement - && $checked - ) { - $element->getParentElement()->setAdditionalArgument('atLeastOneCheckedChildElement', true); - } - } elseif ($element->getElementType() === 'RADIO') { - $groupedElement = false; - if ($element->getParentElement()->getElementType() === 'RADIOGROUP') { - $incomingName = $element->getParentElement()->getName(); - $groupedElement = true; - } else { - $incomingName = $elementName; - } - $checked = false; - $incomingData = $formBuilder->getIncomingData()->getIncomingField($incomingName); - if ( - (!empty($modelValue) && $incomingData === $modelValue) - || $incomingData === $incomingName . '-' . $element->getElementCounter() - ) { - $this->setAttribute($element, 'checked', 'checked'); - $checked = true; - } else { - $this->setAttribute($element, 'checked', null); - } - if ( - $groupedElement - && $checked - ) { - $element->getParentElement()->setAdditionalArgument('atLeastOneCheckedChildElement', true); - } - } elseif ($element->getElementType() === 'OPTION') { - $modelValue = (string)($element->getAdditionalArgument('value') ?: $element->getElementCounter()); - if ($element->getParentElement()->getElementType() === 'OPTGROUP') { - $parentName = $element->getParentElement()->getParentElement()->getName(); - } else { - $parentName = $element->getParentElement()->getName(); - } - $incomingData = $formBuilder->getIncomingData()->getIncomingField($parentName); - - /* Multiselect */ - if (is_array($incomingData)) { - if (in_array($modelValue, $incomingData, true)) { - $element->setAdditionalArgument('selected', 'selected'); - } else { - $element->setAdditionalArgument('selected', null); - } - } else { - if ($modelValue === $incomingData) { - $element->setAdditionalArgument('selected', 'selected'); - } else { - $element->setAdditionalArgument('selected', null); - } - } - } elseif ($element->getElementType() === 'TEXTAREA') { - $incomingData = $formBuilder->getIncomingData()->getIncomingField($elementName); - $element->setAdditionalArgument('text', $incomingData); - } elseif ($element->getElementType() === 'FILEUPLOAD') { - if ( - $formBuilder->getValidationErrors() == null - || ( - $formBuilder->getValidationErrors() - && $formBuilder->getValidationErrors()->forProperty($elementName)->hasErrors() !== true - ) - ) { - $uploadedFiles = $formBuilder->getIncomingData()->getIncomingField($elementName); - if (is_array($uploadedFiles)) { - foreach ($uploadedFiles as $key => &$file) { - $tempFilename = $this->saveUploadedFile($file['tmp_name']); - if (!$tempFilename) { - unset($uploadedFiles[$key]); - continue; - } - $file['tempFilename'] = $tempFilename; - } - $element->setAdditionalArgument('uploadedFiles', $uploadedFiles); - $this->setAttribute($element, 'value', ''); - $this->sessionUtility->setSessionData($elementName, $uploadedFiles); - } - } - } - } - - /** - * Save a uploaded file - * - * @param string $uploadedFile - * @return NULL|string - */ - public function saveUploadedFile($uploadedFile) - { - if (is_uploaded_file($uploadedFile)) { - $tempFilename = GeneralUtility::upload_to_tempfile($uploadedFile); - if (TYPO3_OS === 'WIN') { - $tempFilename = GeneralUtility::fixWindowsFilePath($tempFilename); - } - if ($tempFilename !== '') { - return $tempFilename; - } - } - return null; - } - - /** - * Set the value Attribute to the right place - * - * @param Element $element The element - * @param string $key - * @param string $value - * @return void - */ - public function setAttribute(Element $element, $key, $value = '') - { - if ($element->getHtmlAttribute($key) !== null) { - $element->setHtmlAttribute($key, $value); - } else { - $element->setAdditionalArgument($key, $value); - } - } -} diff --git a/typo3/sysext/form/Classes/Hooks/PageLayoutView/MailformPreviewRenderer.php b/typo3/sysext/form/Classes/Hooks/PageLayoutView/MailformPreviewRenderer.php deleted file mode 100644 index 5a5b3f8818fd70d99337114eceaff4f42cf542b8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Hooks/PageLayoutView/MailformPreviewRenderer.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Hooks\PageLayoutView; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Contains a preview rendering for the page module of - * CType="mailform" - */ -class MailformPreviewRenderer implements \TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface -{ - /** - * Preprocesses the preview rendering of a content element of type "mailform" - * - * @param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object - * @param bool $drawItem Whether to draw the item using the default functionality - * @param string $headerContent Header content - * @param string $itemContent Item content - * @param array $row Record row of tt_content - * - * @return void - */ - public function preProcess(\TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row) - { - if ($row['CType'] === 'mailform') { - $contentType = $parentObject->CType_labels[$row['CType']]; - $itemContent = $parentObject->linkEditContent('<strong>' . htmlspecialchars($contentType) . '</strong>', $row) . '<br />'; - $drawItem = false; - } - } -} diff --git a/typo3/sysext/form/Classes/Hooks/SoftReferenceParserHook.php b/typo3/sysext/form/Classes/Hooks/SoftReferenceParserHook.php new file mode 100644 index 0000000000000000000000000000000000000000..17d22b1c89dd42d62b90440737900020e3721a16 --- /dev/null +++ b/typo3/sysext/form/Classes/Hooks/SoftReferenceParserHook.php @@ -0,0 +1,60 @@ +<?php +namespace TYPO3\CMS\Form\Hooks; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Database\SoftReferenceIndex; + +/** + * Register new referenced formDefinitions within a plugin as a soft reference. + * + * This is used in BE to track how often a specific form is used in a content + * element. The number is shown in the form module "Manage forms". + * + * Scope: backend + * @internal + */ +class SoftReferenceParserHook extends SoftReferenceIndex +{ + /** + * Main function through which all processing happens + * + * @param string $table Database table name + * @param string $field Field name for which processing occurs + * @param int $uid UID of the record + * @param string $content The content/value of the field + * @param string $spKey The softlink parser key. This is only interesting if more than one parser is grouped in the same class. That is the case with this parser. + * @param array $spParams Parameters of the softlink parser. Basically this is the content inside optional []-brackets after the softref keys. Parameters are exploded by "; + * @param string $structurePath If running from inside a FlexForm structure, this is the path of the tag. + * @return array Result array on positive matches, see description above. Otherwise FALSE + */ + public function findRef($table, $field, $uid, $content, $spKey, $spParams, $structurePath = '') + { + $this->tokenID_basePrefix = $table . ':' . $uid . ':' . $field . ':' . $structurePath . ':' . $spKey; + $tokenId = $this->makeTokenID($content); + return [ + 'content' => '{softref:' . $tokenId . '}', + 'elements' => [ + $tokenId => [ + 'matchString' => $content, + 'subst' => [ + 'type' => 'string', + 'tokenID' => $tokenId, + 'tokenValue' => $content + ], + ] + ] + ]; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManager.php b/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManager.php new file mode 100644 index 0000000000000000000000000000000000000000..3bb82c2b40ebb9b24f2aac3f2e62a1982d4b02b5 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManager.php @@ -0,0 +1,146 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility as CoreArrayUtility; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManager as ExtbaseConfigurationManager; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\ExtensionNameRequiredException; +use TYPO3\CMS\Form\Utility\ArrayUtility; + +/** + * Extend the ExtbaseConfigurationManager to read YAML configurations. + * + * Scope: frontend / backend + * @internal + */ +class ConfigurationManager extends ExtbaseConfigurationManager implements ConfigurationManagerInterface +{ + /** + * @var \TYPO3\CMS\Form\Mvc\Configuration\YamlSource + */ + protected $yamlSource; + + /** + * 1st level configuration cache + * + * @var array + */ + protected $configurationCache = []; + + /** + * @param \TYPO3\CMS\Form\Mvc\Configuration\YamlSource $yamlSource + * @internal + */ + public function injectYamlSource(\TYPO3\CMS\Form\Mvc\Configuration\YamlSource $yamlSource) + { + $this->yamlSource = $yamlSource; + } + + /** + * @param string $configurationType The kind of configuration to fetch - must be one of the CONFIGURATION_TYPE_* constants + * @param string $extensionName if specified, the configuration for the given extension will be returned. + * @param string $pluginName if specified, the configuration for the given plugin will be returned. + * @return array The configuration + * @internal + */ + public function getConfiguration($configurationType, $extensionName = null, $pluginName = null) + { + switch ($configurationType) { + case self::CONFIGURATION_TYPE_YAML_SETTINGS: + return $this->getConfigurationFromYamlFile($extensionName); + default: + return parent::getConfiguration($configurationType, $extensionName, $pluginName); + } + } + + /** + * Load and parse yaml files which are configured within the TypoScript + * path plugin.tx_extensionkey.settings.yamlConfigurations + * + * The following steps will be done: + * + * * Convert each singe yaml file into an array + * * merge this arrays together + * * resolve all declared inheritances + * * remove all keys if their values are NULL + * * return all configuration paths within TYPO3.CMS + * * sort by array keys, if all keys within the current nesting level are numerical keys + * * resolve possible TypoScript settings in FE mode + * + * @param string $extensionName + * @return array + * @throws ExtensionNameRequiredException + */ + protected function getConfigurationFromYamlFile(string $extensionName): array + { + if (empty($extensionName)) { + throw new ExtensionNameRequiredException( + 'Please specify an extension key to load a YAML configuration', + 1471473377 + ); + } + $ucFirstExtensioName = ucfirst($extensionName); + + // 1st level cache + $configurationCacheKey = strtolower(self::CONFIGURATION_TYPE_YAML_SETTINGS . '|' . $extensionName); + if (isset($this->configurationCache[$configurationCacheKey])) { + return $this->configurationCache[$configurationCacheKey]; + } + + $typoscriptSettings = parent::getConfiguration( + ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, + $extensionName + ); + $yamlSettingsFilePaths = isset($typoscriptSettings['yamlConfigurations']) + ? $typoscriptSettings['yamlConfigurations'] + : []; + $yamlSettings = InheritancesResolverService::create($this->yamlSource->load($yamlSettingsFilePaths)) + ->getResolvedConfiguration(); + + $yamlSettings = ArrayUtility::removeNullValuesRecursive($yamlSettings); + $yamlSettings = is_array($yamlSettings['TYPO3']['CMS'][$ucFirstExtensioName]) + ? $yamlSettings['TYPO3']['CMS'][$ucFirstExtensioName] + : []; + $yamlSettings = ArrayUtility::sortNumericArrayKeysRecursive($yamlSettings); + $yamlSettings = $this->overrideConfigurationByTypoScript($yamlSettings, $extensionName); + + // 1st level cache + $this->configurationCache[$configurationCacheKey] = $yamlSettings; + return $yamlSettings; + } + + /** + * @param array $yamlSettings + * @param string $extensionName + * @return array + */ + protected function overrideConfigurationByTypoScript(array $yamlSettings, string $extensionName): array + { + $typoScript = parent::getConfiguration(self::CONFIGURATION_TYPE_SETTINGS, $extensionName); + if (is_array($typoScript['yamlSettingsOverrides']) && !empty($typoScript['yamlSettingsOverrides'])) { + CoreArrayUtility::mergeRecursiveWithOverrule( + $yamlSettings, + $typoScript['yamlSettingsOverrides'] + ); + + if ($this->environmentService->isEnvironmentInFrontendMode()) { + $yamlSettings = $this->objectManager->get(TypoScriptService::class) + ->resolvePossibleTypoScriptConfiguration($yamlSettings); + } + } + return $yamlSettings; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManagerInterface.php b/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..0fd7c3b71278babeae48f906b05979cb42a2beae --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/ConfigurationManagerInterface.php @@ -0,0 +1,29 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface as ExtbaseConfigurationManagerInterface; + +/** + * Class ConfigurationManagerInterface + * + * Scope: frontend / backend + * @internal + */ +interface ConfigurationManagerInterface extends ExtbaseConfigurationManagerInterface +{ + const CONFIGURATION_TYPE_YAML_SETTINGS = 'YamlSettings'; +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..5aa153b8a1389afe7a41ca8e4be872d040186616 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Exception as FormException; + +/** + * A generic Form configuration Exception + * + * @internal + */ +class Exception extends FormException +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception/CycleInheritancesException.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/CycleInheritancesException.php new file mode 100644 index 0000000000000000000000000000000000000000..d2d832aaf9535670d0232eda91ee1b5f440a7c18 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/CycleInheritancesException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/** + * This exception is thrown if the InheritancesResolverService wants to + * solve declared inheritances which point cyclically to themselves. + * + * @internal + */ +class CycleInheritancesException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ExtensionNameRequiredException.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ExtensionNameRequiredException.php new file mode 100644 index 0000000000000000000000000000000000000000..e125e67209481d4b2b4fad9b69162bbd2ca63148 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ExtensionNameRequiredException.php @@ -0,0 +1,28 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/** + * This exception is thrown if the configuration manager wants to load + * a YAML file from an empty extension key + * + * @internal + */ +class ExtensionNameRequiredException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception/NoSuchFileException.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/NoSuchFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..c616ce3354c5d58e76fbb50f2b97271c3c149af9 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/NoSuchFileException.php @@ -0,0 +1,24 @@ +<?php +namespace TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/** + * A No Such File exception + */ +class NoSuchFileException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ParseErrorException.php b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ParseErrorException.php new file mode 100644 index 0000000000000000000000000000000000000000..47682656c1186325ba2f7356bd1359cf488e32a3 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/Exception/ParseErrorException.php @@ -0,0 +1,24 @@ +<?php +namespace TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Configuration\Exception; + +/** + * A Parse Error exception + */ +class ParseErrorException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/InheritancesResolverService.php b/typo3/sysext/form/Classes/Mvc/Configuration/InheritancesResolverService.php new file mode 100644 index 0000000000000000000000000000000000000000..26f13ec540f389bc70317cc8c21e31410ba04193 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/InheritancesResolverService.php @@ -0,0 +1,375 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Utility\ArrayUtility; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\CycleInheritancesException; + +/** + * Resolve declared inheritances within an configuration array + * + * Scope: frontend / backend + * @internal + */ +class InheritancesResolverService +{ + + /** + * The operator which is used to declare inheritances + */ + const INHERITANCE_OPERATOR = '__inheritances'; + + /** + * The reference configuration is used to get untouched values which + * can be merged into the touched configuration. + * + * @var array + */ + protected $referenceConfiguration = []; + + /** + * This stack is needed to find cyclically inheritances which are on + * the same nesting level but which do not follow each other directly. + * + * @var array + */ + protected $inheritanceStack = []; + + /** + * Needed to park a configuration path for cyclically inheritances + * detection while inheritances for this path is ongoing. + * + * @var string + */ + protected $inheritancePathToCkeck = ''; + + /** + * Returns an instance of this service. Additionally the configuration + * which should be resolved can be passed. + * + * @param array $configuration + * @return InheritancesResolverService + * @internal + */ + public static function create(array $configuration = []): InheritancesResolverService + { + /** @var InheritancesResolverService $inheritancesResolverService */ + $inheritancesResolverService = GeneralUtility::makeInstance(ObjectManager::class) + ->get(self::class); + $inheritancesResolverService->setReferenceConfiguration($configuration); + return $inheritancesResolverService; + } + + /** + * Reset the state of this service. + * Mainly introduced for unit tests. + * + * @return InheritancesResolverService + * @internal + */ + public function reset() + { + $this->referenceConfiguration = []; + $this->inheritanceStack = []; + $this->inheritancePathToCkeck = ''; + return $this; + } + + /** + * Set the reference configuration which is used to get untouched + * values which can be merged into the touched configuration. + * + * @param array + * @return InheritancesResolverService + */ + public function setReferenceConfiguration(array $referenceConfiguration) + { + $this->referenceConfiguration = $referenceConfiguration; + return $this; + } + + /** + * Resolve all inheritances within a configuration. + * After that the configuration array is cleaned from the + * inheritance operator. + * + * @return array + * @internal + */ + public function getResolvedConfiguration(): array + { + $configuration = $this->resolve($this->referenceConfiguration); + $configuration = $this->removeInheritanceOperatorRecursive($configuration); + return $configuration; + } + + /** + * Resolve all inheritances within a configuration. + * + * @toDo: More description + * @param array $configuration + * @param array $pathStack + * @param bool $setInheritancePathToCkeck + * @return array + */ + protected function resolve( + array $configuration, + array $pathStack = [], + bool $setInheritancePathToCkeck = true + ): array { + foreach ($configuration as $key => $values) { + $pathStack[] = $key; + $path = implode('.', $pathStack); + + $this->throwExceptionIfCycleInheritances($path, $path); + if ($setInheritancePathToCkeck) { + $this->inheritancePathToCkeck = $path; + } + + if (is_array($configuration[$key])) { + if (isset($configuration[$key][self::INHERITANCE_OPERATOR])) { + $inheritances = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $path . '.' . self::INHERITANCE_OPERATOR + ); + + if (is_array($inheritances)) { + $inheritedConfigurations = $this->resolveInheritancesRecursive($inheritances); + + $configuration[$key] = $this->mergeRecursiveWithOverrule( + $inheritedConfigurations, + $configuration[$key] + ); + } + + unset($configuration[$key][self::INHERITANCE_OPERATOR]); + } + + if (!empty($configuration[$key])) { + $configuration[$key] = $this->resolve( + $configuration[$key], + $pathStack + ); + } + } + array_pop($pathStack); + } + + return $configuration; + } + + /** + * Additional helper for the resolve method. + * + * @toDo: More description + * @param array $inheritances + * @return array + * @throws CycleInheritancesException + */ + protected function resolveInheritancesRecursive(array $inheritances): array + { + ksort($inheritances); + $inheritedConfigurations = []; + foreach ($inheritances as $inheritancePath) { + $this->throwExceptionIfCycleInheritances($inheritancePath, $inheritancePath); + $inheritedConfiguration = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $inheritancePath + ); + + if ( + isset($inheritedConfiguration[self::INHERITANCE_OPERATOR]) + && count($inheritedConfiguration) === 1 + ) { + if ($this->inheritancePathToCkeck === $inheritancePath) { + throw new CycleInheritancesException( + $this->inheritancePathToCkeck . ' has cycle inheritances', + 1474900796 + ); + } + + $inheritedConfiguration = $this->resolveInheritancesRecursive( + $inheritedConfiguration[self::INHERITANCE_OPERATOR] + ); + } else { + $pathStack = explode('.', $inheritancePath); + $key = array_pop($pathStack); + $newConfiguration = [ + $key => $inheritedConfiguration + ]; + $inheritedConfiguration = $this->resolve( + $newConfiguration, + $pathStack, + false + ); + $inheritedConfiguration = $inheritedConfiguration[$key]; + } + + $inheritedConfigurations = $this->mergeRecursiveWithOverrule( + $inheritedConfigurations, + $inheritedConfiguration + ); + } + + return $inheritedConfigurations; + } + + /** + * Throw an exception if a cycle is detected. + * + * @toDo: More description + * @param string $path + * @param string $pathToCheck + * @return void + * @throws CycleInheritancesException + */ + protected function throwExceptionIfCycleInheritances(string $path, string $pathToCheck) + { + $configuration = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $path + ); + + if (isset($configuration[self::INHERITANCE_OPERATOR])) { + $inheritances = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $path . '.' . self::INHERITANCE_OPERATOR + ); + if (is_array($inheritances)) { + foreach ($inheritances as $inheritancePath) { + $configuration = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $inheritancePath + ); + if (isset($configuration[self::INHERITANCE_OPERATOR])) { + $_inheritances = ArrayUtility::getValueByPath( + $this->referenceConfiguration, + $inheritancePath . '.' . self::INHERITANCE_OPERATOR + ); + foreach ($_inheritances as $_inheritancePath) { + if (strpos($pathToCheck, $_inheritancePath) === 0) { + throw new CycleInheritancesException( + $pathToCheck . ' has cycle inheritances', + 1474900797 + ); + } + } + } + + if ( + is_array($this->inheritanceStack[$pathToCheck]) + && in_array($inheritancePath, $this->inheritanceStack[$pathToCheck]) + ) { + $this->inheritanceStack[$pathToCheck][] = $inheritancePath; + throw new CycleInheritancesException( + $pathToCheck . ' has cycle inheritances', + 1474900799 + ); + } + $this->inheritanceStack[$pathToCheck][] = $inheritancePath; + $this->throwExceptionIfCycleInheritances($inheritancePath, $pathToCheck); + } + $this->inheritanceStack[$pathToCheck] = null; + } + } + } + + /** + * Recursively remove self::INHERITANCE_OPERATOR keys + * + * @param array $array + * @return array the modified array + */ + protected function removeInheritanceOperatorRecursive(array $array): array + { + $result = $array; + foreach ($result as $key => $value) { + if ($key === self::INHERITANCE_OPERATOR) { + unset($result[$key]); + continue; + } + + if (is_array($value)) { + $result[$key] = $this->removeInheritanceOperatorRecursive($value); + } + } + return $result; + } + + /** + * Merges two arrays recursively and "binary safe" (integer keys are overridden as well), + * overruling similar values in the first array ($firstArray) with the + * values of the second array ($secondArray) + * In case of identical keys, ie. keeping the values of the second. + * This is basicly the Extbase arrayMergeRecursiveOverrule method. + * This method act different to the core mergeRecursiveWithOverrule method. + * This method has the possibility to overrule a array value within the + * $firstArray with a string value within the $secondArray. + * The core method does not support such a overrule. + * The reason for this code duplication is that the extbase method will be + * deprecated in the future. + * + * @param array $firstArray First array + * @param array $secondArray Second array, overruling the first array + * @param bool $dontAddNewKeys If set, keys that are NOT found in $firstArray (first array) + * will not be set. Thus only existing value can/will be + * overruled from second array. + * @param bool $emptyValuesOverride If set (which is the default), values from $secondArray + * will overrule if they are empty (according to PHP's empty() function) + * @return array Resulting array where $secondArray values has overruled $firstArray values + * @internal + */ + protected function mergeRecursiveWithOverrule( + array $firstArray, + array $secondArray, + bool $dontAddNewKeys = false, + bool $emptyValuesOverride = true + ): array { + foreach ($secondArray as $key => $value) { + if ( + array_key_exists($key, $firstArray) + && is_array($firstArray[$key]) + ) { + if (is_array($secondArray[$key])) { + $firstArray[$key] = $this->mergeRecursiveWithOverrule( + $firstArray[$key], + $secondArray[$key], + $dontAddNewKeys, + $emptyValuesOverride + ); + } else { + $firstArray[$key] = $secondArray[$key]; + } + } else { + if ($dontAddNewKeys) { + if (array_key_exists($key, $firstArray)) { + if ($emptyValuesOverride || !empty($value)) { + $firstArray[$key] = $value; + } + } + } else { + if ($emptyValuesOverride || !empty($value)) { + $firstArray[$key] = $value; + } + } + } + } + reset($firstArray); + return $firstArray; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/TypoScriptService.php b/typo3/sysext/form/Classes/Mvc/Configuration/TypoScriptService.php new file mode 100644 index 0000000000000000000000000000000000000000..2f48eb5ffd987f81fbb1855700bc97d8405ee187 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/TypoScriptService.php @@ -0,0 +1,99 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * Utilities to manage and convert TypoScript + * + * Scope: frontend + */ +class TypoScriptService +{ + + /** + * @var \TYPO3\CMS\Extbase\Service\TypoScriptService + */ + protected $extbaseTypoScriptService; + + /** + * @param \TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService + * @internal + */ + public function injectTypoScriptService(\TYPO3\CMS\Extbase\Service\TypoScriptService $typoScriptService) + { + $this->extbaseTypoScriptService = $typoScriptService; + } + + /** + * Parse an configuration with ContentObjectRenderer::cObjGetSingle() + * and return the result. + * + * @param array $configuration + * @return array + * @internal + */ + public function resolvePossibleTypoScriptConfiguration(array $configuration = []): array + { + $configuration = $this->extbaseTypoScriptService->convertPlainArrayToTypoScriptArray($configuration); + $configuration = $this->resolveTypoScriptConfiguration($configuration); + $configuration = $this->extbaseTypoScriptService->convertTypoScriptArrayToPlainArray($configuration); + return $configuration; + } + + /** + * Parse an configuration with ContentObjectRenderer::cObjGetSingle() + * if there is an array key without and with a dot at the end. + * This sample would be identified as a TypoScript parsable configuration + * part: + * + * [ + * 'example' => 'TEXT' + * 'example.' => [ + * 'value' => 'some value' + * ] + * ] + * + * @param array $configuration + * @return array + */ + protected function resolveTypoScriptConfiguration(array $configuration = []): array + { + foreach ($configuration as $key => $value) { + $keyWithoutDot = rtrim((string)$key, '.'); + if (isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) { + $value = $this->getTypoScriptFrontendController()->cObj->cObjGetSingle( + $configuration[$keyWithoutDot], + $configuration[$keyWithoutDot . '.'] + ); + $configuration[$keyWithoutDot] = $value; + } elseif (!isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) { + $configuration[$keyWithoutDot] = $this->resolveTypoScriptConfiguration($value); + } + unset($configuration[$keyWithoutDot . '.']); + } + return $configuration; + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController() + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php b/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php new file mode 100644 index 0000000000000000000000000000000000000000..d628a18bd9ab53c748617b455fb14d5904f96815 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Configuration/YamlSource.php @@ -0,0 +1,156 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\NoSuchFileException; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\ParseErrorException; +use TYPO3\CMS\Form\Utility\ArrayUtility as FormArrayUtility; + +/** + * Configuration source based on YAML files + * + * Scope: frontend / backend + * @internal + */ +class YamlSource +{ + /** + * Will be set if the PHP YAML Extension is installed. + * Having this installed massively improves YAML parsing performance. + * + * @var bool + * @see http://pecl.php.net/package/yaml + */ + protected $usePhpYamlExtension = false; + + /** + * Use PHP YAML Extension if installed. + * @internal + */ + public function __construct() + { + if (extension_loaded('yaml')) { + $this->usePhpYamlExtension = true; + } + } + + /** + * Loads the specified configuration files and returns its merged content + * as an array. + * + * @param array $filesToLoad + * @return array + * @throws ParseErrorException + * @throws NoSuchFileException + * @internal + */ + public function load(array $filesToLoad): array + { + $configuration = []; + foreach ($filesToLoad as $fileToLoad) { + if ($fileToLoad instanceof File) { + $fileIdentifier = $fileToLoad->getIdentifier(); + $rawYamlContent = $fileToLoad->getContents(); + } else { + $fileIdentifier = $fileToLoad; + $fileToLoad = GeneralUtility::getFileAbsFileName($fileToLoad); + if (is_file($fileToLoad)) { + $rawYamlContent = file_get_contents($fileToLoad); + } else { + throw new NoSuchFileException( + 'The file "' . $fileToLoad . '" does not exist.', + 1471473378 + ); + } + } + + try { + if ($this->usePhpYamlExtension) { + $loadedConfiguration = @yaml_parse($rawYamlContent); + if ($loadedConfiguration === false) { + throw new ParseErrorException( + 'A parse error occurred while parsing file "' . $fileIdentifier . '".', + 1391894094 + ); + } + } else { + $loadedConfiguration = Yaml::parse($rawYamlContent); + } + + if (is_array($loadedConfiguration)) { + ArrayUtility::mergeRecursiveWithOverrule($configuration, $loadedConfiguration); + } + } catch (ParseException $exception) { + throw new ParseErrorException( + 'A parse error occurred while parsing file "' . $fileIdentifier . '". Error message: ' . $exception->getMessage(), + 1480195405 + ); + } + } + + $configuration = FormArrayUtility::convertBooleanStringsToBooleanRecursive($configuration); + return $configuration; + } + + /** + * Save the specified configuration array to the given file in YAML format. + * + * @param File|string $fileToSave The file to write to. + * @param array $configuration The configuration to save + * @return void + * @internal + */ + public function save($fileToSave, array $configuration) + { + $header = $this->getHeaderFromFile($fileToSave); + $yaml = Yaml::dump($configuration, 99, 2); + if ($fileToSave instanceof File) { + $fileToSave->setContents($header . LF . $yaml); + } else { + @file_put_contents($fileToSave, $header . LF . $yaml); + } + } + + /** + * Read the header part from the given file. That means, every line + * until the first non comment line is found. + * + * @param File|string $file + * @return string The header of the given YAML file + */ + protected function getHeaderFromFile($file): string + { + $header = ''; + if ($file instanceof File) { + $fileLines = explode(LF, $file->getContents()); + } else { + $fileLines = file($file); + } + foreach ($fileLines as $line) { + if (preg_match('/^#/', $line)) { + $header .= $line; + } else { + break; + } + } + return $header; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Controller/ControllerContext.php b/typo3/sysext/form/Classes/Mvc/Controller/ControllerContext.php deleted file mode 100644 index bd002485e9df70fb046ac347e651a0a96b8230f3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Mvc/Controller/ControllerContext.php +++ /dev/null @@ -1,85 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Mvc\Controller; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Extbase\Reflection\ObjectAccess; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Form\Domain\Model\ValidationElement; - -/** - * Extension to the default Extbase Controller Context. - */ -class ControllerContext extends \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext -{ - /** - * Extends a given default ControllerContext. - * - * @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext - * @return ControllerContext - */ - public static function extend(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $source) - { - $controllerContext = \TYPO3\CMS\Form\Utility\FormUtility::getObjectManager()->get(self::class); - $propertyNames = ObjectAccess::getGettableProperties($source); - foreach ($propertyNames as $propertyName => $propertyValue) { - ObjectAccess::setProperty($controllerContext, $propertyName, $propertyValue); - } - return $controllerContext; - } - - /** - * @var Configuration - */ - protected $configuration; - - /** - * @var ValidationElement - */ - protected $validationElement; - - /** - * @return Configuration - */ - public function getConfiguration() - { - return $this->configuration; - } - - /** - * @param Configuration $configuration - * @return ControllerContext - */ - public function setConfiguration(Configuration $configuration) - { - $this->configuration = $configuration; - return $this; - } - - /** - * @return ValidationElement - */ - public function getValidationElement() - { - return $this->validationElement; - } - - /** - * @param ValidationElement $validationElement - */ - public function setValidationElement(ValidationElement $validationElement) - { - $this->validationElement = $validationElement; - } -} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/Exception.php b/typo3/sysext/form/Classes/Mvc/Persistence/Exception.php new file mode 100644 index 0000000000000000000000000000000000000000..2efc4a6d8c75f3c140d86ec0d128b4060d05132e --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/Exception.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Exception as FormException; + +/** + * A generic Form persistence Exception + * + * @internal + */ +class Exception extends FormException +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniqueIdentifierException.php b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniqueIdentifierException.php new file mode 100644 index 0000000000000000000000000000000000000000..fb267c3a0fef81607a170d1d3922d1b592efd9b8 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniqueIdentifierException.php @@ -0,0 +1,25 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/** + * @internal + */ +class NoUniqueIdentifierException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniquePersistenceIdentifierException.php b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniquePersistenceIdentifierException.php new file mode 100644 index 0000000000000000000000000000000000000000..de1f7cd00beaf32eae6078c336f9b966a2ea6c17 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/NoUniquePersistenceIdentifierException.php @@ -0,0 +1,25 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/** + * @internal + */ +class NoUniquePersistenceIdentifierException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/Exception/PersistenceManagerException.php b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/PersistenceManagerException.php new file mode 100644 index 0000000000000000000000000000000000000000..f8cf7baeae047a8d03a80bd01633264a710cf81b --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/Exception/PersistenceManagerException.php @@ -0,0 +1,27 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Mvc\Persistence\Exception; + +/** + * Generic Persistence Manager Exception, to be thrown f.e. if a given form is not loadable + * + * @internal + */ +class PersistenceManagerException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php new file mode 100644 index 0000000000000000000000000000000000000000..fd19c9d33d84e6a51ce04a5a92a50be66a31f9fe --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManager.php @@ -0,0 +1,493 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException; +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter; +use TYPO3\CMS\Core\Resource\Folder; +use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\PathUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface; +use TYPO3\CMS\Form\Mvc\Configuration\YamlSource; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniqueIdentifierException; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniquePersistenceIdentifierException; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException; + +/** + * Concrete implementation of the FormPersistenceManagerInterface + * + * Scope: frontend / backend + */ +class FormPersistenceManager implements FormPersistenceManagerInterface +{ + + /** + * @var \TYPO3\CMS\Form\Mvc\Configuration\YamlSource + */ + protected $yamlSource; + + /** + * @var \TYPO3\CMS\Core\Resource\StorageRepository + */ + protected $storageRepository; + + /** + * @var array + */ + protected $formSettings; + + /** + * @param \TYPO3\CMS\Form\Mvc\Configuration\YamlSource $yamlSource + * @internal + */ + public function injectYamlSource(\TYPO3\CMS\Form\Mvc\Configuration\YamlSource $yamlSource) + { + $this->yamlSource = $yamlSource; + } + + /** + * @param \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository + * @internal + */ + public function injectStorageRepository(\TYPO3\CMS\Core\Resource\StorageRepository $storageRepository) + { + $this->storageRepository = $storageRepository; + } + + /** + * @internal + */ + public function initializeObject() + { + $this->formSettings = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ConfigurationManagerInterface::class) + ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_YAML_SETTINGS, 'form'); + } + + /** + * Load the array formDefinition identified by $persistenceIdentifier, and return it. + * Only files with the extension .yaml are loaded. + * At this place there is no check if the file location is allowed. + * + * @param string $persistenceIdentifier + * @return array + * @throws PersistenceManagerException + * @internal + */ + public function load(string $persistenceIdentifier): array + { + if (pathinfo($persistenceIdentifier, PATHINFO_EXTENSION) !== 'yaml') { + throw new PersistenceManagerException(sprintf('The file "%s" could not be loaded.', $persistenceIdentifier), 1477679819); + } + + if (strpos($persistenceIdentifier, 'EXT:') === 0) { + $file = $persistenceIdentifier; + } else { + $file = $this->getFileByIdentifier($persistenceIdentifier); + } + return $this->yamlSource->load([$file]); + } + + /** + * Save the array form representation identified by $persistenceIdentifier. + * Only files with the extension .yaml are saved. + * If the formDefinition is located within a EXT: resource, save is only + * allowed if the configuration path + * TYPO3.CMS.Form.persistenceManager.allowSaveToExtensionPaths + * is set to true. + * + * @param string $persistenceIdentifier + * @param array $formDefinition + * @return void + * @throws PersistenceManagerException + * @internal + */ + public function save(string $persistenceIdentifier, array $formDefinition) + { + if (pathinfo($persistenceIdentifier, PATHINFO_EXTENSION) !== 'yaml') { + throw new PersistenceManagerException(sprintf('The file "%s" could not be saved.', $persistenceIdentifier), 1477679820); + } + + if (strpos($persistenceIdentifier, 'EXT:') === 0) { + if (!$this->formSettings['persistenceManager']['allowSaveToExtensionPaths']) { + throw new PersistenceManagerException('Save to extension paths is not allowed.', 1477680881); + } + $fileToSave = GeneralUtility::getFileAbsFileName($persistenceIdentifier); + } else { + $fileToSave = $this->getOrCreateFile($persistenceIdentifier); + } + + $this->yamlSource->save($fileToSave, $formDefinition); + } + + /** + * Delete the form representation identified by $persistenceIdentifier. + * Only files with the extension .yaml are removed. + * formDefinitions within an EXT: resource are not removable. + * + * @param string $persistenceIdentifier + * @return void + * @throws PersistenceManagerException + * @internal + */ + public function delete(string $persistenceIdentifier) + { + if (pathinfo($persistenceIdentifier, PATHINFO_EXTENSION) !== 'yaml') { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239534); + } + if (!$this->exists($persistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239535); + } + if (strpos($persistenceIdentifier, 'EXT:') === 0) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239536); + } + + list($storageUid, $fileIdentifier) = explode(':', $persistenceIdentifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $file = $storage->getFile($fileIdentifier); + if (!$storage->checkFileActionPermission('delete', $file)) { + throw new PersistenceManagerException(sprintf('No delete access to file "%s".', $persistenceIdentifier), 1472239516); + } + $storage->deleteFile($file); + } + + /** + * Check whether a form with the specified $persistenceIdentifier exists + * + * @param string $persistenceIdentifier + * @return bool TRUE if a form with the given $persistenceIdentifier can be loaded, otherwise FALSE + * @internal + */ + public function exists(string $persistenceIdentifier): bool + { + $exists = false; + if (pathinfo($persistenceIdentifier, PATHINFO_EXTENSION) === 'yaml') { + if (strpos($persistenceIdentifier, 'EXT:') === 0) { + $exists = file_exists(GeneralUtility::getFileAbsFileName($persistenceIdentifier)); + } else { + list($storageUid, $fileIdentifier) = explode(':', $persistenceIdentifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $exists = $storage->hasFile($fileIdentifier); + } + } + return $exists; + } + + /** + * List all form definitions which can be loaded through this form persistence + * manager. + * + * Returns an associative array with each item containing the keys 'name' (the human-readable name of the form) + * and 'persistenceIdentifier' (the unique identifier for the Form Persistence Manager e.g. the path to the saved form definition). + * + * @return array in the format [['name' => 'Form 01', 'persistenceIdentifier' => 'path1'], [ .... ]] + * @internal + */ + public function listForms(): array + { + $fileExtensionFilter = GeneralUtility::makeInstance(FileExtensionFilter::class); + $fileExtensionFilter->setAllowedFileExtensions(['yaml']); + + $identifiers = []; + $forms = []; + /** @var \TYPO3\CMS\Core\Resource\Folder $folder */ + foreach ($this->getAccessibleFormStorageFolders() as $folder) { + $storage = $folder->getStorage(); + $storage->addFileAndFolderNameFilter([$fileExtensionFilter, 'filterFileList']); + + $files = $folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, true); + foreach ($files as $file) { + $persistenceIdentifier = $storage->getUid() . ':' . $file->getIdentifier(); + + $form = $this->load($persistenceIdentifier); + $forms[] = [ + 'identifier' => $form['identifier'], + 'name' => isset($form['label']) ? $form['label'] : $form['identifier'], + 'persistenceIdentifier' => $persistenceIdentifier, + 'readOnly' => false, + 'location' => 'storage', + 'duplicateIdentifier' => false, + ]; + $identifiers[$form['identifier']]++; + } + $storage->resetFileAndFolderNameFiltersToDefault(); + } + + foreach ($this->getAccessibleExtensionFolders() as $relativePath => $fullPath) { + $relativePath = rtrim($relativePath, '/') . '/'; + foreach (new \DirectoryIterator($fullPath) as $fileInfo) { + if ($fileInfo->getExtension() !== 'yaml') { + continue; + } + $form = $this->load($relativePath . $fileInfo->getFilename()); + $forms[] = [ + 'identifier' => $form['identifier'], + 'name' => isset($form['label']) ? $form['label'] : $form['identifier'], + 'persistenceIdentifier' => $relativePath . $fileInfo->getFilename(), + 'readOnly' => $this->formSettings['persistenceManager']['allowSaveToExtensionPaths'] ? false: true, + 'location' => 'extension', + 'duplicateIdentifier' => false, + ]; + $identifiers[$form['identifier']]++; + } + } + + foreach ($identifiers as $identifier => $count) { + if ($count > 1) { + foreach ($forms as &$formDefinition) { + if ($formDefinition['identifier'] === $identifier) { + $formDefinition['duplicateIdentifier'] = true; + } + } + } + } + + return $forms; + } + + /** + * Return a list of all accessible file mountpoints for the + * current backend user. + * + * Only registered mountpoints from + * TYPO3.CMS.Form.persistenceManager.allowedFileMounts + * are listet. + * + * @return Folder[] + * @internal + */ + public function getAccessibleFormStorageFolders(): array + { + $storageFolders = []; + if ( + !isset($this->formSettings['persistenceManager']['allowedFileMounts']) + || !is_array($this->formSettings['persistenceManager']['allowedFileMounts']) + || empty($this->formSettings['persistenceManager']['allowedFileMounts']) + ) { + return $storageFolders; + } + + foreach ($this->formSettings['persistenceManager']['allowedFileMounts'] as $allowedFileMount) { + list($storageUid, $fileMountIdentifier) = explode(':', $allowedFileMount, 2); + $fileMountIdentifier = rtrim($fileMountIdentifier, '/') . '/'; + + try { + $storage = $this->getStorageByUid((int)$storageUid); + } catch (PersistenceManagerException $e) { + continue; + } + + try { + $folder = $storage->getFolder($fileMountIdentifier); + } catch (InsufficientFolderAccessPermissionsException $e) { + continue; + } + $storageFolders[$allowedFileMount] = $folder; + } + return $storageFolders; + } + + /** + * Return a list of all accessible extension folders + * + * Only registered mountpoints from + * TYPO3.CMS.Form.persistenceManager.allowedExtensionPaths + * are listet. + * + * @return array + * @internal + */ + public function getAccessibleExtensionFolders(): array + { + $extensionFolders = []; + if ( + !isset($this->formSettings['persistenceManager']['allowedExtensionPaths']) + || !is_array($this->formSettings['persistenceManager']['allowedExtensionPaths']) + || empty($this->formSettings['persistenceManager']['allowedExtensionPaths']) + ) { + return $extensionFolders; + } + + foreach ($this->formSettings['persistenceManager']['allowedExtensionPaths'] as $allowedExtensionPath) { + if (strpos($allowedExtensionPath, 'EXT:') !== 0) { + continue; + } + + $allowedExtensionFullPath = GeneralUtility::getFileAbsFileName($allowedExtensionPath); + if (!file_exists($allowedExtensionFullPath)) { + continue; + } + $extensionFolders[$allowedExtensionPath] = $allowedExtensionFullPath; + } + return $extensionFolders; + } + + /** + * This takes a form identifier and returns a unique persistence identifier for it. + * By default this is just similar to the identifier. But if a form with the same persistence identifier already + * exists a suffix is appended until the persistence identifier is unique. + * + * @param string $formIdentifier lowerCamelCased form identifier + * @param string $savePath + * @return string unique form persistence identifier + * @throws NoUniquePersistenceIdentifierException + * @internal + */ + public function getUniquePersistenceIdentifier(string $formIdentifier, string $savePath): string + { + $savePath = rtrim($savePath, '/') . '/'; + $formPersistenceIdentifier = $savePath . $formIdentifier . '.yaml'; + if (!$this->exists($formPersistenceIdentifier)) { + return $formPersistenceIdentifier; + } + for ($attempts = 1; $attempts < 100; $attempts++) { + $formPersistenceIdentifier = $savePath . sprintf('%s_%d', $formIdentifier, $attempts) . '.yaml'; + if (!$this->exists($formPersistenceIdentifier)) { + return $formPersistenceIdentifier; + } + } + $formPersistenceIdentifier = $savePath . sprintf('%s_%d', $formIdentifier, time()) . '.yaml'; + if (!$this->exists($formPersistenceIdentifier)) { + return $formPersistenceIdentifier; + } + + throw new NoUniquePersistenceIdentifierException( + sprintf('Could not find a unique persistence identifier for form identifier "%s" after %d attempts', $formIdentifier, $attempts), + 1476010403 + ); + } + + /** + * This takes a form identifier and returns a unique identifier for it. + * If a formDefinition with the same identifier already exists a suffix is + * appended until the identifier is unique. + * + * @param string $identifier + * @return string unique form identifier + * @throws NoUniqueIdentifierException + * @internal + */ + public function getUniqueIdentifier(string $identifier): string + { + $originalIdentifier = $identifier; + if ($this->checkForDuplicateIdentifier($identifier)) { + for ($attempts = 1; $attempts < 100; $attempts++) { + $identifier = sprintf('%s_%d', $originalIdentifier, $attempts); + if (!$this->checkForDuplicateIdentifier($identifier)) { + return $identifier; + } + } + $identifier = $originalIdentifier . '_' . time(); + if ($this->checkForDuplicateIdentifier($identifier)) { + throw new NoUniqueIdentifierException( + sprintf('Could not find a unique identifier for form identifier "%s" after %d attempts', $identifier, $attempts), + 1477688567 + ); + } + } + return $identifier; + } + + /** + * Check if a identifier is already used by a formDefintion. + * + * @param string $identifier + * @return bool + * @internal + */ + public function checkForDuplicateIdentifier(string $identifier): bool + { + $identifierUsed = false; + foreach ($this->listForms() as $formDefinition) { + if ($formDefinition['identifier'] === $identifier) { + $identifierUsed = true; + break; + } + } + return $identifierUsed; + } + + /** + * Returns a File object for a given $persistenceIdentifier + * + * @param string $persistenceIdentifier + * @return File + * @throws PersistenceManagerException + */ + protected function getFileByIdentifier(string $persistenceIdentifier): File + { + list($storageUid, $fileIdentifier) = explode(':', $persistenceIdentifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $file = $storage->getFile($fileIdentifier); + if (!$storage->checkFileActionPermission('read', $file)) { + throw new PersistenceManagerException(sprintf('No read access to file "%s".', $persistenceIdentifier), 1471630578); + } + return $file; + } + + /** + * Returns a File object for a given $persistenceIdentifier. + * If no file for this identifier exists a new object will be + * created. + * + * @param string $persistenceIdentifier + * @return File + * @throws PersistenceManagerException + */ + protected function getOrCreateFile(string $persistenceIdentifier): File + { + list($storageUid, $fileIdentifier) = explode(':', $persistenceIdentifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $pathinfo = PathUtility::pathinfo($fileIdentifier); + + if (!$storage->hasFolder($pathinfo['dirname'])) { + throw new PersistenceManagerException(sprintf('Could not create folder "%s".', $pathinfo['dirname']), 1471630579); + } + $folder = $storage->getFolder($pathinfo['dirname']); + if (!$storage->checkFolderActionPermission('write', $folder)) { + throw new PersistenceManagerException(sprintf('No write access to folder "%s".', $pathinfo['dirname']), 1471630580); + } + + if (!$storage->hasFile($fileIdentifier)) { + $file = $folder->createFile($pathinfo['basename']); + } else { + $file = $storage->getFile($fileIdentifier); + } + return $file; + } + + /** + * Returns a ResourceStorage for a given uid + * + * @param int $storageUid + * @return ResourceStorage + * @throws PersistenceManagerException + */ + protected function getStorageByUid(int $storageUid): ResourceStorage + { + $storage = $this->storageRepository->findByUid($storageUid); + if ( + !$storage instanceof ResourceStorage + || !$storage->isBrowsable() + ) { + throw new PersistenceManagerException(sprintf('Could not access storage with uid "%d".', $storageUid), 1471630581); + } + return $storage; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f1cd660ddb62fb7e5172ba07315cc955a7c0f2a7 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php @@ -0,0 +1,110 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Persistence; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\Folder; + +/** + * The form persistence manager interface + * + * Scope: frontend / backend + */ +interface FormPersistenceManagerInterface +{ + + /** + * Load the array form representation identified by $persistenceIdentifier, and return it + * + * @param string $persistenceIdentifier + * @return array + * @api + */ + public function load(string $persistenceIdentifier): array; + + /** + * Save the array form representation identified by $persistenceIdentifier + * + * @param string $persistenceIdentifier + * @param array $formDefinition + * @api + */ + public function save(string $persistenceIdentifier, array $formDefinition); + + /** + * Check whether a form with the specified $persistenceIdentifier exists + * + * @param string $persistenceIdentifier + * @return bool TRUE if a form with the given $persistenceIdentifier can be loaded, otherwise FALSE + * @api + */ + public function exists(string $persistenceIdentifier): bool; + + /** + * Delete the form representation identified by $persistenceIdentifier + * + * @param string $persistenceIdentifier + * @return void + * @api + */ + public function delete(string $persistenceIdentifier); + + /** + * List all form definitions which can be loaded through this form persistence + * manager. + * + * Returns an associative array with each item containing the keys 'name' (the human-readable name of the form) + * and 'persistenceIdentifier' (the unique identifier for the Form Persistence Manager e.g. the path to the saved form definition). + * + * @return array in the format [['name' => 'Form 01', 'persistenceIdentifier' => 'path1'], [ .... ]] + * @api + */ + public function listForms(): array; + + /** + * Return a list of all accessible file mount points + * + * @return Folder[] + * @api + */ + public function getAccessibleFormStorageFolders(): array; + + /** + * Return a list of all accessible extension folders + * + * @return array + * @api + */ + public function getAccessibleExtensionFolders(): array; + + /** + * This takes a form identifier and returns a unique persistence identifier for it. + * + * @param string $formIdentifier + * @param string $savePath + * @return string + * @api + */ + public function getUniquePersistenceIdentifier(string $formIdentifier, string $savePath): string; + + /** + * Check if a identifier is already used by a formDefintion. + * + * @param string $identifier + * @return bool + * @api + */ + public function checkForDuplicateIdentifier(string $identifier): bool; +} diff --git a/typo3/sysext/form/Classes/Mvc/ProcessingRule.php b/typo3/sysext/form/Classes/Mvc/ProcessingRule.php new file mode 100644 index 0000000000000000000000000000000000000000..6b8949a420b5bd2e65122cd354171616987181dc --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/ProcessingRule.php @@ -0,0 +1,181 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Error\Result; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Property\PropertyMapper; +use TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration; +use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator; +use TYPO3\CMS\Extbase\Validation\Validator\ValidatorInterface; + +/** + * A processing Rule contains information for property mapping and validation. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +class ProcessingRule +{ + + /** + * The target data type the data should be converted to + * + * @var string + */ + protected $dataType; + + /** + * @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration + */ + protected $propertyMappingConfiguration; + + /** + * @var \TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator + */ + protected $validator; + + /** + * @var \TYPO3\CMS\Extbase\Error\Result + */ + protected $processingMessages; + + /** + * @var \TYPO3\CMS\Extbase\Property\PropertyMapper + */ + protected $propertyMapper; + + /** + * @param \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration + * @return void + * @internal + */ + public function injectPropertyMappingConfiguration(\TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration) + { + $this->propertyMappingConfiguration = $propertyMappingConfiguration; + } + + /** + * @param \TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator $validator + * @return void + * @internal + */ + public function injectConjunctionValidator(\TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator $validator) + { + $this->validator = $validator; + } + + /** + * @param \TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper + * @return void + * @internal + */ + public function injectPropertyMapper(\TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper) + { + $this->propertyMapper = $propertyMapper; + } + + /** + * Constructs this processing rule + * @internal + */ + public function __construct() + { + $this->processingMessages = GeneralUtility::makeInstance(ObjectManager::class) + ->get(Result::class); + } + + /** + * @return PropertyMappingConfiguration + * @internal + */ + public function getPropertyMappingConfiguration(): PropertyMappingConfiguration + { + return $this->propertyMappingConfiguration; + } + + /** + * @return string + * @internal + */ + public function getDataType(): string + { + return $this->dataType; + } + + /** + * @param string $dataType + * @internal + */ + public function setDataType(string $dataType) + { + $this->dataType = $dataType; + } + + /** + * Returns the child validators of the ConjunctionValidator that is bound to this processing rule + * + * @return \SplObjectStorage<ValidatorInterface> + * @internal + */ + public function getValidators(): \SplObjectStorage + { + return $this->validator->getValidators(); + } + + /** + * @param ValidatorInterface $validator + * @return void + * @internal + */ + public function addValidator(ValidatorInterface $validator) + { + $this->validator->addValidator($validator); + } + + /** + * @param mixed $value + * @return mixed + * @internal + */ + public function process($value) + { + if ($this->dataType !== null) { + $value = $this->propertyMapper->convert($value, $this->dataType, $this->propertyMappingConfiguration); + $messages = $this->propertyMapper->getMessages(); + } else { + $messages = GeneralUtility::makeInstance(ObjectManager::class) + ->get(Result::class); + } + + $validationResult = $this->validator->validate($value); + $messages->merge($validationResult); + + $this->processingMessages->merge($messages); + return $value; + } + + /** + * @return Result + * @internal + */ + public function getProcessingMessages(): Result + { + return $this->processingMessages; + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php b/typo3/sysext/form/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php new file mode 100644 index 0000000000000000000000000000000000000000..7ced599d51037afd1d69cf024a69aabf48d7e42e --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php @@ -0,0 +1,291 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Property\TypeConverter; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\File as File; +use TYPO3\CMS\Core\Resource\FileReference as CoreFileReference; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Domain\Model\AbstractFileFolder; +use TYPO3\CMS\Extbase\Domain\Model\FileReference as ExtbaseFileReference; +use TYPO3\CMS\Extbase\Error\Error; +use TYPO3\CMS\Extbase\Property\Exception\TypeConverterException; +use TYPO3\CMS\Extbase\Property\PropertyMappingConfigurationInterface; +use TYPO3\CMS\Extbase\Property\TypeConverter\AbstractTypeConverter; +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; + +/** + * Class UploadedFileReferenceConverter + * + * Scope: frontend + * @internal + */ +class UploadedFileReferenceConverter extends AbstractTypeConverter +{ + + /** + * Folder where the file upload should go to (including storage). + */ + const CONFIGURATION_UPLOAD_FOLDER = 1; + + /** + * How to handle a upload when the name of the uploaded file conflicts. + */ + const CONFIGURATION_UPLOAD_CONFLICT_MODE = 2; + + /** + * Validator for file types + */ + const CONFIGURATION_FILE_VALIDATORS = 4; + + /** + * @var string + */ + protected $defaultUploadFolder = '1:/user_upload/'; + + /** + * One of 'cancel', 'replace', 'rename' + * + * @var string + */ + protected $defaultConflictMode = 'rename'; + + /** + * @var array + */ + protected $sourceTypes = ['array']; + + /** + * @var string + */ + protected $targetType = ExtbaseFileReference::class; + + /** + * Take precedence over the available FileReferenceConverter + * + * @var int + */ + protected $priority = 2; + + /** + * @var \TYPO3\CMS\Core\Resource\FileInterface[] + */ + protected $convertedResources = []; + + /** + * @var \TYPO3\CMS\Core\Resource\ResourceFactory + */ + protected $resourceFactory; + + /** + * @var \TYPO3\CMS\Extbase\Security\Cryptography\HashService + */ + protected $hashService; + + /** + * @var \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface + */ + protected $persistenceManager; + + /** + * @param \TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory + * @return void + * @internal + */ + public function injectResourceFactory(\TYPO3\CMS\Core\Resource\ResourceFactory $resourceFactory) + { + $this->resourceFactory = $resourceFactory; + } + + /** + * @param \TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService + * @return void + * @internal + */ + public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService) + { + $this->hashService = $hashService; + } + + /** + * @param \TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager + * @return void + * @internal + */ + public function injectPersistenceManager(\TYPO3\CMS\Extbase\Persistence\PersistenceManagerInterface $persistenceManager) + { + $this->persistenceManager = $persistenceManager; + } + + /** + * Actually convert from $source to $targetType, taking into account the fully + * built $convertedChildProperties and $configuration. + * + * @param string|int $source + * @param string $targetType + * @param array $convertedChildProperties + * @param PropertyMappingConfigurationInterface $configuration + * @return AbstractFileFolder + * @internal + */ + public function convertFrom($source, $targetType, array $convertedChildProperties = [], PropertyMappingConfigurationInterface $configuration = null) + { + if (!isset($source['error']) || $source['error'] === \UPLOAD_ERR_NO_FILE) { + if (isset($source['submittedFile']['resourcePointer'])) { + try { + $resourcePointer = $this->hashService->validateAndStripHmac($source['submittedFile']['resourcePointer']); + if (strpos($resourcePointer, 'file:') === 0) { + $fileUid = substr($resourcePointer, 5); + return $this->createFileReferenceFromFalFileObject($this->resourceFactory->getFileObject($fileUid)); + } else { + return $this->createFileReferenceFromFalFileReferenceObject($this->resourceFactory->getFileReferenceObject($resourcePointer), $resourcePointer); + } + } catch (\InvalidArgumentException $e) { + // Nothing to do. No file is uploaded and resource pointer is invalid. Discard! + } + } + return null; + } + + if ($source['error'] !== \UPLOAD_ERR_OK) { + return $this->objectManager->get(Error::class, $this->getUploadErrorMessage($source['error']), 1471715915); + } + + if (isset($this->convertedResources[$source['tmp_name']])) { + return $this->convertedResources[$source['tmp_name']]; + } + + try { + $resource = $this->importUploadedResource($source, $configuration); + } catch (\Exception $e) { + return $this->objectManager->get(Error::class, $e->getMessage(), $e->getCode()); + } + + $this->convertedResources[$source['tmp_name']] = $resource; + return $resource; + } + + /** + * Import a resource and respect configuration given for properties + * + * @param array $uploadInfo + * @param PropertyMappingConfigurationInterface $configuration + * @return ExtbaseFileReference + * @throws TypeConverterException + */ + protected function importUploadedResource( + array $uploadInfo, + PropertyMappingConfigurationInterface $configuration + ): ExtbaseFileReference { + if (!GeneralUtility::verifyFilenameAgainstDenyPattern($uploadInfo['name'])) { + throw new TypeConverterException('Uploading files with PHP file extensions is not allowed!', 1471710357); + } + + $uploadFolderId = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_FOLDER) ?: $this->defaultUploadFolder; + $conflictMode = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_CONFLICT_MODE) ?: $this->defaultConflictMode; + + $uploadFolder = $this->resourceFactory->retrieveFileOrFolderObject($uploadFolderId); + $uploadedFile = $uploadFolder->addUploadedFile($uploadInfo, $conflictMode); + + $validators = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_FILE_VALIDATORS); + if (is_array($validators)) { + foreach ($validators as $validator) { + if ($validator instanceof AbstractValidator) { + $validationResult = $validator->validate($uploadedFile); + if ($validationResult->hasErrors()) { + $uploadedFile->getStorage()->deleteFile($uploadedFile); + throw new TypeConverterException($validationResult->getErrors()[0]->getMessage(), 1471708999); + } + } + } + } + + $resourcePointer = isset($uploadInfo['submittedFile']['resourcePointer']) && strpos($uploadInfo['submittedFile']['resourcePointer'], 'file:') === false + ? $this->hashService->validateAndStripHmac($uploadInfo['submittedFile']['resourcePointer']) + : null; + + $fileReferenceModel = $this->createFileReferenceFromFalFileObject($uploadedFile, $resourcePointer); + + return $fileReferenceModel; + } + + /** + * @param File $file + * @param int $resourcePointer + * @return ExtbaseFileReference + */ + protected function createFileReferenceFromFalFileObject( + File $file, + int $resourcePointer = null + ): ExtbaseFileReference { + $fileReference = $this->resourceFactory->createFileReferenceObject( + [ + 'uid_local' => $file->getUid(), + 'uid_foreign' => uniqid('NEW_'), + 'uid' => uniqid('NEW_'), + 'crop' => null, + ] + ); + return $this->createFileReferenceFromFalFileReferenceObject($fileReference, $resourcePointer); + } + + /** + * @param CoreFileReference $falFileReference + * @param int $resourcePointer + * @return ExtbaseFileReference + */ + protected function createFileReferenceFromFalFileReferenceObject( + CoreFileReference $falFileReference, + int $resourcePointer = null + ): ExtbaseFileReference { + if ($resourcePointer === null) { + $fileReference = $this->objectManager->get(ExtbaseFileReference::class); + } else { + $fileReference = $this->persistenceManager->getObjectByIdentifier($resourcePointer, ExtbaseFileReference::class, false); + } + + $fileReference->setOriginalResource($falFileReference); + return $fileReference; + } + + /** + * Returns a human-readable message for the given PHP file upload error + * constant. + * + * @param int $errorCode + * @return string + */ + protected function getUploadErrorMessage(int $errorCode): string + { + switch ($errorCode) { + case \UPLOAD_ERR_INI_SIZE: + return 'The uploaded file exceeds the upload_max_filesize directive in php.ini'; + case \UPLOAD_ERR_FORM_SIZE: + return 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'; + case \UPLOAD_ERR_PARTIAL: + return 'The uploaded file was only partially uploaded'; + case \UPLOAD_ERR_NO_FILE: + return 'No file was uploaded'; + case \UPLOAD_ERR_NO_TMP_DIR: + return 'Missing a temporary folder'; + case \UPLOAD_ERR_CANT_WRITE: + return 'Failed to write file to disk'; + case \UPLOAD_ERR_EXTENSION: + return 'File upload stopped by extension'; + default: + return 'Unknown upload error'; + } + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Validation/CountValidator.php b/typo3/sysext/form/Classes/Mvc/Validation/CountValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..1d21963e671a30169d59d831ba28831c6b630ddf --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Validation/CountValidator.php @@ -0,0 +1,69 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; + +/** + * Validator for countable types + * + * Scope: frontend + * @internal + */ +class CountValidator extends AbstractValidator +{ + /** + * @var array + */ + protected $supportedOptions = [ + 'minimum' => [0, 'The minimum count to accept', 'integer'], + 'maximum' => [PHP_INT_MAX, 'The maximum count to accept', 'integer'] + ]; + + /** + * The given value is valid if it is an array or \Countable that contains the specified amount of elements. + * + * @param mixed $value + * @return void + * @api + */ + public function isValid($value) + { + if (!is_array($value) && !($value instanceof \Countable)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1475002976', + 'form' + ), + 1475002976 + ); + return; + } + + $minimum = (int)$this->options['minimum']; + $maximum = (int)$this->options['maximum']; + if (count($value) < $minimum || count($value) > $maximum) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1475002994', + 'form', + [$minimum, $maximum] + ), + 1475002994 + ); + } + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Validation/EmptyValidator.php b/typo3/sysext/form/Classes/Mvc/Validation/EmptyValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..5e1204a5520e2b9c3c2c9bbb29dcfdd0ec16460d --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Validation/EmptyValidator.php @@ -0,0 +1,55 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; + +/** + * Validator for empty values. + * + * Scope: frontend + * @api + */ +class EmptyValidator extends AbstractValidator +{ + /** + * This validator always needs to be executed even if the given value is empty. + * See AbstractValidator::validate() + * + * @var bool + */ + protected $acceptsEmptyValues = true; + + /** + * Checks if the given property ($propertyValue) is empty (NULL, empty string, empty array or empty object). + * + * @param mixed $value The value that should be validated + * @return void + * @api + */ + public function isValid($value) + { + if (!empty($value)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1476396435', + 'form' + ), + 1476396435 + ); + } + } +} diff --git a/typo3/sysext/form/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php b/typo3/sysext/form/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php new file mode 100644 index 0000000000000000000000000000000000000000..5386627f7f801f1dc7408f1d03a0e39ba3ef5d53 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php @@ -0,0 +1,25 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Validation\Exception; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Exception; + +/** + * @api + */ +class InvalidValidationOptionsException extends Exception +{ +} diff --git a/typo3/sysext/form/Classes/Mvc/Validation/MimeTypeValidator.php b/typo3/sysext/form/Classes/Mvc/Validation/MimeTypeValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..4cf7b93a030e1eedc3bdcf6965c1b3b9f86f847c --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/Validation/MimeTypeValidator.php @@ -0,0 +1,90 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; +use TYPO3\CMS\Form\Mvc\Validation\Exception\InvalidValidationOptionsException; + +/** + * Validator for mime types + * + * Scope: frontend + * @api + */ +class MimeTypeValidator extends AbstractValidator +{ + /** + * @var array + */ + protected $supportedOptions = [ + 'allowedMimeTypes' => [null, 'Allowed mime types (using */* IANA media types)', 'array', true] + ]; + + /** + * The given $value is valid if it is an FileReference of the + * configured type (one of the image/* IANA media subtypes) + * + * Note: a value of NULL or empty string ('') is considered valid + * + * @param FileReference|File $resource The resource that should be validated + * @return void + * @api + */ + public function isValid($resource) + { + $this->validateOptions(); + + if ($resource instanceof FileReference) { + $resource = $resource->getOriginalResource(); + } elseif (!$resource instanceof File) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1471708997', + 'form' + ), + 1471708997 + ); + return; + } + + $allowedMimeTypes = $this->options['allowedMimeTypes']; + if (!in_array($resource->getMimeType(), $allowedMimeTypes, true)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1471708998', + 'form', + [$resource->getMimeType()] + ), + 1471708998 + ); + } + } + + /** + * Checks if this validator is correctly configured + * + * @return void + * @throws InvalidValidationOptionsException if the configured validation options are incorrect + */ + protected function validateOptions() + { + if (!is_array($this->options['allowedMimeTypes']) || $this->options['allowedMimeTypes'] === []) { + throw new InvalidValidationOptionsException('The option "allowedMimeTypes" must be an array with at least one item.', 1471713296); + } + } +} diff --git a/typo3/sysext/form/Classes/Mvc/View/FormView.php b/typo3/sysext/form/Classes/Mvc/View/FormView.php new file mode 100644 index 0000000000000000000000000000000000000000..8cac863e5763d51fa06a4e4f746b513bbb14df69 --- /dev/null +++ b/typo3/sysext/form/Classes/Mvc/View/FormView.php @@ -0,0 +1,233 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Mvc\View; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Fluid\View\AbstractTemplateView; +use TYPO3\CMS\Form\Domain\Exception\RenderingException; +use TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Renderer\RendererInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * A fluid TemplateView implementation which used to render *Renderables*. + * + * The FormView is especially capable of rendering nested renderables + * as well, i.e a form with a page, with all FormElements. + * + * Options + * ======= + * + * The FormView uses some rendering options which are of particular + * importance, as they determine how the form field is resolved to a path + * in the file system. + * + * All rendering options are retrieved from the renderable which shall be rendered, + * using the {@link \TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface::getRenderingOptions()} + * method. + * + * templateRootPaths + * ----------------- + * + * Used to define several paths for templates, which will be tried in reversed + * order (the paths are searched from bottom to top). The first folder where + * the desired layout is found, is used. If the array keys are numeric, + * they are first sorted and then tried in reversed order. + * + * layoutRootPaths + * --------------- + * + * Used to define several paths for layouts, which will be tried in reversed + * order (the paths are searched from bottom to top). The first folder where + * the desired layout is found, is used. If the array keys are numeric, + * they are first sorted and then tried in reversed order. + * + * partialRootPaths + * ---------------- + * + * Used to define several paths for partials, which will be tried in reversed + * order. The first folder where the desired partial is found, is used. + * The keys of the array define the order. + * + * renderableNameInTemplate + * ------------------------ + * + * This is a mostly-internal setting which controls the name under which the current + * renderable is made available inside the template. For example, it controls that + * inside the template of a "Page", the Page object is available using the variable + * *page*. + * + * Rendering Child Renderables + * =========================== + * + * If a renderable wants to render child renderables, inside its template, + * it can do that using the <code><formvh:renderRenderable></code> ViewHelper. + * + * A template example from Page shall demonstrate this: + * + * <pre> + * {namespace formvh=TYPO3\CMS\Form\ViewHelpers} + * <f:for each="{page.elements}" as="element"> + * <formvh:renderRenderable renderable="{element}" /> + * </f:for> + * </pre> + * + * Rendering PHP Based Child Renderables + * ===================================== + * + * If a child renderable has a *rendererClassName* set (i.e. {@link \TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface::getRendererClassName()} + * returns a non-NULL string), this renderer is automatically instanciated + * and the rendering for this element is delegated to this Renderer. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +class FormView extends AbstractTemplateView +{ + + /** + * @var \TYPO3\CMS\Form\Domain\Runtime\FormRuntime + */ + protected $formRuntime; + + /** + * @param FormRuntime $formRuntime + * @return void + * @internal + */ + public function setFormRuntime(FormRuntime $formRuntime) + { + $this->formRuntime = $formRuntime; + } + + /** + * @return FormRuntime + * @internal + */ + public function getFormRuntime(): FormRuntime + { + return $this->formRuntime; + } + + /** + * Render the $renderable and return the content. + * + * @param RootRenderable $renderable + * @return string + * @throws RenderingException + * @internal + */ + public function renderRenderable(RootRenderableInterface $renderable): string + { + // Invoke the beforeRendering callback on the renderable + $renderable->beforeRendering($this->formRuntime); + + if ( + $renderable->getRendererClassName() !== null + && $renderable->getRendererClassName() !== $this->formRuntime->getRendererClassName() + ) { + // If a child renderable has a *rendererClassName* set + // then render it with this foreign renderer. + $rendererClassName = $renderable->getRendererClassName(); + $renderer = GeneralUtility::makeInstance(ObjectManager::class)->get($rendererClassName); + if (!($renderer instanceof RendererInterface)) { + throw new RenderingException( + sprintf('The renderer class "%s" for "%s" does not implement RendererInterface.', $rendererClassName, $renderable->getType()), + 1480286138 + ); + } + $renderer->setControllerContext($this->baseRenderingContext->getControllerContext()); + $renderer->setFormRuntime($this->formRuntime); + return $renderer->render($renderable); + } + + $renderingOptions = $renderable->getRenderingOptions(); + + if (!isset($renderingOptions['templateRootPaths'])) { + throw new RenderingException( + sprintf('The option templateRootPaths must be set for renderable "%s"', $renderable->getType()), + 1480293084 + ); + } + if (!isset($renderingOptions['layoutRootPaths'])) { + throw new RenderingException( + sprintf('The option layoutRootPaths must be set for renderable "%s"', $renderable->getType()), + 1480293085 + ); + } + if (!isset($renderingOptions['partialRootPaths'])) { + throw new RenderingException( + sprintf('The option partialRootPaths must be set for renderable "%s"', $renderable->getType()), + 1480293086 + ); + } + if (!isset($renderingOptions['renderableNameInTemplate'])) { + throw new RenderingException( + sprintf('The option renderableNameInTemplate must be set for renderable "%s"', $renderable->getType()), + 1480293087 + ); + } + + $renderingContext = $this->getCurrentRenderingContext(); + // Configure the fluid TemplateView with the rendering options + // from the renderable + $renderingContext->getTemplatePaths()->setTemplateRootPaths($renderingOptions['templateRootPaths']); + $renderingContext->getTemplatePaths()->setLayoutRootPaths($renderingOptions['layoutRootPaths']); + $renderingContext->getTemplatePaths()->setPartialRootPaths($renderingOptions['partialRootPaths']); + + // Add the renderable object to the template variables and use the + // configured variable name + $renderingContext->getVariableProvider()->add($renderingOptions['renderableNameInTemplate'], $renderable); + + // Render the renderable. + if (isset($renderingOptions['templatePathAndFilename'])) { + $renderingContext->getTemplatePaths()->setTemplatePathAndFilename($renderingOptions['templatePathAndFilename']); + $output = $this->render(); + } else { + // Use the *type* of the renderable as template name + $output = $this->render($renderable->getType()); + } + + return $this->renderPreviewMode($output, $renderable); + } + + /** + * Wrap every renderable with a span with a identifier path data attribute. + * + * @param string $output + * @param RootRenderableInterface $renderable + * @return string + * @internal + */ + protected function renderPreviewMode(string $output, RootRenderableInterface $renderable): string + { + $renderingOptions = $this->formRuntime->getRenderingOptions(); + $previewMode = isset($renderingOptions['previewMode']) && $renderingOptions['previewMode'] === true; + if ($previewMode) { + $path = $renderable->getIdentifier(); + if ($renderable instanceof RenderableInterface) { + while ($renderable = $renderable->getParentRenderable()) { + $path = $renderable->getIdentifier() . '/' . $path; + } + } + $output = sprintf('<span data-element-identifier-path="%s">%s</span>', $path, $output); + } + return $output; + } +} diff --git a/typo3/sysext/form/Classes/PostProcess/AbstractPostProcessor.php b/typo3/sysext/form/Classes/PostProcess/AbstractPostProcessor.php deleted file mode 100644 index 1a0f0366b91d16b57a80890a6498c8a09a91cd6d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/PostProcess/AbstractPostProcessor.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * The mail post processor - */ -abstract class AbstractPostProcessor -{ - /** - * @var \TYPO3\CMS\Form\Mvc\Controller\ControllerContext - */ - protected $controllerContext; - - /** - * Set the current controller context - * - * @param \TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext - * @return void - */ - public function setControllerContext(\TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext) - { - $this->controllerContext = $controllerContext; - } -} diff --git a/typo3/sysext/form/Classes/PostProcess/MailPostProcessor.php b/typo3/sysext/form/Classes/PostProcess/MailPostProcessor.php deleted file mode 100644 index 1cf9517a001936fc0aed793b2aba6035745a7a91..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/PostProcess/MailPostProcessor.php +++ /dev/null @@ -1,566 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Mail\Rfc822AddressesParser; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\MailUtility; -use TYPO3\CMS\Core\Utility\MathUtility; -use TYPO3\CMS\Extbase\Utility\LocalizationUtility; -use TYPO3\CMS\Form\Utility\FormUtility; - -/** - * The mail post processor - */ -class MailPostProcessor extends AbstractPostProcessor implements PostProcessorInterface -{ - /** - * Constant for localization - * - * @var string - */ - const LOCALISATION_OBJECT_NAME = 'tx_form_view_mail'; - - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManager - */ - protected $objectManager; - - /** - * @var \TYPO3\CMS\Form\Utility\SessionUtility - */ - protected $sessionUtility; - - /** - * @var FormUtility - */ - protected $formUtility; - - /** - * @var \TYPO3\CMS\Form\Domain\Model\Element - */ - protected $form; - - /** - * @var array - */ - protected $typoScript; - - /** - * @var \TYPO3\CMS\Core\Mail\MailMessage - */ - protected $mailMessage; - - /** - * @var string - */ - protected $htmlMailTemplatePath = 'Html'; - - /** - * @var string - */ - protected $plaintextMailTemplatePath = 'Plain'; - - /** - * @var array - */ - protected $dirtyHeaders = []; - - /** - * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager - * @return void - */ - public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * @param \TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility - * @return void - */ - public function injectSessionUtility(\TYPO3\CMS\Form\Utility\SessionUtility $sessionUtility) - { - $this->sessionUtility = $sessionUtility; - } - - /** - * Constructor - * - * @param \TYPO3\CMS\Form\Domain\Model\Element $form Form domain model - * @param array $typoScript Post processor TypoScript settings - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript) - { - $this->form = $form; - $this->typoScript = $typoScript; - $this->mailMessage = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Mail\MailMessage::class); - $this->setTemplatePaths(); - } - - /** - * The main method called by the post processor - * - * Configures the mail message - * - * @return string HTML message from this processor - */ - public function process() - { - $this->formUtility = FormUtility::create($this->controllerContext->getConfiguration()); - $this->setSubject(); - $this->setFrom(); - $this->setTo(); - $this->setCc(); - $this->setReplyTo(); - $this->setPriority(); - $this->setOrganization(); - $this->setHtmlContent(); - $this->setPlainContent(); - $this->addAttachmentsFromSession(); - $this->send(); - return $this->render(); - } - - /** - * Sets the subject of the mail message - * - * If not configured, it will use a default setting - * - * @return void - */ - protected function setSubject() - { - if (isset($this->typoScript['subject'])) { - $subject = $this->formUtility->renderItem( - $this->typoScript['subject.'], - $this->typoScript['subject'] - ); - } elseif ($this->getTypoScriptValueFromIncomingData('subjectField') !== null) { - $subject = $this->getTypoScriptValueFromIncomingData('subjectField'); - } else { - $subject = 'Formmail on ' . GeneralUtility::getIndpEnv('HTTP_HOST'); - } - - $subject = $this->sanitizeHeaderString($subject); - $this->mailMessage->setSubject($subject); - } - - /** - * Sets the sender of the mail message - * - * Mostly the sender is a combination of the name and the email address - * - * @return void - */ - protected function setFrom() - { - if (isset($this->typoScript['senderEmail'])) { - $fromEmail = $this->formUtility->renderItem( - $this->typoScript['senderEmail.'], - $this->typoScript['senderEmail'] - ); - } elseif ($this->getTypoScriptValueFromIncomingData('senderEmailField') !== null) { - $fromEmail = $this->getTypoScriptValueFromIncomingData('senderEmailField'); - } else { - $fromEmail = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress']; - } - if (!GeneralUtility::validEmail($fromEmail)) { - $fromEmail = MailUtility::getSystemFromAddress(); - } - if (isset($this->typoScript['senderName'])) { - $fromName = $this->formUtility->renderItem( - $this->typoScript['senderName.'], - $this->typoScript['senderName'] - ); - } elseif ($this->getTypoScriptValueFromIncomingData('senderNameField') !== null) { - $fromName = $this->getTypoScriptValueFromIncomingData('senderNameField'); - } else { - $fromName = $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']; - } - $fromName = $this->sanitizeHeaderString($fromName); - if (!empty($fromName)) { - $from = [$fromEmail => $fromName]; - } else { - $from = $fromEmail; - } - $this->mailMessage->setFrom($from); - } - - /** - * Filter input-string for valid email addresses - * - * @param string $emails If this is a string, it will be checked for one or more valid email addresses. - * @return array List of valid email addresses - */ - protected function filterValidEmails($emails) - { - if (!is_string($emails)) { - // No valid addresses - empty list - return []; - } - - /** @var $addressParser Rfc822AddressesParser */ - $addressParser = GeneralUtility::makeInstance(Rfc822AddressesParser::class, $emails); - $addresses = $addressParser->parseAddressList(); - - $validEmails = []; - foreach ($addresses as $address) { - $fullAddress = $address->mailbox . '@' . $address->host; - if (GeneralUtility::validEmail($fullAddress)) { - if ($address->personal) { - $validEmails[$fullAddress] = $address->personal; - } else { - $validEmails[] = $fullAddress; - } - } - } - return $validEmails; - } - - /** - * Adds the receiver of the mail message when configured - * - * Checks the address if it is a valid email address - * - * @return void - */ - protected function setTo() - { - $emails = $this->formUtility->renderItem( - $this->typoScript['recipientEmail.'], - $this->typoScript['recipientEmail'] - ); - $validEmails = $this->filterValidEmails($emails); - if (!empty($validEmails)) { - $this->mailMessage->setTo($validEmails); - } - } - - /** - * Adds the carbon copy receiver of the mail message when configured - * - * Checks the address if it is a valid email address - * - * @return void - */ - protected function setCc() - { - $emails = $this->formUtility->renderItem( - $this->typoScript['ccEmail.'], - $this->typoScript['ccEmail'] - ); - $validEmails = $this->filterValidEmails($emails); - if (!empty($validEmails)) { - $this->mailMessage->setCc($validEmails); - } - } - - /** - * Adds the reply to header of the mail message when configured - * - * Checks the address if it is a valid email address - * - * @return void - */ - protected function setReplyTo() - { - if (isset($this->typoScript['replyToEmail'])) { - $emails = $this->formUtility->renderItem( - $this->typoScript['replyToEmail.'], - $this->typoScript['replyToEmail'] - ); - } elseif ($this->getTypoScriptValueFromIncomingData('replyToEmailField') !== null) { - $emails = $this->getTypoScriptValueFromIncomingData('replyToEmailField'); - } - $validEmails = $this->filterValidEmails($emails); - if (!empty($validEmails)) { - $this->mailMessage->setReplyTo($validEmails); - } - } - - /** - * Set the priority of the mail message - * - * When not in settings, the value will be 3. If the priority is configured, - * but too big, it will be set to 5, which means very low. - * - * @return void - */ - protected function setPriority() - { - $priority = 3; - if (isset($this->typoScript['priority'])) { - $priorityFromTs = $this->formUtility->renderItem( - $this->typoScript['priority.'], - $this->typoScript['priority'] - ); - } - if (!empty($priorityFromTs)) { - $priority = MathUtility::forceIntegerInRange($priorityFromTs, 1, 5); - } - $this->mailMessage->setPriority($priority); - } - - /** - * Add a text header to the mail header of the type Organization - * - * Sanitizes the header string when necessary - * - * @return void - */ - protected function setOrganization() - { - if (isset($this->typoScript['organization'])) { - $organization = $this->formUtility->renderItem( - $this->typoScript['organization.'], - $this->typoScript['organization'] - ); - } - if (!empty($organization)) { - $organization = $this->sanitizeHeaderString($organization); - $this->mailMessage->getHeaders()->addTextHeader('Organization', $organization); - } - } - - /** - * Set the default character set used - * - * Respect formMailCharset if it was set, otherwise use metaCharset for mail - * if different than utf-8 - * - * @return void - */ - protected function setCharacterSet() - { - $characterSet = null; - if ($GLOBALS['TSFE']->config['config']['formMailCharset']) { - $characterSet = $GLOBALS['TSFE']->csConvObj->parse_charset($GLOBALS['TSFE']->config['config']['formMailCharset']); - } elseif ($GLOBALS['TSFE']->metaCharset !== 'utf-8') { - $characterSet = $GLOBALS['TSFE']->metaCharset; - } - if ($characterSet) { - $this->mailMessage->setCharset($characterSet); - } - } - - /** - * Add the HTML content - * - * Add a MimePart of the type text/html to the message. - * - * @return void - */ - protected function setHtmlContent() - { - $htmlContent = $this->getView($this->htmlMailTemplatePath)->render(); - $this->mailMessage->setBody($htmlContent, 'text/html'); - } - - /** - * Add the plain content - * - * Add a MimePart of the type text/plain to the message. - * - * @return void - */ - protected function setPlainContent() - { - $plainContent = $this->getView($this->plaintextMailTemplatePath, 'Plain')->render(); - $this->mailMessage->addPart($plainContent, 'text/plain'); - } - - /** - * Sends the mail. - * Sending the mail requires the recipient and message to be set. - * - * @return void - */ - protected function send() - { - if ($this->mailMessage->getTo() && $this->mailMessage->getBody()) { - $this->mailMessage->send(); - } - } - - /** - * Render the message after trying to send the mail - * - * @return string HTML message from the mail view - */ - protected function render() - { - if ($this->mailMessage->isSent()) { - $output = $this->renderMessage('success'); - } else { - $output = $this->renderMessage('error'); - } - return $output; - } - - /** - * Checks string for suspicious characters - * - * @param string $string String to check - * @return string Valid or empty string - */ - protected function sanitizeHeaderString($string) - { - $pattern = '/[\\r\\n\\f\\e]/'; - if (preg_match($pattern, $string) > 0) { - $this->dirtyHeaders[] = $string; - $string = ''; - } - return $string; - } - - /** - * Loop through all elements of the session and attach the file - * if its a uploaded file - * - * @return void - */ - protected function addAttachmentsFromSession() - { - $sessionData = $this->sessionUtility->getSessionData(); - if (is_array($sessionData)) { - foreach ($sessionData as $fieldName => $values) { - if (is_array($values)) { - foreach ($values as $file) { - if (isset($file['tempFilename'])) { - if ( - is_file($file['tempFilename']) - && GeneralUtility::isAllowedAbsPath($file['tempFilename']) - ) { - $this->mailMessage->attach(\Swift_Attachment::fromPath($file['tempFilename'])->setFilename($file['name'])); - } - } - } - } - } - } - } - - /** - * Set the html and plaintext templates - * - * @return void - */ - protected function setTemplatePaths() - { - if ( - isset($this->typoScript['htmlMailTemplatePath']) - && $this->typoScript['htmlMailTemplatePath'] !== '' - ) { - $this->htmlMailTemplatePath = $this->typoScript['htmlMailTemplatePath']; - } - - if ( - isset($this->typoScript['plaintextMailTemplatePath']) - && $this->typoScript['plaintextMailTemplatePath'] !== '' - ) { - $this->plaintextMailTemplatePath = $this->typoScript['plaintextMailTemplatePath']; - } - } - - /** - * Make fluid view instance - * - * @param string $templateName - * @param string $scope - * @return \TYPO3\CMS\Fluid\View\StandaloneView - */ - protected function getView($templateName, $scope = 'Html') - { - $configurationManager = $this->objectManager->get(\TYPO3\CMS\Extbase\Configuration\ConfigurationManager::class); - $typoScript = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK); - /** @var \TYPO3\CMS\Fluid\View\StandaloneView $view */ - $view = $this->objectManager->get(\TYPO3\CMS\Fluid\View\StandaloneView::class); - - /* Extend all template root paths to $templateRootPaths/PostProcessor/Mail/$themeName */ - foreach ($typoScript['view']['templateRootPaths'] as &$path) { - if (substr($path, -1) !== '/') { - $path .= '/'; - } - $path .= 'PostProcessor/Mail/' . $this->controllerContext->getConfiguration()->getThemeName(); - } - /* Extend all partial root paths to $partialRootPaths/$themeName/PostProcessor/Mail/$scope/ */ - foreach ($typoScript['view']['partialRootPaths'] as &$path) { - if (substr($path, -1) !== '/') { - $path .= '/'; - } - $path .= $this->controllerContext->getConfiguration()->getThemeName() . '/PostProcessor/Mail/' . $scope . '/'; - } - $view->setLayoutRootPaths($typoScript['view']['layoutRootPaths']); - $view->setTemplateRootPaths($typoScript['view']['templateRootPaths']); - $view->setPartialRootPaths($typoScript['view']['partialRootPaths']); - $view->setTemplate($templateName); - $view->assignMultiple([ - 'model' => $this->form - ]); - return $view; - } - - /** - * Render the processor message - * - * @param string $messageType - * @return string - */ - protected function renderMessage($messageType) - { - return $this->formUtility->renderItem( - $this->typoScript['messages.'][$messageType . '.'], - $this->typoScript['messages.'][$messageType], - $this->getLocalLanguageLabel($messageType) - ); - } - - /** - * Get the local language label(s) for the message - * In some cases this method will be override by rule class - * - * @param string $type The type - * @return string The local language message label - */ - protected function getLocalLanguageLabel($type = '') - { - $label = static::LOCALISATION_OBJECT_NAME . '.' . $type; - $message = LocalizationUtility::translate($label, 'form'); - return $message; - } - - /** - * Determines user submitted data from a field - * that has been defined as TypoScript property. - * - * @param string $propertyName - * @return NULL|mixed - */ - protected function getTypoScriptValueFromIncomingData($propertyName) - { - if (empty($this->typoScript[$propertyName])) { - return null; - } - - $propertyValue = $this->typoScript[$propertyName]; - $incomingData = $this->controllerContext->getValidationElement(); - if (!$incomingData->hasIncomingField($propertyValue)) { - return null; - } - - return $incomingData->getIncomingField($propertyValue); - } -} diff --git a/typo3/sysext/form/Classes/PostProcess/PostProcessor.php b/typo3/sysext/form/Classes/PostProcess/PostProcessor.php deleted file mode 100644 index 1fb2f5227d21fdaff4392b150dbd344dc5f776af..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/PostProcess/PostProcessor.php +++ /dev/null @@ -1,106 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\ArrayUtility; - -/** - * The post processor - */ -class PostProcessor extends AbstractPostProcessor -{ - /** - * @var \TYPO3\CMS\Extbase\Object\ObjectManager - */ - protected $objectManager; - - /** - * @var array - */ - protected $postProcessorTypoScript; - - /** - * @var \TYPO3\CMS\Form\Domain\Model\Element $form - */ - protected $form; - - /** - * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager - * @return void - */ - public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) - { - $this->objectManager = $objectManager; - } - - /** - * Constructor - * - * @param \TYPO3\CMS\Form\Domain\Model\Element $form - * @param array $postProcessorTypoScript Post processor TypoScript settings - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $postProcessorTypoScript) - { - $this->form = $form; - $this->postProcessorTypoScript = $postProcessorTypoScript; - } - - /** - * The main method called by the controller - * - * Iterates over the configured post processors and calls them with their - * own settings - * - * @return string HTML messages from the called processors - */ - public function process() - { - $html = ''; - - if (is_array($this->postProcessorTypoScript)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($this->postProcessorTypoScript); - - foreach ($keys as $key) { - if (!(int)$key || strpos($key, '.') !== false) { - continue; - } - $className = false; - $processorName = $this->postProcessorTypoScript[$key]; - $processorArguments = []; - if (isset($this->postProcessorTypoScript[$key . '.'])) { - $processorArguments = $this->postProcessorTypoScript[$key . '.']; - } - - if (class_exists($processorName, true)) { - $className = $processorName; - } else { - $classNameExpanded = 'TYPO3\\CMS\\Form\\PostProcess\\' . ucfirst(strtolower($processorName)) . 'PostProcessor'; - if (class_exists($classNameExpanded, true)) { - $className = $classNameExpanded; - } - } - if ($className !== false) { - $processor = $this->objectManager->get($className, $this->form, $processorArguments); - if ($processor instanceof PostProcessorInterface) { - $processor->setControllerContext($this->controllerContext); - $html .= $processor->process(); - } - } - } - } - - return $html; - } -} diff --git a/typo3/sysext/form/Classes/PostProcess/PostProcessorInterface.php b/typo3/sysext/form/Classes/PostProcess/PostProcessorInterface.php deleted file mode 100644 index bbbbc7d898658cc063941c6a2ea9586852eb13a5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/PostProcess/PostProcessorInterface.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Interface for post-processors - */ -interface PostProcessorInterface -{ - /** - * Constructor - * - * @param \TYPO3\CMS\Form\Domain\Model\Element $form Form domain model - * @param array $typoScript Post processor TypoScript settings - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript); - - /** - * Set the current controller context - * - * @param \TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext - * @return void - */ - public function setControllerContext(\TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext); - - /** - * The main method called by the post processor - * - * @return string The post processing HTML - */ - public function process(); -} diff --git a/typo3/sysext/form/Classes/PostProcess/RedirectPostProcessor.php b/typo3/sysext/form/Classes/PostProcess/RedirectPostProcessor.php deleted file mode 100644 index 58f7083997b1bbad346e3e00dc11839870c3002a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/PostProcess/RedirectPostProcessor.php +++ /dev/null @@ -1,84 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * The redirect post-processor - */ -class RedirectPostProcessor extends AbstractPostProcessor implements PostProcessorInterface -{ - /** - * @var \TYPO3\CMS\Form\Domain\Model\Element - */ - protected $form; - - /** - * @var array - */ - protected $typoScript; - - /** - * @var string - */ - protected $destination; - - /** - * Constructor - * - * @param \TYPO3\CMS\Form\Domain\Model\Element $form Form domain model - * @param array $typoScript Post processor TypoScript settings - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript) - { - $this->form = $form; - $this->typoScript = $typoScript; - } - - /** - * The main method called by the post processor - * - * @return string HTML message from this processor - */ - public function process() - { - $this->setDestination(); - $this->render(); - } - - /** - * Sets the redirect destination - * - * @return void - */ - protected function setDestination() - { - $this->destination = ''; - if ($this->typoScript['destination']) { - $urlConf = ['parameter' => $this->typoScript['destination']]; - $this->destination = $GLOBALS['TSFE']->cObj->typoLink_URL($urlConf); - } - } - - /** - * Redirect to a destination - * - * @return void - */ - protected function render() - { - \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->destination); - return; - } -} diff --git a/typo3/sysext/form/Classes/Service/TranslationService.php b/typo3/sysext/form/Classes/Service/TranslationService.php new file mode 100644 index 0000000000000000000000000000000000000000..b975b03d38b3c942a847cb5025bf08db80b14c7d --- /dev/null +++ b/typo3/sysext/form/Classes/Service/TranslationService.php @@ -0,0 +1,508 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Service; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Localization\Locales; +use TYPO3\CMS\Core\Localization\LocalizationFactory; +use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Utility\ArrayUtility; +use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; +use TYPO3\CMS\Lang\LanguageService; + +/** + * Advanced translations + * This class is subjected to change. + * **Do NOT subclass** + * + * Scope: frontend / backend + * @internal + */ +class TranslationService implements SingletonInterface +{ + + /** + * Local Language content + * + * @var array + */ + protected $LOCAL_LANG = []; + + /** + * Contains those LL keys, which have been set to (empty) in TypoScript. + * This is necessary, as we cannot distinguish between a nonexisting + * translation and a label that has been cleared by TS. + * In both cases ['key'][0]['target'] is "". + * + * @var array + */ + protected $LOCAL_LANG_UNSET = []; + + /** + * Key of the language to use + * + * @var string + */ + protected $languageKey = null; + + /** + * Pointer to alternative fall-back language to use + * + * @var array + */ + protected $alternativeLanguageKeys = []; + + /** + * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface + */ + protected $configurationManager = null; + + /** + * Return TranslationService as singleton + * + * @return TranslationService + * @internal + */ + public static function getInstance() + { + return GeneralUtility::makeInstance(ObjectManager::class)->get(self::class); + } + + /** + * Returns the localized label of the LOCAL_LANG key, $key. + * + * @param mixed $key The key from the LOCAL_LANG array for which to return the value. + * @param array $arguments the arguments of the extension, being passed over to vsprintf + * @param string $locallangPathAndFilename + * @param string $language + * @param mixed $defaultValue + * @return mixed The value from LOCAL_LANG or $defaultValue if no translation was found. + * @internal + */ + public function translate( + $key, + array $arguments = null, + string $locallangPathAndFilename = null, + string $language = null, + $defaultValue = '' + ) { + $value = null; + $key = (string)$key; + + if ($locallangPathAndFilename) { + $key = $locallangPathAndFilename . ':' . $key; + } + + $keyParts = explode(':', $key); + if (GeneralUtility::isFirstPartOfStr($key, 'LLL:')) { + $locallangPathAndFilename = $keyParts[1] . ':' . $keyParts[2]; + $key = $keyParts[3]; + } elseif (GeneralUtility::isFirstPartOfStr($key, 'EXT:')) { + $locallangPathAndFilename = $keyParts[0] . ':' . $keyParts[1]; + $key = $keyParts[2]; + } else { + if (count($keyParts) === 2) { + $locallangPathAndFilename = $keyParts[0]; + $key = $keyParts[1]; + } + } + + if ($language) { + $this->languageKey = $language; + } + + $this->initializeLocalization($locallangPathAndFilename); + + // The "from" charset of csConv() is only set for strings from TypoScript via _LOCAL_LANG + if (!empty($this->LOCAL_LANG[$this->languageKey][$key][0]['target']) + || isset($this->LOCAL_LANG_UNSET[$this->languageKey][$key]) + ) { + // Local language translation for key exists + $value = $this->LOCAL_LANG[$this->languageKey][$key][0]['target']; + } elseif (!empty($this->alternativeLanguageKeys)) { + $languages = array_reverse($this->alternativeLanguageKeys); + foreach ($languages as $language) { + if (!empty($this->LOCAL_LANG[$language][$key][0]['target']) + || isset($this->LOCAL_LANG_UNSET[$language][$key]) + ) { + // Alternative language translation for key exists + $value = $this->LOCAL_LANG[$language][$key][0]['target']; + break; + } + } + } + + if ($value === null && (!empty($this->LOCAL_LANG['default'][$key][0]['target']) + || isset($this->LOCAL_LANG_UNSET['default'][$key])) + ) { + // Default language translation for key exists + // No charset conversion because default is English and thereby ASCII + $value = $this->LOCAL_LANG['default'][$key][0]['target']; + } + + if (is_array($arguments) && $value !== null) { + $value = vsprintf($value, $arguments); + } else { + if (empty($value)) { + $value = $defaultValue; + } + } + + return $value; + } + + /** + * Recursively translate values. + * + * @param array $array + * @param string $translationFile + * @return array the modified array + * @internal + */ + public function translateValuesRecursive(array $array, string $translationFile = null): array + { + $result = $array; + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = $this->translateValuesRecursive($value, $translationFile); + } else { + $result[$key] = $this->translate($value, null, $translationFile, null, $value); + } + } + return $result; + } + + /** + * @param FormRuntime $formRuntime + * @param string $finisherIdentifier + * @param string $optionKey + * @param string $optionValue + * @param array $renderingOptions + * @return string + * @throws \InvalidArgumentException + * @api + */ + public function translateFinisherOption( + FormRuntime $formRuntime, + string $finisherIdentifier, + string $optionKey, + string $optionValue, + array $renderingOptions = [] + ): string { + if (empty($finisherIdentifier)) { + throw new \InvalidArgumentException('The argument "finisherIdentifier" is empty', 1476216059); + } + if (empty($optionKey)) { + throw new \InvalidArgumentException('The argument "optionKey" is empty', 1476216060); + } + + $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier); + $translationFile = $renderingOptions['translationFile']; + if (isset($renderingOptions['translatePropertyValueIfEmpty'])) { + $translatePropertyValueIfEmpty = (bool)$renderingOptions['translatePropertyValueIfEmpty']; + } else { + $translatePropertyValueIfEmpty = true; + } + + if (empty($optionValue) && !$translatePropertyValueIfEmpty) { + return $optionValue; + } + + $language = null; + if (isset($renderingOptions['language'])) { + $language = $renderingOptions['language']; + } + + $translationKeyChain = [ + sprintf('%s:%s.finisher.%s.%s', $translationFile, $formRuntime->getIdentifier(), $finisherIdentifier, $optionKey), + sprintf('%s:finisher.%s.%s', $translationFile, $finisherIdentifier, $optionKey) + ]; + $translatedValue = $this->processTranslationChain($translationKeyChain, $language); + $translatedValue = (empty($translatedValue)) ? $optionValue : $translatedValue; + + return $translatedValue; + } + + /** + * @param RootRenderableInterface $element + * @param string $property + * @param FormRuntime $formRuntime + * @return string|array + * @throws \InvalidArgumentException + * @internal + */ + public function translateFormElementValue( + RootRenderableInterface $element, + string $property, + FormRuntime $formRuntime + ) { + if (empty($property)) { + throw new \InvalidArgumentException('The argument "property" is empty', 1476216007); + } + + $propertyType = 'properties'; + $renderingOptions = $element->getRenderingOptions(); + + if ($property === 'label') { + $defaultValue = $element->getLabel(); + } else { + if ($element instanceof FormElementInterface) { + $defaultValue = ArrayUtility::getValueByPath($element->getProperties(), $property); + } else { + $propertyType = 'renderingOptions'; + $defaultValue = ArrayUtility::getValueByPath($renderingOptions, $property); + } + } + + if (isset($renderingOptions['translation']['translatePropertyValueIfEmpty'])) { + $translatePropertyValueIfEmpty = $renderingOptions['translation']['translatePropertyValueIfEmpty']; + } else { + $translatePropertyValueIfEmpty = true; + } + + if (empty($defaultValue) && !$translatePropertyValueIfEmpty) { + return $defaultValue; + } + + $defaultValue = empty($defaultValue) ? '' : $defaultValue; + $translationFile = $renderingOptions['translation']['translationFile']; + + $language = null; + if (isset($renderingOptions['translation']['language'])) { + $language = $renderingOptions['translation']['language']; + } + $translationKeyChain = []; + if ($property === 'options' && is_array($defaultValue)) { + foreach ($defaultValue as $optionValue => &$optionLabel) { + $translationKeyChain = [ + sprintf('%s:%s.element.%s.%s.%s.%s', $translationFile, $formRuntime->getIdentifier(), $element->getIdentifier(), $propertyType, $property, $optionValue), + sprintf('%s:element.%s.%s.%s.%s', $translationFile, $element->getIdentifier(), $propertyType, $property, $optionValue) + ]; + $translatedValue = $this->processTranslationChain($translationKeyChain, $language); + $optionLabel = (empty($translatedValue)) ? $optionLabel : $translatedValue; + } + $translatedValue = $defaultValue; + } else { + $translationKeyChain = [ + sprintf('%s:%s.element.%s.%s.%s', $translationFile, $formRuntime->getIdentifier(), $element->getIdentifier(), $propertyType, $property), + sprintf('%s:element.%s.%s.%s', $translationFile, $element->getIdentifier(), $propertyType, $property), + sprintf('%s:element.%s.%s.%s', $translationFile, $element->getType(), $propertyType, $property), + ]; + $translatedValue = $this->processTranslationChain($translationKeyChain, $language); + $translatedValue = (empty($translatedValue)) ? $defaultValue : $translatedValue; + } + + return $translatedValue; + } + + /** + * @param string $languageKey + * @internal + */ + public function setLanguage(string $languageKey) + { + $this->languageKey = $languageKey; + } + + /** + * @return string + * @internal + */ + public function getLanguage(): string + { + return $this->languageKey; + } + + /** + * @param array $translationKeyChain + * @param string $language + * @return string|null + */ + protected function processTranslationChain(array $translationKeyChain, string $language = null) + { + $translatedValue = null; + foreach ($translationKeyChain as $translationKey) { + $translatedValue = $this->translate($translationKey, null, null, $language); + if (!empty($translatedValue)) { + break; + } + } + return $translatedValue; + } + + /** + * @param string $locallangPathAndFilename + * @return void + */ + protected function initializeLocalization(string $locallangPathAndFilename) + { + if (empty($this->languageKey)) { + $this->setLanguageKeys(); + } + + if (!empty($locallangPathAndFilename)) { + /** @var $languageFactory LocalizationFactory */ + $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class); + + $this->LOCAL_LANG = $languageFactory->getParsedData($locallangPathAndFilename, $this->languageKey, 'utf-8'); + + foreach ($this->alternativeLanguageKeys as $language) { + $tempLL = $languageFactory->getParsedData($locallangPathAndFilename, $language, 'utf-8'); + if ($this->languageKey !== 'default' && isset($tempLL[$language])) { + $this->LOCAL_LANG[$language] = $tempLL[$language]; + } + } + } + $this->loadTypoScriptLabels(); + } + + /** + * Sets the currently active language/language_alt keys. + * Default values are "default" for language key and "" for language_alt key. + * + * @return void + */ + protected function setLanguageKeys() + { + $this->languageKey = 'default'; + + $this->alternativeLanguageKeys = []; + if (TYPO3_MODE === 'FE') { + if (isset($this->getTypoScriptFrontendController()->config['config']['language'])) { + $this->languageKey = $this->getTypoScriptFrontendController()->config['config']['language']; + if (isset($this->getTypoScriptFrontendController()->config['config']['language_alt'])) { + $this->alternativeLanguageKeys[] = $this->getTypoScriptFrontendController()->config['config']['language_alt']; + } else { + /** @var $locales \TYPO3\CMS\Core\Localization\Locales */ + $locales = GeneralUtility::makeInstance(Locales::class); + if (in_array($this->languageKey, $locales->getLocales(), true)) { + foreach ($locales->getLocaleDependencies($this->languageKey) as $language) { + $this->alternativeLanguageKeys[] = $language; + } + } + } + } + } elseif (!empty($GLOBALS['BE_USER']->uc['lang'])) { + $this->languageKey = $GLOBALS['BE_USER']->uc['lang']; + } elseif (!empty($this->getLanguageService()->lang)) { + $this->languageKey = $this->getLanguageService()->lang; + } + } + + /** + * Overwrites labels that are set via TypoScript. + * TS locallang labels have to be configured like: + * plugin.tx_form._LOCAL_LANG.languageKey.key = value + * + * @return void + */ + protected function loadTypoScriptLabels() + { + $frameworkConfiguration = $this->getConfigurationManager() + ->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, 'form'); + + if (!is_array($frameworkConfiguration['_LOCAL_LANG'])) { + return; + } + $this->LOCAL_LANG_UNSET = []; + foreach ($frameworkConfiguration['_LOCAL_LANG'] as $languageKey => $labels) { + if (!(is_array($labels) && isset($this->LOCAL_LANG[$languageKey]))) { + continue; + } + foreach ($labels as $labelKey => $labelValue) { + if (is_string($labelValue)) { + $this->LOCAL_LANG[$languageKey][$labelKey][0]['target'] = $labelValue; + if ($labelValue === '') { + $this->LOCAL_LANG_UNSET[$languageKey][$labelKey] = ''; + } + } elseif (is_array($labelValue)) { + $labelValue = $this->flattenTypoScriptLabelArray($labelValue, $labelKey); + foreach ($labelValue as $key => $value) { + $this->LOCAL_LANG[$languageKey][$key][0]['target'] = $value; + if ($value === '') { + $this->LOCAL_LANG_UNSET[$languageKey][$key] = ''; + } + } + } + } + } + } + + /** + * Flatten TypoScript label array; converting a hierarchical array into a flat + * array with the keys separated by dots. + * + * Example Input: array('k1' => array('subkey1' => 'val1')) + * Example Output: array('k1.subkey1' => 'val1') + * + * @param array $labelValues Hierarchical array of labels + * @param string $parentKey the name of the parent key in the recursion; is only needed for recursion. + * @return array flattened array of labels. + */ + protected function flattenTypoScriptLabelArray(array $labelValues, string $parentKey = ''): array + { + $result = []; + foreach ($labelValues as $key => $labelValue) { + if (!empty($parentKey)) { + $key = $parentKey . '.' . $key; + } + if (is_array($labelValue)) { + $labelValue = $this->flattenTypoScriptLabelArray($labelValue, $key); + $result = array_merge($result, $labelValue); + } else { + $result[$key] = $labelValue; + } + } + return $result; + } + + /** + * Returns instance of the configuration manager + * + * @return ConfigurationManagerInterface + */ + protected function getConfigurationManager(): ConfigurationManagerInterface + { + if ($this->configurationManager !== null) { + return $this->configurationManager; + } + + $this->configurationManager = GeneralUtility::makeInstance(ObjectManager::class) + ->get(ConfigurationManagerInterface::class); + return $this->configurationManager; + } + + /** + * @return LanguageService + */ + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController(): TypoScriptFrontendController + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/form/Classes/Utility/ArrayUtility.php b/typo3/sysext/form/Classes/Utility/ArrayUtility.php new file mode 100644 index 0000000000000000000000000000000000000000..8790146e8c1ad3c3f772d2cca815c06122bc25dd --- /dev/null +++ b/typo3/sysext/form/Classes/Utility/ArrayUtility.php @@ -0,0 +1,153 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Utility; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException; + +/** + * Collection of static array utility functions + * + * Scope: frontend / backend + * @internal + */ +class ArrayUtility +{ + + /** + * Validates the given $arrayToTest by checking if an element is not in $allowedArrayKeys. + * + * @param array $arrayToTest + * @param array $allowedArrayKeys + * @return void + * @throws TypeDefinitionNotValidException if an element in $arrayToTest is not in $allowedArrayKeys + * @internal + */ + public static function assertAllArrayKeysAreValid(array $arrayToTest, array $allowedArrayKeys) + { + $notAllowedArrayKeys = array_keys(array_diff_key($arrayToTest, array_flip($allowedArrayKeys))); + if (count($notAllowedArrayKeys) !== 0) { + throw new TypeDefinitionNotValidException(sprintf('The options "%s" were not allowed (allowed were: "%s")', implode(', ', $notAllowedArrayKeys), implode(', ', $allowedArrayKeys)), 1325697085); + } + } + + /** + * Sort keys from the current nesting level if all keys within the + * current nesting level are integers. + * + * @param array $array + * @return array + * @internal + */ + public static function sortNumericArrayKeysRecursive(array $array): array + { + if (count(array_filter(array_keys($array), 'is_string')) === 0) { + ksort($array); + } + foreach ($array as $key => $value) { + if (is_array($value) && !empty($value)) { + $array[$key] = self::sortNumericArrayKeysRecursive($value); + } + } + return $array; + } + + /** + * Reindex keys from the current nesting level if all keys within + * the current nesting level are integers. + * + * @param array $array + * @return array + * @internal + */ + public static function reIndexNumericArrayKeysRecursive(array $array): array + { + if (count(array_filter(array_keys($array), 'is_string')) === 0) { + $array = array_values($array); + } + foreach ($array as $key => $value) { + if (is_array($value) && !empty($value)) { + $array[$key] = self::reIndexNumericArrayKeysRecursive($value); + } + } + return $array; + } + + /** + * Recursively remove keys if their value are NULL. + * + * @param array $array + * @return array the modified array + * @internal + */ + public static function removeNullValuesRecursive(array $array): array + { + $result = $array; + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = self::removeNullValuesRecursive($value); + } elseif ($value === null) { + unset($result[$key]); + } + } + return $result; + } + + /** + * Recursively translate values. + * + * @param array $array + * @return array the modified array + * @internal + */ + public static function stripTagsFromValuesRecursive(array $array): array + { + $result = $array; + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = self::stripTagsFromValuesRecursive($value); + } else { + if (!is_bool($value)) { + $result[$key] = strip_tags($value); + } + } + } + return $result; + } + + /** + * Recursively convert 'true' and 'false' strings to boolen values. + * + * @param array $array + * @return array the modified array + * @internal + */ + public static function convertBooleanStringsToBooleanRecursive(array $array): array + { + $result = $array; + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = self::convertBooleanStringsToBooleanRecursive($value); + } else { + if ($value === 'true') { + $result[$key] = true; + } elseif ($value === 'false') { + $result[$key] = false; + } + } + } + return $result; + } +} diff --git a/typo3/sysext/form/Classes/Utility/ElementCounter.php b/typo3/sysext/form/Classes/Utility/ElementCounter.php deleted file mode 100644 index 002dabfbb1a22977c6f47e4bf46780f760c60ada..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Utility/ElementCounter.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Utility; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -class ElementCounter implements \TYPO3\CMS\Core\SingletonInterface -{ - /** - * @var int - */ - protected $elementCounter = 0; - - /** - * Raise the element counter by one - * - * @return int - */ - public function getElementId() - { - $this->elementCounter++; - return $this->elementCounter; - } -} diff --git a/typo3/sysext/form/Classes/Utility/FormUtility.php b/typo3/sysext/form/Classes/Utility/FormUtility.php deleted file mode 100644 index a0c49999706bfcfef087c9c6fa53e2b43fa58fd0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Utility/FormUtility.php +++ /dev/null @@ -1,283 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Utility; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Model\Configuration; - -/** - * A utility for the form - */ -class FormUtility -{ - /** - * @param Configuration $configuration - * @return FormBuilder - */ - public static function create(Configuration $configuration) - { - /** @var FormBuilder $formBuilder */ - $formUtility = self::getObjectManager()->get(self::class); - $formUtility->setConfiguration($configuration); - return $formUtility; - } - - /** - * @var Configuration - */ - protected $configuration; - - /** - * @param Configuration $configuration - */ - public function setConfiguration(Configuration $configuration) - { - $this->configuration = $configuration; - } - - /** - * Render TypoScript values - * There are different variants. It is possible that the TypoScript - * which we want to render looks like this: - * - * array( - * 'message' => 'TEXT', - * 'message.' => array( - * 'value' => 'blah' - * ) - * ) - * - * or in "short syntax" (the wizard writes some syntax partly) - * - * array( - * 'message.' => array( - * 'value' => 'blah' - * ) - * ) - * - * or it is simply a string. - * - * Furthermore we have 2 modes: - * - contentelement rendering is allowed - * - or contentelement rendering is not allowed - * - * This method will take care of all scenarios and provide some - * fallbacks. - * Call this method always in the following way: - * - * renderItem( - * $typoscript['itemToRender.'], - * $typoscript['itemToRender'], - * $optionalDefaultMessage - * ) - * - * You dont have to handle if is $typoscript['itemToRender.'] is - * set or not. This function determines this. - * This allows us to get the value of a TypoScript construct - * without knowing about "short syntax", only a string, a cObject, - * if cObject rendering is allowed and so on. - * - * If contentelement rendering is allowed: - * If $type and $configuration are set - * render as an cObject. - * - * If $type is set but $configuration is empty - * only return the value of $type. - * - * If $type is empty and $configuration is an array ("short syntax") - * render the $configuration as content type TEXT. - * - * If $type is empty and $configuration is a string - * render the value of $configuration like - * 10 = TEXT 10.value = $configuration. - * - * If $type is empty and $configuration is empty - * return the $defaultMessage. - * - * If contentelement rendering is not allowed: - * If $type is set but $configuration is empty - * only return the value of $type. - * - * If $type is set and $configuration['value'] isset - * return the value of $configuration['value']. - * - * If $type is set and $configuration['value'] is not set - * return the value of $defaultMessage. - * - * If $type is empty and $configuration['value'] isset - * return the value of $configuration['value']. - * - * If $type is empty and $configuration['value'] is not set - * return the value of $defaultMessage. - * - * @param mixed $configuration a string or a TypoScript array - * @param NULL|string $type cObject type or simply a string value - * @param string $defaultMessage - * @return string - */ - public function renderItem($configuration, $type = null, $defaultMessage = '') - { - if ($this->configuration->getContentElementRendering()) { - $renderedMessage = null; - if ($type !== null) { - if (is_array($configuration)) { - /* Direct cObject rendering */ - $value = $configuration; - } else { - /* got only a string, no rendering required */ - $renderedMessage = $type; - } - } else { - if ($configuration !== null) { - /* Render the "short syntax" - * The wizard write things like label.value - * The previous version of EXT:form interpreted this - * as a TEXT content object, so we do the same - * */ - $type = 'TEXT'; - if (is_array($configuration)) { - $value = $configuration; - } else { - $value['value'] = $configuration; - } - } else { - /* return the default message - * If $type === NULL and $configuration === NULL - * return the default message (if set). - * */ - $renderedMessage = $defaultMessage; - } - } - if ($renderedMessage === null) { - $renderedMessage = $GLOBALS['TSFE']->cObj->cObjGetSingle( - $type, - $value - ); - } - } else { - if ($type !== null) { - if ($configuration !== null) { - /* the wizard write things like label.value = some text - * so we need the handle that, even content object rendering - * is not allowed. - * */ - if (isset($configuration['value'])) { - $renderedMessage = $configuration['value']; - } else { - $renderedMessage = $defaultMessage; - } - } else { - // string, no rendering required - $renderedMessage = $type; - } - } else { - $renderedMessage = $defaultMessage; - if ( - is_array($configuration) - && isset($configuration['value']) - ) { - $renderedMessage = $configuration['value']; - } - } - } - return $renderedMessage; - } - - /** - * Render array values recursively as cObjects using the - * method renderItem. - * - * @param array $arrayToRender - * @return array - */ - public function renderArrayItems(array &$arrayToRender = []) - { - foreach ($arrayToRender as $attributeName => &$attributeValue) { - $attributeNameWithoutDot = rtrim($attributeName, '.'); - if ( - isset($arrayToRender[$attributeNameWithoutDot]) - && isset($arrayToRender[$attributeNameWithoutDot . '.']) - ) { - $attributeValue = $this->renderItem( - $arrayToRender[$attributeNameWithoutDot . '.'], - $arrayToRender[$attributeNameWithoutDot] - ); - unset($arrayToRender[$attributeNameWithoutDot . '.']); - } elseif ( - !isset($arrayToRender[$attributeNameWithoutDot]) - && isset($arrayToRender[$attributeNameWithoutDot . '.']) - ) { - $this->renderArrayItems($attributeValue); - } - } - } - - /** - * If the name is not defined it is automatically generated - * using the following syntax: id-{element_counter} - * The name attribute will be transformed if it contains some - * non allowed characters: - * - spaces are changed into hyphens - * - remove all characters except a-z A-Z 0-9 _ - - * - * @param string $name - * @return string - */ - public function sanitizeNameAttribute($name) - { - if (!empty($name)) { - // Change spaces into hyphens - $name = preg_replace('/\\s/', '-', $name); - // Remove non-word characters - $name = preg_replace('/[^a-zA-Z0-9_\\-]+/', '', $name); - } - return $name; - } - - /** - * If the id is not defined it is automatically generated - * using the following syntax: field-{element_counter} - * The id attribute will be transformed if it contains some - * non allowed characters: - * - spaces are changed into hyphens - * - if the id start with a integer then transform it to field-{integer} - * - remove all characters expect a-z A-Z 0-9 _ - : . - * - * @param string $id - * @return string - */ - public function sanitizeIdAttribute($id) - { - if (!empty($id)) { - // Change spaces into hyphens - $attribute = preg_replace('/\\s/', '-', $id); - // Change first non-letter to field- - if (preg_match('/^([^a-zA-Z]{1})/', $attribute)) { - $id = 'field-' . $attribute; - } - // Remove non-word characters - $id = preg_replace('/([^a-zA-Z0-9_:\\-\\.]*)/', '', $id); - } - return $id; - } - - /** - * @return \TYPO3\CMS\Extbase\Object\ObjectManager - */ - public static function getObjectManager() - { - return GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class); - } -} diff --git a/typo3/sysext/form/Classes/Utility/SessionUtility.php b/typo3/sysext/form/Classes/Utility/SessionUtility.php deleted file mode 100644 index 00f9c5ae734a373d327ae4d51b9fdf7149e00325..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Utility/SessionUtility.php +++ /dev/null @@ -1,160 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Utility; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\SingletonInterface; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; - -/** - * A session utility - */ -class SessionUtility implements SingletonInterface -{ - /** - * Session data - * - * @var array - */ - protected $sessionData = []; - - /** - * Prefix for the session - * - * @var string - */ - protected $formPrefix = ''; - - /** - * @var TypoScriptFrontendController - */ - protected $frontendController; - - /** - * Constructor - */ - public function __construct() - { - $this->frontendController = $GLOBALS['TSFE']; - } - - /** - * Store the form input in a session - * - * @param string $formPrefix - * @return void - */ - public function initSession($formPrefix = '') - { - $this->setFormPrefix($formPrefix); - if ($this->frontendController->loginUser) { - $this->sessionData = $this->frontendController->fe_user->getKey('user', $this->formPrefix); - } else { - $this->sessionData = $this->frontendController->fe_user->getKey('ses', $this->formPrefix); - } - } - - /** - * Store the form input in a session - * - * @return void - */ - public function storeSession() - { - if ($this->frontendController->loginUser) { - $this->frontendController->fe_user->setKey('user', $this->formPrefix, $this->getSessionData()); - } else { - $this->frontendController->fe_user->setKey('ses', $this->formPrefix, $this->getSessionData()); - } - $this->frontendController->storeSessionData(); - } - - /** - * Destroy the session data for the form - * - * @return void - */ - public function destroySession() - { - $this->removeFiles(); - if ($this->frontendController->loginUser) { - $this->frontendController->fe_user->setKey('user', $this->formPrefix, null); - } else { - $this->frontendController->fe_user->setKey('ses', $this->formPrefix, null); - } - $this->frontendController->storeSessionData(); - } - - /** - * Set the session Data by $key - * - * @param string $key - * @param string $value - * @return void - */ - public function setSessionData($key, $value) - { - $this->sessionData[$key] = $value; - } - - /** - * Retrieve a member of the $sessionData variable - * - * If no $key is passed, returns the entire $sessionData array - * - * @param string $key Parameter to search for - * @param mixed $default Default value to use if key not found - * @return mixed Returns NULL if key does not exist - */ - public function getSessionData($key = null, $default = null) - { - if ($key === null) { - return $this->sessionData; - } - return isset($this->sessionData[$key]) ? $this->sessionData[$key] : $default; - } - - /** - * Set the form prefix - * - * @param string $formPrefix - * @return array - */ - public function setFormPrefix($formPrefix) - { - $this->formPrefix = $formPrefix; - } - - /** - * Remove uploaded files from the typo3temp - * - * @return void - */ - protected function removeFiles() - { - $sessionData = $this->getSessionData(); - if (is_array($sessionData)) { - foreach ($sessionData as $fieldName => $values) { - if (is_array($values)) { - foreach ($values as $file) { - if (isset($file['tempFilename'])) { - GeneralUtility::unlink_tempfile($file['tempFilename']); - } - } - } - } - } - } -} diff --git a/typo3/sysext/form/Classes/Utility/TypoScriptToJsonConverter.php b/typo3/sysext/form/Classes/Utility/TypoScriptToJsonConverter.php deleted file mode 100644 index 6ef9881b0205870c0d76e11ae1f30817b12bdac0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/Utility/TypoScriptToJsonConverter.php +++ /dev/null @@ -1,212 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Utility; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Utility\ArrayUtility; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Form\Domain\Model\Json\AbstractJsonElement; - -/** - * Typoscript to JSON converter - * - * Takes the incoming TypoScript and converts it to JSON. - */ -class TypoScriptToJsonConverter -{ - protected $registeredElementNames = [ - 'BUTTON', - 'CHECKBOX', - 'CHECKBOXGROUP', - 'FIELDSET', - 'FILEUPLOAD', - 'HEADER', - 'HIDDEN', - 'OPTGROUP', - 'OPTION', - 'PASSWORD', - 'RADIO', - 'RADIOGROUP', - 'RESET', - 'SELECT', - 'SUBMIT', - 'TEXTAREA', - 'TEXTBLOCK', - 'TEXTLINE' - ]; - - /** - * @var array - */ - protected $nameMapping = [ - 'checkboxgroup' => 'CheckboxGroup', - 'radiogroup' => 'RadioGroup', - ]; - - /** - * @var array - */ - protected $validationRules; - - /** - * Convert TypoScript string to JSON - * - * @param array $typoscript TypoScript string containing all configuration for the form - * @return TYPO3\CMS\Form\Domain\Model\Json\FormJsonElement|false The JSON for the form - */ - public function convert(array $typoscript) - { - $this->setValidationRules($typoscript); - $jsonObject = $this->createElement('form', $typoscript); - return $jsonObject; - } - - /** - * Create element by loading class - * and instantiating the object - * - * @param string $class Type of element - * @param array $arguments Configuration array - * @return AbstractJsonElement - * @throws \RuntimeException - */ - public function createElement($class, array $arguments = []) - { - $class = strtolower((string)$class); - if (!empty($this->nameMapping[$class])) { - $class = $this->nameMapping[$class]; - } - $className = 'TYPO3\\CMS\\Form\\Domain\\Model\Json\\' . ucfirst($class) . 'JsonElement'; - $this->addValidationRules($arguments); - - if (!class_exists($className)) { - throw new \RuntimeException('Class "' . $className . '" does not exist', 1440779351); - } - - /** @var $object AbstractJsonElement */ - $object = GeneralUtility::makeInstance($className); - $object->setParameters($arguments); - if ($object->childElementsAllowed()) { - $this->getChildElementsByIntegerKey($object, $arguments); - } - return $object; - } - - /** - * Rendering of a "numerical array" of Form objects from TypoScript - * Creates new object for each element found - * - * @param AbstractJsonElement $parentElement Parent model object - * @param array $typoscript Configuration array - * @return void - */ - protected function getChildElementsByIntegerKey(AbstractJsonElement $parentElement, array $typoscript) - { - if (is_array($typoscript)) { - $keys = ArrayUtility::filterAndSortByNumericKeys($typoscript); - foreach ($keys as $key) { - $class = $typoscript[$key]; - if ((int)$key && strpos($key, '.') === false) { - if (isset($typoscript[$key . '.'])) { - $elementArguments = $typoscript[$key . '.']; - } else { - $elementArguments = []; - } - $this->setElementType($parentElement, $class, $elementArguments); - } - } - } - } - - /** - * Set the element type of the object - * - * Checks if the typoscript object is part of the FORM or has a predefined - * class for name or header object - * - * @param AbstractJsonElement $parentElement The parent object - * @param string $class A predefined class - * @param array $arguments Configuration array - * @return void - */ - private function setElementType(AbstractJsonElement $parentElement, $class, array $arguments) - { - if (in_array($class, $this->registeredElementNames)) { - if (strstr($arguments['class'], 'predefined-name')) { - $class = 'NAME'; - } - $this->addElement($parentElement, $class, $arguments); - } - } - - /** - * Add child object to this element - * - * @param AbstractJsonElement $parentElement The parent object - * @param string $class Type of element - * @param array $arguments Configuration array - * @return void - */ - public function addElement(AbstractJsonElement $parentElement, $class, array $arguments) - { - try { - $element = $this->createElement($class, $arguments); - $parentElement->addElement($element); - } catch (\RuntimeException $exception) { - // Catch missing classes or element types - // There are elements that can be used the - // TypoScript-like declaration, which don't - // have a counterpart in the ExtJS wizard. - } - } - - /** - * Set the validation rules - * - * @param array $typoscript Configuration array - * @return void - */ - protected function setValidationRules(array $typoscript) - { - if (isset($typoscript['rules.']) && is_array($typoscript['rules.'])) { - $this->validationRules = $typoscript['rules.']; - } - } - - /** - * Add validation rules to an element if available - * - * In TypoScript the validation rules belong to the form and are connected - * to the elements by name. However, in the wizard, they are added to the - * element for usability - * - * @param array $arguments The element arguments - * @return void - */ - protected function addValidationRules(array &$arguments) - { - if (!empty($this->validationRules) && isset($arguments['name'])) { - foreach ($this->validationRules as $key => $ruleName) { - if ((int)$key && strpos($key, '.') === false) { - if (isset($this->validationRules[$key . '.'])) { - $ruleConfiguration = $this->validationRules[$key . '.']; - if (isset($ruleConfiguration['element']) && $ruleConfiguration['element'] === $arguments['name']) { - $arguments['validation'][$ruleName] = $ruleConfiguration; - } - } - } - } - } - } -} diff --git a/typo3/sysext/form/Classes/View/Wizard/Element/FormWizardElement.php b/typo3/sysext/form/Classes/View/Wizard/Element/FormWizardElement.php deleted file mode 100644 index c219d9b7173fc4c1906d17b7f40ad2ffe8050528..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/View/Wizard/Element/FormWizardElement.php +++ /dev/null @@ -1,230 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\View\Wizard\Element; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Backend\Form\Element\AbstractFormElement; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Utility\StringUtility; -use TYPO3\CMS\Extbase\Service\TypoScriptService; -use TYPO3\CMS\Form\Domain\Repository\ContentRepository; -use TYPO3\CMS\Form\Utility\TypoScriptToJsonConverter; - -/** - * form Wizard widget - */ -class FormWizardElement extends AbstractFormElement -{ - /** - * @var array - */ - protected $resultArray; - - /** - * Store initialized resultArray - */ - protected function initializeResultArray() - { - $this->resultArray = parent::initializeResultArray(); - } - - /** - * @return int - */ - protected function getCurrentPageId() - { - // $this->data used to be globalOptions - return (int)$this->data['inlineFirstPid']; - } - - /** - * @return int - */ - protected function getCurrentUid() - { - return (int)$this->data['databaseRow']['uid']; - } - - /** - * @return array - */ - protected function getPlainPageWizardModTsConfigSettingsProperties() - { - $settings = $this->data['pageTsConfig']['mod.']['wizards.']['form.']; - return $this->getTypoScriptService()->convertTypoScriptArrayToPlainArray($settings); - } - - /** - * Gets the repository object. - * - * @return ContentRepository - */ - protected function getRepository() - { - return GeneralUtility::makeInstance(ContentRepository::class); - } - - /** - * Read and convert the content record to JSON - * - * @see \TYPO3\CMS\Form\Domain\Repository\ContentRepository::getRecordAsJson - * @return TYPO3\CMS\Form\Domain\Model\Json\FormJsonElement|false The JSON object if record exists, FALSE if not - */ - protected function getRecordAsJson() - { - $json = false; - $record = $this->getRepository()->getRecord($this->getCurrentUid(), 'tt_content'); - if ($record) { - $typoscript = $record->getTyposcript(); - /** @var $converter TypoScriptToJsonConverter */ - $converter = GeneralUtility::makeInstance(TypoScriptToJsonConverter::class); - $json = $converter->convert($typoscript); - } - return $json; - } - - /** - * @return string - */ - protected function getAjaxUrl() - { - /** - * @see TYPO3.CMS/src/typo3/sysext/backend/Classes/Form/Element/AbstractFormElement.php:267 for wizard type=popup - */ - $parameterArray = $this->data['parameterArray']; - $table = $this->data['tableName']; - $fieldName = $this->data['fieldName']; - $row = $this->data['databaseRow']; - $itemName = $parameterArray['itemFormElName']; - // Resolving script filename and setting URL. - - $params = []; - $params['fieldConfig'] = $parameterArray['fieldConf']; - $params['table'] = $table; - $params['uid'] = $row['uid']; - $params['pid'] = $row['pid']; - $params['field'] = $fieldName; - - $params['formName'] = 'editform'; - $params['itemName'] = $itemName; - $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js'); - - return GeneralUtility::implodeArrayForUrl('', ['P' => $params]); - } - - /** - * locallang files for return array - * - * @return array strings - */ - protected function getLocalization() - { - $wizardLabels = 'EXT:form/Resources/Private/Language/locallang_wizard.xlf'; - $controllerLabels = 'EXT:form/Resources/Private/Language/locallang.xlf'; - return [$controllerLabels, $wizardLabels]; - } - - /** - * @param array $settings - * @return string - */ - protected function resultAddWizardSettingsJson(array $settings) - { - $recordJson = $this->getRecordAsJson(); - $settings['Configuration'] = $recordJson; - $settings['ajaxUrl'] = $this->getAjaxUrl(); - $settingsCommand = 'TYPO3.Form.Wizard.Settings = ' . json_encode($settings) . ';'; - // enhance global variable for requireJs shim "exports: 'TYPO3.Form.Wizard.Settings'" to work - $this->resultArray['additionalJavaScriptPost'][] = ';TYPO3.Form = TYPO3.Form || {Wizard:{}};'; - $this->resultArray['additionalJavaScriptPost'][] = - ';define("TYPO3/CMS/Form/Wizard/Settings", function() {' - . "\n" . ' TYPO3.Form.Wizard.Settings = ' . json_encode($settings) . ';' - . "\n" . ' return TYPO3.Form.Wizard.Settings;' - . "\n" . '});'; - return $settingsCommand; - } - - /** - * Load the wizards css - */ - protected function resultAddWizardCss() - { - $this->resultArray['stylesheetFiles'][] = 'EXT:form/Resources/Public/Css/form.css'; - } - - /** - * @return array - */ - public function render() - { - $this->initializeResultArray(); - - /** @var \TYPO3\CMS\Core\Authentication\BackendUserAuthentication $beUser */ - $beUser = $GLOBALS['BE_USER']; - /** @var string $showWizardByDefault */ - $showWizardByDefault = $beUser->getTSConfigVal('setup.default.tx_form.showWizardByDefault'); - if ((int)$showWizardByDefault == 0) { - $content = ''; - $record = $this->getRepository()->getRecord($this->getCurrentUid(), 'tt_content'); - if ($record) { - $content = $record->getBodytext(); - } - - $id = StringUtility::getUniqueId('formengine-textarea-'); - $this->resultArray['html'] = '<textarea id="formengine-textarea-' . $id . '"' - . ' class="form-control t3js-formengine-textarea formengine-textarea" wrap="off"' - . ' onchange="TBE_EDITOR.fieldChanged(\'tt_content\',\'' . $this->getCurrentUid() . '\',\'bodytext\',\'data[tt_content][' . $this->getCurrentUid() . '][bodytext]\');"' - . ' rows="15" style="" name="data[tt_content][' . $this->getCurrentUid() . '][bodytext]">' . $content . '</textarea>'; - return $this->resultArray; - } - - $this->resultAddWizardCss(); - $this->resultArray['additionalInlineLanguageLabelFiles'] += $this->getLocalization(); - $settings = $this->getPlainPageWizardModTsConfigSettingsProperties(); - $settingsCommand = $this->resultAddWizardSettingsJson($settings); - $this->resultArray['requireJsModules'][] = [ - 'TYPO3/CMS/Form/Wizard' => "function(){\n" - //. "\t" . 'console.log(this, arguments);' . "\n" - . "\t" . $settingsCommand . "\n" - . '}' - ]; - $attributes = []; - $attributes['id'] = StringUtility::getUniqueId('formengine-form-wizard-'); - /** - * @see TYPO3.CMS/src/typo3/sysext/backend/Classes/Form/Element/AbstractFormElement.php:267 for wizard type=popup - */ - $parameterArray = $this->data['parameterArray']; - $attributes['name'] = $parameterArray['itemFormElName']; - - $attributeString = ''; - foreach ($attributes as $attributeName => $attributeValue) { - $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"'; - } - - $input = '<input ' . $attributeString . ' type="hidden" />' . "\n"; - $content = $input . '<div id="form-wizard-element"></div>'; - $this->resultArray['html'] = '<div id="form-wizard-element-container" rel="' . $attributes['id'] . '">' - . "\n" . $content - . "\n" . '</div>'; - return $this->resultArray; - } - - /** - * @return TypoScriptService - */ - protected function getTypoScriptService() - { - return GeneralUtility::makeInstance(TypoScriptService::class); - } -} diff --git a/typo3/sysext/form/Classes/ViewHelpers/AggregateSelectOptionsViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/AggregateSelectOptionsViewHelper.php deleted file mode 100644 index 92b78094d7f9d51d90cc2080b5a1244f5b906a8b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/ViewHelpers/AggregateSelectOptionsViewHelper.php +++ /dev/null @@ -1,116 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\ViewHelpers; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3\CMS\Form\Domain\Model\Element; - -/** - * Aggregator for the select options - */ -class AggregateSelectOptionsViewHelper extends AbstractViewHelper -{ - /** - * @var array - */ - protected $options = []; - - /** - * @var array - */ - protected $selectedValues = []; - - /** - * Initializes the arguments - */ - public function initializeArguments() - { - parent::initializeArguments(); - $this->registerArgument('model', Element::class, '', true); - $this->registerArgument('returnSelectedValues', 'bool', '', false, false); - } - - /** - * @return array - */ - public function render() - { - /** @var Element $model */ - $model = $this->arguments['model']; - /** @var Element $element */ - foreach ($model->getChildElements() as $element) { - $this->createElement($element); - } - - return $this->arguments['returnSelectedValues'] ? $this->selectedValues : $this->options; - } - - /** - * @param Element $model - * @param array $optGroupData - * @return void - */ - protected function createElement(Element $model, array $optGroupData = []) - { - $this->checkElementForOptgroup($model, $optGroupData); - } - - /** - * @param Element $model - * @param array $optGroupData - * @return void - */ - protected function checkElementForOptgroup(Element $model, array $optGroupData = []) - { - if ($model->getElementType() === 'OPTGROUP') { - $optGroupData = [ - 'label' => $model->getAdditionalArgument('label'), - 'disabled' => $model->getAdditionalArgument('disabled'), - ]; - $this->getChildElements($model, $optGroupData); - } else { - $optionData = [ - 'value' => $model->getAdditionalArgument('value') ?: $model->getElementCounter(), - 'label' => $model->getAdditionalArgument('text'), - 'selected' => $model->getAdditionalArgument('selected'), - ]; - - if (!empty($optionData['selected'])) { - $this->selectedValues[] = $optionData['value']; - } - - if (count($optGroupData)) { - $optGroupLabel = $optGroupData['label']; - $this->options[$optGroupLabel]['disabled'] = $optGroupData['disabled']; - $this->options[$optGroupLabel]['options'][] = $optionData; - } else { - $this->options[] = $optionData; - } - } - } - - /** - * @param Element $model - * @param array $optGroupData - * @return void - */ - protected function getChildElements(Element $model, array $optGroupData = []) - { - /** @var Element $element */ - foreach ($model->getChildElements() as $element) { - $this->createElement($element, $optGroupData); - } - } -} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Be/PageRendererViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Be/PageRendererViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..0c32752b168ed7f4db40829a06ad5d643957f53b --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Be/PageRendererViewHelper.php @@ -0,0 +1,56 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Be; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Fluid\ViewHelpers\Be\PageRendererViewHelper as FluidPageRendererViewHelper; + +/** + * Extends the FluidPageRendererViewHelper + * Add the additional argument 'addInlineSettings' to add settings to + * the TYPO3 javascript inline setting + * + * Scope: backend + * @internal + */ +class PageRendererViewHelper extends FluidPageRendererViewHelper +{ + + /** + * Initialize arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('addInlineSettings', 'array', 'Adds Javascript Inline Setting'); + } + + /** + * @return void + * @internal + */ + public function render() + { + $addInlineSettings = $this->arguments['addInlineSettings']; + if (is_array($addInlineSettings) && count($addInlineSettings) > 0) { + $this->pageRenderer->addInlineSettingArray(null, $addInlineSettings); + } + + parent::render(); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Be/RenderContentElementPreviewViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Be/RenderContentElementPreviewViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..a03f342b8679215eddf2df0de7a817fb8509d95a --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Be/RenderContentElementPreviewViewHelper.php @@ -0,0 +1,73 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Be; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\PageLayoutView; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Used by the form editor. + * Render a content element preview like the page module + * + * Scope: backend + * @internal + */ +class RenderContentElementPreviewViewHelper extends AbstractViewHelper +{ + use CompileWithRenderStatic; + + /** + * As this ViewHelper renders HTML, the output must not be escaped. + * + * @var bool + */ + protected $escapeOutput = false; + + /** + * Initialize arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('contentElementUid', 'int', 'The uid of a content element'); + } + + /** + * @param array $arguments + * @param callable|\Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + * @internal + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + $content = ''; + $contentElementUid = $arguments['contentElementUid']; + $contentRecord = BackendUtility::getRecord('tt_content', $contentElementUid); + if (!empty($contentRecord)) { + $pageLayoutView = GeneralUtility::makeInstance(PageLayoutView::class); + $content = $pageLayoutView->tt_content_drawItem($contentRecord); + } + return $content; + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Form/CheckboxViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Form/CheckboxViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..400fcbacc5c9234fecd348a95ad857a4ac8ce888 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Form/CheckboxViewHelper.php @@ -0,0 +1,41 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Fluid\ViewHelpers\Form\CheckboxViewHelper as FluidCheckboxViewHelper; + +/** + * Fix a bug within the fluid checkbox viewhelper. + * It is not possible to pass a bool value for the 'multiple' option + * + * Scope: frontend + * @api + */ +class CheckboxViewHelper extends FluidCheckboxViewHelper +{ + + /** + * Renders the checkbox. + * + * @return string + * @api + */ + public function render() + { + $this->arguments['multiple'] = (bool)$this->arguments['multiple']; + return parent::render(); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Form/DatePickerViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Form/DatePickerViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..b586e4b26d83e775325a11d918c6496b0de3b903 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Form/DatePickerViewHelper.php @@ -0,0 +1,161 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Property\PropertyMapper; +use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper; + +/** + * Display a jQuery date picker. + * + * Note: Requires jQuery UI to be included on the page. + * + * Scope: frontend + * @api + */ +class DatePickerViewHelper extends AbstractFormFieldViewHelper +{ + + /** + * @var string + */ + protected $tagName = 'input'; + + /** + * @var \TYPO3\CMS\Extbase\Property\PropertyMapper + */ + protected $propertyMapper; + + /** + * @param \TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper + * @return void + * @internal + */ + public function injectPropertyMapper(\TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper) + { + $this->propertyMapper = $propertyMapper; + } + + /** + * Initialize the arguments. + * + * @return void + * @api + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerTagAttribute('size', 'int', 'The size of the input field'); + $this->registerTagAttribute('placeholder', 'string', 'Specifies a short hint that describes the expected value of an input element'); + $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', false, 'f3-form-error'); + $this->registerArgument('initialDate', 'string', 'Initial date (@see http://www.php.net/manual/en/datetime.formats.php for supported formats)'); + $this->registerArgument('enableDatePicker', 'bool', 'Enable the Datepicker', false, true); + $this->registerArgument('dateFormat', 'string', 'The date format', false, 'Y-m-d'); + $this->registerUniversalTagAttributes(); + } + + /** + * Renders the text field, hidden field and required javascript + * + * @return string + * @api + */ + public function render() + { + $enableDatePicker = $this->arguments['enableDatePicker']; + $dateFormat = $this->arguments['dateFormat']; + + $name = $this->getName(); + $this->registerFieldNameForFormTokenGeneration($name); + + $this->tag->addAttribute('type', 'date'); + $this->tag->addAttribute('name', $name . '[date]'); + if ($enableDatePicker) { + $this->tag->addAttribute('readonly', true); + } + $date = $this->getSelectedDate(); + if ($date !== null) { + $this->tag->addAttribute('value', $date->format($dateFormat)); + } + + if ($this->hasArgument('id')) { + $id = $this->arguments['id']; + } else { + $id = 'field' . md5(uniqid()); + $this->tag->addAttribute('id', $id); + } + $this->setErrorClassAttribute(); + $content = ''; + $content .= $this->tag->render(); + $content .= '<input type="hidden" name="' . $name . '[dateFormat]" value="' . htmlspecialchars($dateFormat) . '" />'; + + if ($enableDatePicker) { + $datePickerDateFormat = $this->convertDateFormatToDatePickerFormat($dateFormat); + $this->templateVariableContainer->add('datePickerDateFormat', $datePickerDateFormat); + $content .= $this->renderChildren(); + $this->templateVariableContainer->remove('datePickerDateFormat'); + } + return $content; + } + + /** + * @return null|\DateTime + */ + protected function getSelectedDate() + { + $fluidFormRenderer = $this->viewHelperVariableContainer->getView(); + $formRuntime = $fluidFormRenderer->getFormRuntime(); + $formState = $formRuntime->getFormState(); + + $date = $formRuntime[$this->arguments['property']]; + if ($date instanceof \DateTime) { + return $date; + } + if ($date !== null) { + $date = $this->propertyMapper->convert($date, 'DateTime'); + if (!$date instanceof \DateTime) { + return null; + } + return $date; + } + if ($this->hasArgument('initialDate')) { + return new \DateTime($this->arguments['initialDate']); + } + } + + /** + * @param string $dateFormat + * @return string + */ + protected function convertDateFormatToDatePickerFormat(string $dateFormat): string + { + $replacements = [ + 'd' => 'dd', + 'D' => 'D', + 'j' => 'o', + 'l' => 'DD', + + 'F' => 'MM', + 'm' => 'mm', + 'M' => 'M', + 'n' => 'm', + + 'Y' => 'yy', + 'y' => 'y' + ]; + return strtr($dateFormat, $replacements); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Form/TimePickerViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Form/TimePickerViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..9b3d0fc21cda46c47d2ce8b759691435a72bc134 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Form/TimePickerViewHelper.php @@ -0,0 +1,152 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Property\PropertyMapper; +use TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper; + +/** + * Displays two select-boxes for hour and minute selection. + * + * Scope: frontend + * @api + */ +class TimePickerViewHelper extends AbstractFormFieldViewHelper +{ + + /** + * @var string + */ + protected $tagName = 'select'; + + /** + * @var \TYPO3\CMS\Extbase\Property\PropertyMapper + */ + protected $propertyMapper; + + /** + * @param \TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper + * @return void + * @internal + */ + public function injectPropertyMapper(\TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper) + { + $this->propertyMapper = $propertyMapper; + } + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerTagAttribute('size', 'int', 'The size of the select field'); + $this->registerTagAttribute('placeholder', 'string', 'Specifies a short hint that describes the expected value of an input element'); + $this->registerTagAttribute('disabled', 'string', 'Specifies that the select element should be disabled when the page loads'); + $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this view helper', false, 'f3-form-error'); + $this->registerArgument('initialDate', 'string', 'Initial time (@see http://www.php.net/manual/en/datetime.formats.php for supported formats)'); + $this->registerUniversalTagAttributes(); + } + + /** + * Renders the select fields for hour & minute + * + * @return string + * @api + */ + public function render() + { + $name = $this->getName(); + $this->registerFieldNameForFormTokenGeneration($name); + + $this->tag->addAttribute('name', $name . '[hour]'); + $date = $this->getSelectedDate(); + $this->setErrorClassAttribute(); + + $content = ''; + $content .= $this->buildHourSelector($date); + $content .= $this->buildMinuteSelector($date); + return $content; + } + + /** + * @return \DateTime + */ + protected function getSelectedDate(): \DateTime + { + $fluidFormRenderer = $this->viewHelperVariableContainer->getView(); + $formRuntime = $fluidFormRenderer->getFormRuntime(); + + $date = $formRuntime[$this->arguments['property']]; + if ($date instanceof \DateTime) { + return $date; + } + if ($date !== null) { + $date = $this->propertyMapper->convert($date, 'DateTime'); + if (!$date instanceof \DateTime) { + return null; + } + return $date; + } + if ($this->hasArgument('initialDate')) { + return new \DateTime($this->arguments['initialDate']); + } + } + + /** + * @param \DateTime $date + * @return string + */ + protected function buildHourSelector(\DateTime $date = null): string + { + $value = $date !== null ? $date->format('H') : null; + $hourSelector = clone $this->tag; + $hourSelector->addAttribute('name', sprintf('%s[hour]', $this->getName())); + $options = ''; + foreach (range(0, 23) as $hour) { + $hour = str_pad($hour, 2, '0', STR_PAD_LEFT); + $selected = $hour === $value ? ' selected="selected"' : ''; + $options .= '<option value="' . $hour . '"' . $selected . '>' . $hour . '</option>'; + } + $hourSelector->setContent($options); + return $hourSelector->render(); + } + + /** + * @param \DateTime $date + * @return string + */ + protected function buildMinuteSelector(\DateTime $date = null): string + { + $value = $date !== null ? $date->format('i') : null; + $minuteSelector = clone $this->tag; + if ($this->hasArgument('id')) { + $minuteSelector->addAttribute('id', $this->arguments['id'] . '-minute'); + } + $minuteSelector->addAttribute('name', sprintf('%s[minute]', $this->getName())); + $options = ''; + foreach (range(0, 59) as $minute) { + $minute = str_pad($minute, 2, '0', STR_PAD_LEFT); + $selected = $minute === $value ? ' selected="selected"' : ''; + $options .= '<option value="' . $minute . '"' . $selected . '>' . $minute . '</option>'; + } + $minuteSelector->setContent($options); + return $minuteSelector->render(); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..988c3114d13173b6158cb7a1f6ce2b6dc3413d51 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php @@ -0,0 +1,133 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Extbase\Property\PropertyMapper; +use TYPO3\CMS\Extbase\Security\Cryptography\HashService; +use TYPO3\CMS\Fluid\ViewHelpers\Form\UploadViewHelper; + +/** + * This ViewHelper makes the specified Image object available for its + * childNodes. + * In case the form is redisplayed because of validation errors, a previously + * uploaded image will be correctly used. + * + * Scope: frontend + * @api + */ +class UploadedResourceViewHelper extends UploadViewHelper +{ + + /** + * @var HashService + */ + protected $hashService; + + /** + * @var \TYPO3\CMS\Extbase\Property\PropertyMapper + */ + protected $propertyMapper; + + /** + * @param HashService $hashService + * @return void + * @internal + */ + public function injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService) + { + $this->hashService = $hashService; + } + + /** + * @param \TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper + * @return void + * @internal + */ + public function injectPropertyMapper(\TYPO3\CMS\Extbase\Property\PropertyMapper $propertyMapper) + { + $this->propertyMapper = $propertyMapper; + } + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('as', 'string', ''); + $this->registerArgument('accept', 'array', 'Values for the accept attribute', false, []); + } + + /** + * @return string + * @api + */ + public function render() + { + $output = ''; + + $as = $this->arguments['as']; + $accept = $this->arguments['accept']; + $resource = $this->getUploadedResource(); + + if (!empty($accept)) { + $this->tag->addAttribute('accept', implode(',', $accept)); + } + + if ($resource !== null) { + $resourcePointerIdAttribute = ''; + if ($this->hasArgument('id')) { + $resourcePointerIdAttribute = ' id="' . htmlspecialchars($this->arguments['id']) . '-file-reference"'; + } + $resourcePointerValue = $resource->getUid(); + if ($resourcePointerValue === null) { + // Newly created file reference which is not persisted yet. + // Use the file UID instead, but prefix it with "file:" to communicate this to the type converter + $resourcePointerValue = 'file:' . $resource->getOriginalResource()->getOriginalFile()->getUid(); + } + $output .= '<input type="hidden" name="' . $this->getName() . '[submittedFile][resourcePointer]" value="' . htmlspecialchars($this->hashService->appendHmac((string)$resourcePointerValue)) . '"' . $resourcePointerIdAttribute . ' />'; + + $this->templateVariableContainer->add($as, $resource); + $output .= $this->renderChildren(); + $this->templateVariableContainer->remove($as); + } + + $output .= parent::render(); + return $output; + } + + /** + * Return a previously uploaded resource. + * Return NULL if errors occurred during property mapping for this property. + * + * @return null|FileReference + */ + protected function getUploadedResource() + { + if ($this->getMappingResultsForProperty()->hasErrors()) { + return null; + } + $resource = $this->getValueAttribute(); + if ($resource instanceof FileReference) { + return $resource; + } + return $this->propertyMapper->convert($resource, FileReference::class); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/FormViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/FormViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..d6e2e18709be8dc41a47b66c1bf4425c34290f36 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/FormViewHelper.php @@ -0,0 +1,62 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Extbase\Mvc\Web\Request; +use TYPO3\CMS\Extbase\Security\Cryptography\HashService; +use TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper as FluidFormViewHelper; +use TYPO3Fluid\Fluid\Core\ViewHelper\TagBuilder; + +/** + * Custom form ViewHelper that renders the form state instead of referrer fields + * + * Scope: frontend + * @api + */ +class FormViewHelper extends FluidFormViewHelper +{ + + /** + * Renders hidden form fields for referrer information about + * the current request. + * + * @return string Hidden fields with referrer information + */ + protected function renderHiddenReferrerFields() + { + $tagBuilder = $this->objectManager->get(TagBuilder::class, 'input'); + $tagBuilder->addAttribute('type', 'hidden'); + $stateName = $this->prefixFieldName($this->arguments['object']->getFormDefinition()->getIdentifier()) . '[__state]'; + $tagBuilder->addAttribute('name', $stateName); + + $serializedFormState = base64_encode(serialize($this->arguments['object']->getFormState())); + $tagBuilder->addAttribute('value', $this->hashService->appendHmac($serializedFormState)); + return $tagBuilder->render(); + } + + /** + * We do NOT return NULL as in this case, the Form ViewHelpers do not enter $objectAccessorMode. + * However, we return the form identifier. + * + * @return string + */ + protected function getFormObjectName() + { + $fluidFormRenderer = $this->viewHelperVariableContainer->getView(); + $formRuntime = $fluidFormRenderer->getFormRuntime(); + return $formRuntime->getFormDefinition()->getIdentifier(); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/PlainMailViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/PlainMailViewHelper.php deleted file mode 100644 index 50263817e0fbdaabdf2efd1023cca1dabbed17c0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/ViewHelpers/PlainMailViewHelper.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\ViewHelpers; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; -use TYPO3\CMS\Form\Domain\Model\Element; - -/** - * A viewhelper for the plain mail view - */ -class PlainMailViewHelper extends AbstractViewHelper -{ - /** - * Initializes the arguments - */ - public function initializeArguments() - { - parent::initializeArguments(); - $this->registerArgument('labelContent', 'mixed', ''); - $this->registerArgument('content', 'mixed', ''); - $this->registerArgument('newLineAfterLabel', 'bool', '', false, false); - $this->registerArgument('indent', 'int', '', false, 0); - } - - /** - * Render the plain mail view - * - * @return string - */ - public function render() - { - $templateVariableContainer = $this->renderingContext->getViewHelperVariableContainer(); - if (!$templateVariableContainer->exists(__CLASS__, 'spaces')) { - $templateVariableContainer->add(__CLASS__, 'spaces', 0); - } - - $spaces = $templateVariableContainer->get(__CLASS__, 'spaces'); - $output = ''; - if ($this->arguments['labelContent']) { - if ($this->arguments['labelContent'] instanceof Element) { - $output = $this->getLabel($this->arguments['labelContent']); - } else { - $output = $this->arguments['labelContent']; - } - if ($this->arguments['newLineAfterLabel']) { - if ($output !== '') { - $output = str_repeat(chr(32), $spaces) . $output . LF; - } - $this->setIndent($this->arguments['indent']); - } - } - - if ($this->arguments['content']) { - if (!$this->arguments['newLineAfterLabel']) { - $this->setIndent($this->arguments['indent']); - } - if ($this->arguments['labelContent'] && !$this->arguments['newLineAfterLabel']) { - $output = $output . ': ' . $this->getValue($this->arguments['content']); - } elseif ($this->arguments['labelContent'] && $this->arguments['newLineAfterLabel']) { - $output = $output - . str_repeat(chr(32), ($spaces + 4)) - . str_replace(LF, LF . str_repeat(chr(32), ($spaces + 4)), $this->getValue($this->arguments['content'])); - } else { - $output = $this->getValue($this->arguments['content']); - } - } - - if ($this->arguments['labelContent'] || $this->arguments['content']) { - if ($output !== '' && !$this->arguments['newLineAfterLabel']) { - $output = str_repeat(chr(32), $spaces) . $output; - } - } else { - $this->setIndent($this->arguments['indent']); - } - - return $output; - } - - /** - * Get the label - * @param Element $model - * @return string - */ - protected function getLabel(Element $model) - { - $label = ''; - if ($model->getAdditionalArgument('legend')) { - $label = $model->getAdditionalArgument('legend'); - } elseif ($model->getAdditionalArgument('label')) { - $label = $model->getAdditionalArgument('label'); - } - return $label; - } - - /** - * Get the label - * - * @param string $content - * @return string - */ - protected function getValue($content) - { - return $content instanceof Element ? $content->getAdditionalArgument('value') : $content; - } - - /** - * Set the current indent level - * - * @param int $indent - * @return void - */ - public function setIndent($indent = 0) - { - $templateVariableContainer = $this->renderingContext->getViewHelperVariableContainer(); - $spaces = $templateVariableContainer->get(__CLASS__, 'spaces'); - $spaces += (int)$indent; - $templateVariableContainer->addOrUpdate(__CLASS__, 'indent', $indent); - $templateVariableContainer->addOrUpdate(__CLASS__, 'spaces', $spaces); - } -} diff --git a/typo3/sysext/form/Classes/ViewHelpers/PlainTextMailViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/PlainTextMailViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..0b8e0f4efd1764fabc449d82269a3ef1d0c9f26d --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/PlainTextMailViewHelper.php @@ -0,0 +1,79 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * A viewhelper for the plain mail view + * + * Scope: frontend + * @api + */ +class PlainTextMailViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper +{ + use CompileWithRenderStatic; + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('formValue', 'array', 'The values from a form element', true); + $this->registerArgument('formRuntime', FormRuntime::class, 'A FormRuntime instance', true); + } + + /** + * @param array $arguments + * @param callable|\Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + * @api + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + $formValue = $arguments['formValue']; + $formRuntime = $arguments['formRuntime']; + + $label = $formValue['element']->getLabel(); + $label = TranslateElementPropertyViewHelper::renderStatic( + ['element' => $formValue['element'], 'property' => 'label', 'formRuntime' => $formRuntime], + $renderChildrenClosure, + $renderingContext + ); + $processedValue = (!empty($formValue['processedValue'])) ? $formValue['processedValue'] : '-'; + $isMultiValue = $formValue['isMultiValue']; + + $label .= ': '; + if ($isMultiValue) { + $output = $label . array_shift($processedValue) . LF; + $indent = str_repeat(chr(32), (strlen($label))); + foreach ($processedValue as $multiValue) { + $output .= $indent . $multiValue; + } + } else { + $output = $label . $processedValue; + } + + return $output . LF . LF; + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..31fe05006ea75c002f9f90f274367b18b81fc2ac --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php @@ -0,0 +1,190 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Extbase\Domain\Model\FileReference; +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface; +use TYPO3\CMS\Form\Domain\Model\Renderable\CompositeRenderableInterface; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Renderer\RendererInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; + +/** + * Renders the values of a form + * + * Scope: frontend + * @api + */ +class RenderAllFormValuesViewHelper extends AbstractViewHelper +{ + + /** + * @var bool + */ + protected $escapeOutput = false; + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('renderable', RootRenderableInterface::class, 'A RootRenderableInterface instance', true); + $this->registerArgument('as', 'string', 'The name within the template', false, 'formValue'); + $this->registerArgument('formRuntime', FormRuntime::class, 'A FormRuntime instance', false, null); + } + + /** + * @return string the rendered form values + * @api + */ + public function render() + { + $renderable = $this->arguments['renderable']; + $as = $this->arguments['as']; + $formRuntime = $this->arguments['formRuntime']; + + if ($renderable instanceof CompositeRenderableInterface) { + $elements = $renderable->getRenderablesRecursively(); + } else { + $elements = [$renderable]; + } + + if ($formRuntime === null) { + /** @var RendererInterface $fluidFormRenderer */ + $fluidFormRenderer = $this->viewHelperVariableContainer->getView(); + $formRuntime = $fluidFormRenderer->getFormRuntime(); + } + + $output = ''; + foreach ($elements as $element) { + if (!$element instanceof FormElementInterface || $element->getType() === 'Honeypot') { + continue; + } + $value = $formRuntime[$element->getIdentifier()]; + + $formValue = [ + 'element' => $element, + 'value' => $value, + 'processedValue' => $this->processElementValue($element, $value, $formRuntime), + 'isMultiValue' => is_array($value) || $value instanceof \Iterator + ]; + $this->templateVariableContainer->add($as, $formValue); + $output .= $this->renderChildren(); + $this->templateVariableContainer->remove($as); + } + return $output; + } + + /** + * Converts the given value to a simple type (string or array) considering the underlying FormElement definition + * + * @param FormElementInterface $element + * @param mixed $value + * @param FormRuntime $formRuntime + * @return mixed + */ + protected function processElementValue(FormElementInterface $element, $value, FormRuntime $formRuntime) + { + $properties = $element->getProperties(); + if (isset($properties['options']) && is_array($properties['options'])) { + $properties['options'] = TranslateElementPropertyViewHelper::renderStatic( + ['element' => $element, 'property' => 'options', 'formRuntime' => $formRuntime], + $this->buildRenderChildrenClosure(), + $this->renderingContext + ); + if (is_array($value)) { + return $this->mapValuesToOptions($value, $properties['options']); + } else { + return $this->mapValueToOption($value, $properties['options']); + } + } + if (is_object($value)) { + return $this->processObject($element, $value); + } + return $value; + } + + /** + * Replaces the given values (=keys) with the corresponding elements in $options + * @see mapValueToOption() + * + * @param array $value + * @param array $options + * @return array + */ + protected function mapValuesToOptions(array $value, array $options): array + { + $result = []; + foreach ($value as $key) { + $result[] = $this->mapValueToOption($key, $options); + } + return $result; + } + + /** + * Replaces the given value (=key) with the corresponding element in $options + * If the key does not exist in $options, it is returned without modification + * + * @param mixed $value + * @param array $options + * @return mixed + */ + protected function mapValueToOption($value, array $options) + { + return isset($options[$value]) ? $options[$value] : $value; + } + + /** + * Converts the given $object to a string representation considering the $element FormElement definition + * + * @param FormElementInterface $element + * @param object $object + * @return string + */ + protected function processObject(FormElementInterface $element, $object): string + { + $properties = $element->getProperties(); + if ($object instanceof \DateTime) { + if (isset($properties['dateFormat'])) { + $dateFormat = $properties['dateFormat']; + if (isset($properties['displayTimeSelector']) && $properties['displayTimeSelector'] === true) { + $dateFormat .= ' H:i'; + } + } else { + $dateFormat = \DateTime::W3C; + } + return $object->format($dateFormat); + } + + if ($object instanceof File || $object instanceof FileReference) { + if ($object instanceof FileReference) { + $object = $object->getOriginalResource(); + } + return $object->getName(); + } + + if (method_exists($object, '__toString')) { + return (string)$object; + } + return 'Object [' . get_class($object) . ']'; + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/RenderRenderableViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/RenderRenderableViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..b454752c448994a77ad079a7710f5c4afbe05646 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/RenderRenderableViewHelper.php @@ -0,0 +1,66 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Render a renderable. + * + * Set the renderable into the \TYPO3\CMS\Form\Mvc\View\FormView + * and return the rendered content. + * + * Scope: frontend + * @api + */ +class RenderRenderableViewHelper extends AbstractViewHelper +{ + use CompileWithRenderStatic; + + /** + * @var bool + */ + protected $escapeOutput = false; + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('renderable', RenderableInterface::class, 'A RenderableInterface instance', true); + } + + /** + * @param array $arguments + * @param callable|\Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + * @public + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + /** @var \TYPO3\CMS\Form\Mvc\View\FormView $view */ + $view = $renderingContext->getViewHelperVariableContainer()->getView(); + return $view->renderRenderable($arguments['renderable']); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/RenderViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/RenderViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..7846237ad3195da59bd63650d92bbb20e98a7c34 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/RenderViewHelper.php @@ -0,0 +1,101 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Utility\ArrayUtility; +use TYPO3\CMS\Extbase\Mvc\Web\Response; +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Main Entry Point to render a Form into a Fluid Template + * + * Usage + * ===== + * + * <pre> + * {namespace formvh=TYPO3\CMS\Form\ViewHelpers} + * <formvh:render factoryClass="NameOfYourCustomFactoryClass" /> + * </pre> + * + * The factory class must implement {@link TYPO3\CMS\Form\Domain\Factory\FormFactoryInterface}. + * + * Scope: frontend + * @api + */ +class RenderViewHelper extends AbstractViewHelper +{ + use CompileWithRenderStatic; + + /** + * @var bool + */ + protected $escapeOutput = false; + + /** + * Initialize the arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('persistenceIdentifier', 'string', 'The persistence identifier for the form.', false, null); + $this->registerArgument('factoryClass', 'string', 'The fully qualified class name of the factory', false, ArrayFormFactory::class); + $this->registerArgument('prototypeName', 'string', 'Name of the prototype to use', false, null); + $this->registerArgument('overrideConfiguration', 'array', 'factory specific configuration', false, []); + } + + /** + * @param array $arguments + * @param callable|\Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + * @public + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + $persistenceIdentifier = $arguments['persistenceIdentifier']; + $factoryClass = $arguments['factoryClass']; + $prototypeName = $arguments['prototypeName']; + $overrideConfiguration = $arguments['overrideConfiguration']; + + if (!empty($persistenceIdentifier)) { + $formPersistenceManager = $renderingContext->getObjectManager()->get(FormPersistenceManagerInterface::class); + $formConfiguration = $formPersistenceManager->load($persistenceIdentifier); + ArrayUtility::mergeRecursiveWithOverrule( + $formConfiguration, + $overrideConfiguration + ); + $overrideConfiguration = $formConfiguration; + $overrideConfiguration['persistenceIdentifier'] = $persistenceIdentifier; + } + + if (empty($prototypeName)) { + $prototypeName = isset($overrideConfiguration['prototypeName']) ? $overrideConfiguration['prototypeName'] : 'standard'; + } + + $factory = $renderingContext->getObjectManager()->get($factoryClass); + $formDefinition = $factory->build($overrideConfiguration, $prototypeName); + $response = $renderingContext->getObjectManager()->get(Response::class, $renderingContext->getControllerContext()->getResponse()); + $form = $formDefinition->bind($renderingContext->getControllerContext()->getRequest(), $response); + return $form->render(); + } +} diff --git a/typo3/sysext/form/Classes/ViewHelpers/SelectViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/SelectViewHelper.php deleted file mode 100644 index e1455c3177f4ea842b139b384bbb1eaf6eaefbc5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Classes/ViewHelpers/SelectViewHelper.php +++ /dev/null @@ -1,139 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\ViewHelpers; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * The form wizard controller - */ -class SelectViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\SelectViewHelper -{ - /** - * Render the option tags. - * - * @return array an associative array of options, key will be the value of the option tag - */ - protected function getOptions() - { - if (!is_array($this->arguments['options']) && !$this->arguments['options'] instanceof \Traversable) { - return []; - } - $options = []; - $optionsArgument = $this->arguments['options']; - foreach ($optionsArgument as $key => $value) { - if (is_string($key)) { - $options[$key]['disabled'] = $value['disabled']; - $options[$key]['isOptgroup'] = true; - $optGroupOptions = $value['options']; - foreach ($optGroupOptions as $optionKey => $optionValue) { - $option = $this->getOption($optionKey, $optionValue); - $options[$key]['options'][key($option)] = current($option); - } - } else { - $option = $this->getOption($key, $value); - $options[key($option)] = current($option); - } - } - - if ($this->arguments['sortByOptionLabel']) { - asort($options, SORT_LOCALE_STRING); - } - return $options; - } - - /** - * Build a option array. - * - * @param string $key - * @param string $value - * @return array an associative array of an option, key will be the value of the option tag - */ - protected function getOption($key, $value) - { - $option = []; - if (is_object($value) || is_array($value)) { - if ($this->hasArgument('optionValueField')) { - $key = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionValueField']); - if (is_object($key)) { - if (method_exists($key, '__toString')) { - $key = (string)$key; - } else { - throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Identifying value for object of class "' . get_class($value) . '" was an object.', 1460975593); - } - } - // @todo use $this->persistenceManager->isNewObject() once it is implemented - } elseif ($this->persistenceManager->getIdentifierByObject($value) !== null) { - $key = $this->persistenceManager->getIdentifierByObject($value); - } elseif (method_exists($value, '__toString')) { - $key = (string)$value; - } else { - throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('No identifying value for object of class "' . get_class($value) . '" found.', 1460975538); - } - if ($this->hasArgument('optionLabelField')) { - $value = \TYPO3\CMS\Extbase\Reflection\ObjectAccess::getPropertyPath($value, $this->arguments['optionLabelField']); - if (is_object($value)) { - if (method_exists($value, '__toString')) { - $value = (string)$value; - } else { - throw new \TYPO3\CMS\Fluid\Core\ViewHelper\Exception('Label value for object of class "' . get_class($value) . '" was an object without a __toString() method.', 1460975633); - } - } - } elseif (method_exists($value, '__toString')) { - $value = (string)$value; - // @todo use $this->persistenceManager->isNewObject() once it is implemented - } elseif ($this->persistenceManager->getIdentifierByObject($value) !== null) { - $value = $this->persistenceManager->getIdentifierByObject($value); - } - } - $option[$key] = $value; - return $option; - } - - /** - * Render the option tags. - * - * @param array $options the options for the form. - * @return string rendered tags. - */ - protected function renderOptionTags($options) - { - $output = ''; - if ($this->hasArgument('prependOptionLabel')) { - $value = $this->hasArgument('prependOptionValue') ? $this->arguments['prependOptionValue'] : ''; - $label = $this->arguments['prependOptionLabel']; - $output .= $this->renderOptionTag($value, $label, false) . LF; - } - foreach ($options as $value => $label) { - if ( - isset($label['isOptgroup']) - && $label['isOptgroup'] === true - ) { - $output .= '<optgroup label="' . htmlspecialchars($value) . '"'; - if ($label['disabled'] !== null) { - $output .= ' disabled="disabled"'; - } - $output .= '>' . LF; - foreach ($label['options'] as $optionValue => $optionLabel) { - $isSelected = $this->isSelected($optionValue); - $output .= $this->renderOptionTag($optionValue, $optionLabel, $isSelected) . LF; - } - $output .= ' </optgroup>' . LF; - } else { - $isSelected = $this->isSelected($value); - $output .= $this->renderOptionTag($value, $label, $isSelected) . LF; - } - } - return $output; - } -} diff --git a/typo3/sysext/form/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php b/typo3/sysext/form/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..5abb18b4c59b3b2d3484922a527681043a698119 --- /dev/null +++ b/typo3/sysext/form/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php @@ -0,0 +1,80 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\ViewHelpers; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper; +use TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface; +use TYPO3\CMS\Form\Domain\Renderer\RendererInterface; +use TYPO3\CMS\Form\Domain\Runtime\FormRuntime; +use TYPO3\CMS\Form\Service\TranslationService; +use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; +use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; + +/** + * Translate form element properites. + * + * Scope: frontend / backend + * @api + */ +class TranslateElementPropertyViewHelper extends AbstractViewHelper +{ + use CompileWithRenderStatic; + + /** + * Initialize arguments. + * + * @return void + * @internal + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('element', RootRenderableInterface::class, 'Form Element to translate', true); + $this->registerArgument('property', 'string', 'Property to translate', false); + $this->registerArgument('renderingOptionProperty', 'string', 'Property to translate', false); + $this->registerArgument('formRuntime', FormRuntime::class, 'The form runtime', false); + } + + /** + * Return array element by key. + * + * @param array $arguments + * @param \Closure $renderChildrenClosure + * @param RenderingContextInterface $renderingContext + * @return string + * @api + */ + public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) + { + $element = $arguments['element']; + $formRuntime = $arguments['formRuntime']; + + $property = null; + if (!empty($arguments['property'])) { + $property = $arguments['property']; + } elseif (!empty($arguments['renderingOptionProperty'])) { + $property = $arguments['renderingOptionProperty']; + } + + if ($formRuntime === null) { + /** @var RendererInterface $fluidFormRenderer */ + $fluidFormRenderer = $renderingContext->getViewHelperVariableContainer()->getView(); + $formRuntime = $fluidFormRenderer->getFormRuntime(); + } + + return TranslationService::getInstance()->translateFormElementValue($element, $property, $formRuntime); + } +} diff --git a/typo3/sysext/form/Configuration/Backend/AjaxRoutes.php b/typo3/sysext/form/Configuration/Backend/AjaxRoutes.php deleted file mode 100644 index 660792b6c3ab6a92bc9eb146fde6d2eba38c9209..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/Backend/AjaxRoutes.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php -use TYPO3\CMS\Form\Controller\WizardController; - -/** - * Definitions for AJAX routes provided by EXT:form - */ -return [ - // Save the current form wizard - 'formwizard_save' => [ - 'path' => '/wizard/form/save', - 'target' => WizardController::class . '::saveAction' - ], -]; diff --git a/typo3/sysext/form/Configuration/FlexForms/FormFramework.xml b/typo3/sysext/form/Configuration/FlexForms/FormFramework.xml new file mode 100644 index 0000000000000000000000000000000000000000..b8b9dab0418b46fc4aa62980e62c03aca4bd407b --- /dev/null +++ b/typo3/sysext/form/Configuration/FlexForms/FormFramework.xml @@ -0,0 +1,40 @@ +<T3DataStructure> + <sheets> + <sDEF> + <ROOT> + <TCEforms> + <sheetTitle>LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.pi_flexform.formframework.sheet_general</sheetTitle> + </TCEforms> + <type>array</type> + <el> + <settings.persistenceIdentifier> + <TCEforms> + <label>LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.pi_flexform.formframework.persistenceIdentifier</label> + <onChange>reload</onChange> + <config> + <type>select</type> + <items> + <numIndex index="0" type="array"> + <numIndex index="0">LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.pi_flexform.formframework.selectPersistenceIdentifier</numIndex> + <numIndex index="1"></numIndex> + </numIndex> + </items> + <softref>formPersistenceIdentifier</softref> + </config> + </TCEforms> + </settings.persistenceIdentifier> + <settings.overrideFinishers> + <TCEforms> + <label>LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.pi_flexform.formframework.overrideFinishers</label> + <displayCond>FIELD:settings.persistenceIdentifier:REQ:TRUE</displayCond> + <onChange>reload</onChange> + <config> + <type>check</type> + </config> + </TCEforms> + </settings.overrideFinishers> + </el> + </ROOT> + </sDEF> + </sheets> +</T3DataStructure> diff --git a/typo3/sysext/form/Configuration/PageTS/modWizards.ts b/typo3/sysext/form/Configuration/PageTS/modWizards.ts index aa514e38263e5363c7c0a01d1930c0013580373a..86a93700c9b2fd2b1b5fd0638b365fa60eb69463 100644 --- a/typo3/sysext/form/Configuration/PageTS/modWizards.ts +++ b/typo3/sysext/form/Configuration/PageTS/modWizards.ts @@ -1,367 +1,17 @@ mod.wizards { - newContentElement.wizardItems { - forms { - show :=addToList(mailform) - elements { - mailform { - iconIdentifier = content-elements-mailform - title = LLL:EXT:backend/Resources/Private/Language/locallang_db_new_content_el.xlf:forms_mail_title - description = LLL:EXT:backend/Resources/Private/Language/locallang_db_new_content_el.xlf:forms_mail_description - tt_content_defValues { - CType = mailform - bodytext ( -enctype = multipart/form-data -method = post -prefix = tx_form - ) - } - } - } - } - } - - form { - defaults { - showTabs = elements, options, form - tabs { - elements { - showAccordions = basic, predefined, content - accordions { - basic { - showButtons = textline, textarea, checkbox, radio, select, fileupload, hidden, password, fieldset, submit, reset, button - } - predefined { - showButtons = name, email, checkboxgroup, radiogroup - } - content { - showButtons = header, textblock - } - } - } - - options { - showAccordions = legend, label, attributes, options, validation, filters, various - accordions { - label { - showProperties = label - } - attributes { - showProperties = accept, accept-charset, accesskey, action, alt, autocomplete, autofocus, checked, class, cols, contenteditable, contextmenu, dir, draggable, dropzone, disabled, enctype, hidden, height, id, inputmode, label, lang, list, max, maxlength, method, min, minlength, multiple, name, novalidate, pattern, placeholder, readonly, required, rows, selected, selectionDirection, selectionEnd, selectionStart, size, spellcheck, src, step, style, tabindex, text, title, translate, type, value, width, wrap - } - validation { - showRules = alphabetic, alphanumeric, between, date, digit, email, equals, fileallowedtypes, filemaximumsize, fileminimumsize, float, greaterthan, inarray, integer, ip, length, lessthan, regexp, required, uri - - rules { - alphabetic { - showProperties = message, error, showMessage, allowWhiteSpace - } - - alphanumeric { - showProperties = message, error, showMessage, allowWhiteSpace - } - - between { - showProperties = message, error, showMessage, minimum, maximum, inclusive - } - - date { - showProperties = message, error, showMessage, format - } - - digit { - showProperties = message, error, showMessage - } - - email { - showProperties = message, error, showMessage - } - - equals { - showProperties = message, error, showMessage, field - } - - fileallowedtypes { - showProperties = message, error, showMessage, types - } - - filemaximumsize { - showProperties = message, error, showMessage, maximum - } - - fileminimumsize { - showProperties = message, error, showMessage, minimum - } - - float { - showProperties = message, error, showMessage - } - - greaterthan { - showProperties = message, error, showMessage, minimum - } - - inarray { - showProperties = message, error, showMessage, array, strict - } - - integer { - showProperties = message, error, showMessage - } - - ip { - showProperties = message, error, showMessage - } - - length { - showProperties = message, error, showMessage, minimum, maximum - } - - lessthan { - showProperties = message, error, showMessage, maximum - } - - regexp { - showProperties = message, error, showMessage, expression - } - - required { - showProperties = message, error, showMessage - } - - uri { - showProperties = message, error, showMessage - } - } - } - filtering { - showFilters = alphabetic, alphanumeric, currency, digit, integer, lowercase, regexp, stripnewlines, titlecase, trim, uppercase - - filters { - alphabetic { - showProperties = allowWhiteSpace - } - - alphanumeric { - showProperties = allowWhiteSpace - } - - currency { - showProperties = decimalPoint, thousandSeparator - } - - digit { - showProperties = - } - - integer { - showProperties = - } - - lowercase { - showProperties = - } - - regexp { - showProperties = expression - } - - stripnewlines { - showProperties = - } - - titlecase { - showProperties = - } - - trim { - showProperties = characterList - } - - uppercase { - showProperties = - } - } - } - } - } - - form { - showAccordions = behaviour, prefix, attributes, postProcessor - accordions { - postProcessor { - showPostProcessors = mail, redirect - postProcessors { - mail { - showProperties = recipientEmail, senderEmail, subject - } - redirect { - showProperties = destination - } - } - } - } - } - } - } - - elements { - form { - accordions { - attributes { - showProperties = accept, action, dir, enctype, lang, method, novalidate, class, id, style, title - } - } - } - - button { - showAccordions = label, attributes - accordions { - attributes { - showProperties = name, value, class, id - } - } - } - - checkbox { - showAccordions = label, attributes, validation - accordions { - attributes { - showProperties = name, value, class, id, checked, required - } - validation { - showRules = required - } - } - } - - fieldset { - showAccordions = legend, attributes - accordions { - attributes { - showProperties = class, id - } - } - } - - fileupload { - showAccordions = label, attributes, validation - accordions { - attributes { - showProperties = name, class, id, required - } - validation { - showRules = required, fileallowedtypes, filemaximumsize, fileminimumsize - } - } - } - - hidden { - showAccordions = attributes - accordions { - attributes { - showProperties = name, value - } - } - } - - password { - showAccordions = label, attributes, validation - accordions { - attributes { - showProperties = name, placeholder, class, id, autocomplete, required - } - validation { - showRules = required, equals - } - } - } - - radio < .checkbox - - reset < .button - reset { - accordions { - attributes { - showProperties := removeFromList(name) - } - } - } - - select { - showAccordions = label, attributes, options, validation - accordions { - attributes { - showProperties = name, size, class, id, multiple, required - } - validation { - showRules = required - } - } - } - - submit < .button - submit { - accordions { - attributes { - showProperties := removeFromList(name) - } - } - } - - textarea { - showAccordions = label, attributes, validation, filters - accordions { - attributes { - showProperties = name, placeholder, cols, rows, class, id, required, text - } - filtering { - showFilters = alphabetic, alphanumeric, lowercase, regexp, stripnewlines, titlecase, trim, uppercase - } - validation { - showRules = alphabetic, alphanumeric, length, regexp, required - } - } - } - - textline { - showAccordions = label, attributes, validation, filters - accordions { - attributes { - showProperties = name, placeholder, type, class, id, autocomplete, required - } - validation { - showRules = alphabetic, alphanumeric, between, date, digit, email, equals, float, greaterthan, inarray, integer, ip, length, lessthan, regexp, required, uri - } - filtering { - showFilters = alphabetic, alphanumeric, currency, digit, integer, lowercase, regexp, titlecase, trim, uppercase - } - } - } - - name { - showAccordions = legend, various - } - - email < .textline - - checkboxgroup { - showAccordions = legend, options, various, validation - accordions { - validation { - showRules = required - } - } - } - - radiogroup < .checkboxgroup - - header { - showAccordions = various - } - - textblock { - showAccordions = various - } - } - } + newContentElement.wizardItems { + forms { + show :=addToList(formframework) + elements { + formframework { + iconIdentifier = content-elements-mailform + title = LLL:EXT:backend/Resources/Private/Language/locallang_db_new_content_el.xlf:forms_mail_title + description = LLL:EXT:backend/Resources/Private/Language/locallang_db_new_content_el.xlf:forms_mail_description + tt_content_defValues { + CType = form_formframework + } + } + } + } + } } \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TCA/Overrides/sys_template.php b/typo3/sysext/form/Configuration/TCA/Overrides/sys_template.php deleted file mode 100644 index 6d53f0320ee2e2b0d4e40fcd97d7949ab5321b5d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TCA/Overrides/sys_template.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php -defined('TYPO3_MODE') or die(); - -// Register static TypoScript resource -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addStaticFile('form', 'Configuration/TypoScript/', 'Default TS'); diff --git a/typo3/sysext/form/Configuration/TCA/Overrides/tt_content.php b/typo3/sysext/form/Configuration/TCA/Overrides/tt_content.php index 00b0d95497b3fdf661230f5c2fd7a8d08097562a..99ec0cd67be51141a920b0c1bddd1e1c4a8a76f1 100644 --- a/typo3/sysext/form/Configuration/TCA/Overrides/tt_content.php +++ b/typo3/sysext/form/Configuration/TCA/Overrides/tt_content.php @@ -1,121 +1,30 @@ <?php defined('TYPO3_MODE') or die(); -// add an CType element "mailform" -$GLOBALS['TCA']['tt_content']['ctrl']['typeicon_classes']['mailform'] = 'mimetypes-x-content-form'; - -// check if there is already a forms tab and add the item after that, otherwise -// add the tab item as well -$additionalCTypeItem = [ - 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.I.8', - 'mailform', - 'content-elements-mailform' -]; - -$existingCTypeItems = $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items']; -$groupFound = false; -$groupPosition = false; -foreach ($existingCTypeItems as $position => $item) { - if ($item[0] === 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.div.forms') { - $groupFound = true; - $groupPosition = $position; - break; - } -} - -if ($groupFound && $groupPosition) { - // add the new CType item below CType - array_splice($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'], $groupPosition+1, 0, [0 => $additionalCTypeItem]); -} else { - // nothing found, add two items (group + new CType) at the bottom of the list - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem('tt_content', 'CType', - ['LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.div.forms', '--div--'] +call_user_func(function () { + // Add the FlexForm + \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue( + '*', + 'FILE:EXT:form/Configuration/FlexForms/FormFramework.xml', + 'form_formframework' ); - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem('tt_content', 'CType', $additionalCTypeItem); -} - -// predefined forms -\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns( - 'tt_content', - [ - 'tx_form_predefinedform' => [ - 'label' => 'LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform', - 'exclude' => true, - 'config' => [ - 'type' => 'select', - 'renderType' => 'selectSingle', - 'items' => [ - [ - 'LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform.selectPredefinedForm', - '' - ], - ], - ], - ], - ] -); -$GLOBALS['TCA']['tt_content']['ctrl']['requestUpdate'] .= ',tx_form_predefinedform'; - -// Hide bodytext if a predefined form is selected -$GLOBALS['TCA']['tt_content']['columns']['bodytext']['displayCond']['AND'] = [ - 'OR' => [ - 'FIELD:CType:!=:mailform', - 'AND' => [ - 'FIELD:CType:=:mailform', - 'FIELD:tx_form_predefinedform:REQ:false', - ], - ], -]; -$GLOBALS['TCA']['tt_content']['columns']['bodytext']['config']['wizards']['forms'] = [ - 'notNewRecords' => true, - 'enableByTypeConfig' => 1, - 'type' => 'script', - 'title' => 'Form wizard', - 'icon' => 'EXT:backend/Resources/Public/Images/FormFieldWizard/wizard_forms.gif', - 'module' => [ - 'name' => 'wizard_form' - ], - 'params' => [ - 'xmlOutput' => 0 - ] -]; - -// Add palettes if they are not available -if (!isset($GLOBALS['TCA']['tt_content']['palettes']['visibility'])) { - $GLOBALS['TCA']['tt_content']['palettes']['visibility'] = [ - 'showitem' => ' - hidden;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:hidden_formlabel, - sectionIndex;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:sectionIndex_formlabel, - linkToTop;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:linkToTop_formlabel - ', - ]; -} - -if (!isset($GLOBALS['TCA']['tt_content']['palettes']['frames'])) { - $GLOBALS['TCA']['tt_content']['palettes']['frames'] = [ - 'showitem' => ' - layout;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:layout_formlabel - ', - ]; -} - -$GLOBALS['TCA']['tt_content']['types']['mailform']['showitem'] = ' - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.general;general, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.header;header,rowDescription, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:CType.I.8, - bodytext;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:bodytext.ALT.mailform, - tx_form_predefinedform;LLL:EXT:form/Resources/Private/Language/Database.xlf:tx_form_predefinedform, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.frames;frames, - --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.visibility;visibility, - --palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.access;access, -'; -if (!is_array($GLOBALS['TCA']['tt_content']['types']['mailform']['columnsOverrides'])) { - $GLOBALS['TCA']['tt_content']['types']['mailform']['columnsOverrides'] = []; -} -if (!is_array($GLOBALS['TCA']['tt_content']['types']['mailform']['columnsOverrides']['bodytext'])) { - $GLOBALS['TCA']['tt_content']['types']['mailform']['columnsOverrides']['bodytext'] = []; -} -$GLOBALS['TCA']['tt_content']['types']['mailform']['columnsOverrides']['bodytext']['config']['renderType'] = 'formwizard'; + $GLOBALS['TCA']['tt_content']['types']['form_formframework']['showitem'] = + '--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.general;general,' + . '--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.header;header,rowDescription,' + . '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.plugin,pi_flexform,' + . '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.access,' + . '--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.visibility;visibility,' + . '--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.access;access,' + . '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.appearance,' + . '--palette--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:palette.frames;frames,' + . '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.behaviour,' + . '--div--;LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:tabs.extended'; + + // Register the plugin + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( + 'TYPO3.CMS.Form', + 'Formframework', + 'Form' + ); +}); diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Button.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Button.ts deleted file mode 100644 index 7cec6af661dcd17a863dcf955bf8c58b278f9fd8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Button.ts +++ /dev/null @@ -1,38 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - BUTTON { - 10 { - displayName = Default - partialPath = FlatElements/Button - } - } - } - } - - settings { - registeredElements { - # BUTTON - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.button - # - # A historical element which generates a <input type="button" /> tag. - # To be compatible it is a copy of the new element INPUTTYPEBUTTON - # If you want to use a <button> tag you have to use - # BUTTON =< .BUTTONTAG or use the BUTTONTAG directly - BUTTON =< .INPUTTYPEBUTTON - BUTTON { - partialPath =< plugin.tx_form.view.elementPartials.INPUTTYPEBUTTON.10.partialPath - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Buttontag.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Buttontag.ts deleted file mode 100644 index a4ce6f5cf219de90e5d08acc1b076d876b8c7ca5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Buttontag.ts +++ /dev/null @@ -1,145 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - BUTTONTAG { - 10 { - displayName = Default - partialPath = FlatElements/ButtonTag - } - } - } - } - - settings { - registeredElements { - # BUTTONTAG - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.button - # - # Generates an element <button type="..." /> - BUTTONTAG { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = autofocus - 210 = disabled - 220 = name - 230 = type - 240 = value - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # ButtonViewHelper - 120 = autofocus - 130 = type - } - - # defaultHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set if there is no entry in the user configured element. - defaultHtmlAttributeValues { - type = button - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.BUTTONTAG.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Checkbox.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Checkbox.ts deleted file mode 100644 index 5f2ecfb83ab9fa756d7866e1382305e4bd68ff9a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Checkbox.ts +++ /dev/null @@ -1,147 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - CHECKBOX { - 10 { - displayName = Default - partialPath = FlatElements/Checkbox - } - } - } - } - - settings { - registeredElements { - # CHECKBOX - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.checkbox - # - # @ToDo: add more details - CHECKBOX { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autofocus - 220 = checked - 230 = disabled - 240 = name - 250 = readonly - 260 = required - 270 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = checkbox - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # CheckboxViewHelper - 120 = checked - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.CHECKBOX.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Checkboxgroup.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Checkboxgroup.ts deleted file mode 100644 index fc079b2e885ac98d1dbbaed7dd428376c0e1b72c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Checkboxgroup.ts +++ /dev/null @@ -1,67 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - CHECKBOXGROUP { - 10 { - displayName = Default - partialPath = ContainerElements/Checkboxgroup - } - } - } - } - - settings { - registeredElements { - # CHECKBOXGROUP - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: none - # - # This defines a container element. - # @ToDo: add more details - CHECKBOXGROUP =< .FIELDSET - CHECKBOXGROUP { - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.CHECKBOXGROUP.10.partialPath - - # childrenInheritName - # Used by: frontend - # Overwritable by user: FALSE - # - # If set to 1 all child elements inherit the name of the parent element. - # @ToDo: add more details - childrenInheritName = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Contentelement.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Contentelement.ts deleted file mode 100644 index 871984870c94028c2bad39e24612e9b37661a256..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Contentelement.ts +++ /dev/null @@ -1,69 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - # useless for the wizard but needed for the frontend - CONTENTELEMENT { - 10 { - displayName = Default - partialPath = FlatElements/ContentElement - } - } - } - } - - settings { - registeredElements { - # CONTENTELEMENT - # Used by: frontend - # Used ViewHelper: none - # - # This defines an internal element which holds some basic configuration - # like visibility settings and the used partial path. - # - # @ToDo: add more details - CONTENTELEMENT { - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.CONTENTELEMENT.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Fieldset.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Fieldset.ts deleted file mode 100644 index 2f273285b174cdc66e38537e7aabe61319122a89..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Fieldset.ts +++ /dev/null @@ -1,96 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - FIELDSET { - 10 { - displayName = Default - partialPath = ContainerElements/Fieldset - } - } - } - } - - settings { - registeredElements { - # FIELDSET - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: none - # - # This defines a container element. - # @ToDo: add more details - FIELDSET { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - # element specific attributes - 200 = disabled - 210 = name - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.FIELDSET.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Fileupload.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Fileupload.ts deleted file mode 100644 index 065586cb4b189636ff4135177d62acadc025a4f0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Fileupload.ts +++ /dev/null @@ -1,148 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - FILEUPLOAD { - 10 { - displayName = Default - partialPath = FlatElements/Upload - } - } - } - } - - settings { - registeredElements { - # FILEUPLOAD - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.upload - # - # @ToDo: add more details - FILEUPLOAD { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = accept - 220 = autofocus - 230 = disabled - 240 = multiple - 250 = name - 260 = readonly - 270 = required - 280 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = file - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # UploadViewHelper - 120 = multiple - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.FILEUPLOAD.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Form.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Form.ts deleted file mode 100644 index 1ededb98bdf67f0242efc390124075be3b453bc0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Form.ts +++ /dev/null @@ -1,166 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - FORM { - 10 { - displayName = Default - partialPath = ContainerElements/Form - } - } - } - } - - settings { - registeredElements { - # FORM - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # Used ViewHelper: f:form - # - # @ToDo: add more details - FORM { - # themeName - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # Sets the theme name used for templating. - # Right now there is one default theme. One can define an own theme and use this one instead. - # - # This setting can be overwritten in the FORM object. - # @ToDo: add more details - themeName = Default - - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = action - 210 = accept - 220 = accept-charset - 230 = autocomplete - 240 = enctype - 250 = method - 260 = name - 270 = novalidate - 280 = target - } - - # defaultHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set if there is no entry in the user configured element. - defaultHtmlAttributeValues { - enctype = multipart/form-data - method = post - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues = - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - # FormViewHelper - 90 = enctype - 100 = method - 110 = name - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.FORM.10.partialPath - - # viewHelperDefaultArguments - # Used by: frontend - # Overwritable by user: FALSE - # - # This helper array is used to cast some values needed by the ViewHelpers. - # E.g the f:form ViewHelper needs an array for the - # argument "additionalParams". If additionalParams is not set - # in the userdefined TypoScript this results in a NULL value in the - # templating variable "{model.additionalArguments.additionalParams}" - # and this throws an error. Most of the ViewHelper arguments - # are strings and/ or can handle such NULL values but there are some - # ViewHelpers which need some type casting. - viewHelperDefaultArguments { - arguments { - } - - additionalParams { - } - - argumentsToBeExcludedFromQueryString { - } - } - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Header.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Header.ts deleted file mode 100644 index fc7ea71872ebb588cdc838e85ee182e316b7f3da..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Header.ts +++ /dev/null @@ -1,65 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - HEADER { - 10 { - displayName = Default - partialPath = FlatElements/Header - } - } - } - } - - settings { - registeredElements { - # HEADER - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:format.raw - # - # @ToDo: add more details - HEADER { - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.HEADER.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Hidden.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Hidden.ts deleted file mode 100644 index c33c1edad4a85dc4c342358f064d48f6ded0fc20..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Hidden.ts +++ /dev/null @@ -1,140 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - HIDDEN { - 10 { - displayName = Default - partialPath = FlatElements/Hidden - } - } - } - } - - settings { - registeredElements { - # HIDDEN - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.hidden - # - # @ToDo: add more details - HIDDEN { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = name - 220 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = hidden - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.HIDDEN.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Input.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Input.ts deleted file mode 100644 index 03017f165caf3d71f05aadbe9acdcd634467fd5b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Input.ts +++ /dev/null @@ -1,168 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - INPUT { - 10 { - displayName = Default - partialPath = FlatElements/Input - } - } - } - } - - settings { - registeredElements { - # INPUT - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.textfield - # - # @ToDo: add more details - INPUT { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = accept - 220 = autocomplete - 230 = autofocus - 240 = checked - 250 = disabled - 260 = list - 270 = inputmode - 280 = max - 290 = maxlength - 300 = min - 310 = minlength - 320 = multiple - 330 = name - 340 = pattern - 350 = placeholder - 360 = readonly - 370 = required - 380 = size - 390 = src - 400 = step - 410 = value - 420 = width - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # TextfieldViewHelper - 120 = autofocus - 130 = maxlength - 140 = size - 150 = placeholder - 160 = pattern - 170 = required - 180 = type - } - - # defaultHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set if there is no entry in the user configured element. - defaultHtmlAttributeValues { - type = text - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.INPUT.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Inputtypebutton.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Inputtypebutton.ts deleted file mode 100644 index 5c674eb5f6e909223574c4b359bfe0ae0b6718bc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Inputtypebutton.ts +++ /dev/null @@ -1,144 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - INPUTTYPEBUTTON { - 10 { - displayName = Default - partialPath = FlatElements/InputTypeButton - } - } - } - } - - settings { - registeredElements { - # INPUTTYPEBUTTON - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.textfield - # - # Generates an element <input type="button" /> - INPUTTYPEBUTTON { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autofocus - 220 = disabled - 230 = name - 240 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = button - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # TextfieldViewHelper - 120 = type - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.INPUTTYPEBUTTON.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Label.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Label.ts deleted file mode 100644 index 5a3afe02284b772123128b5160c3022ac7f6ccdb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Label.ts +++ /dev/null @@ -1,22 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - # special definitions for internal usage - LABEL { - 10 { - displayName = Default - partialPath = AdditionalElements/Label - } - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Optgroup.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Optgroup.ts deleted file mode 100644 index a30bf70512bd1d994de3fed7952492bf32798e36..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Optgroup.ts +++ /dev/null @@ -1,17 +0,0 @@ -plugin.tx_form { - settings { - registeredElements { - # OPTGROUP - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: form:select (extends f:form.select) - # - # Element is needed to define select options via TypoScript but - # the rendering is based on the select ViewHelper. - # Therefore no special settings are needed. - # - # @ToDo: add more details - OPTGROUP { - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Option.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Option.ts deleted file mode 100644 index cc84a4b2078e86b714cd4a64074dd26ba027428b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Option.ts +++ /dev/null @@ -1,17 +0,0 @@ -plugin.tx_form { - settings { - registeredElements { - # OPTION - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: form:select (extends f:form.select) - # - # Element is needed to define select options via TypoScript but - # the rendering is based on the select ViewHelper. - # Therefore no special settings are needed. - # - # @ToDo: add more details - OPTION { - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Password.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Password.ts deleted file mode 100644 index c364c2a22b96c17beeb8dc60b9f6b97aa907846c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Password.ts +++ /dev/null @@ -1,153 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - PASSWORD { - 10 { - displayName = Default - partialPath = FlatElements/Password - } - } - } - } - - settings { - registeredElements { - # PASSWORD - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.password - # - # @ToDo: add more details - PASSWORD { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autocomplete - 220 = autofocus - 230 = disabled - 240 = maxlength - 250 = minlength - 260 = name - 270 = pattern - 280 = placeholder - 290 = readonly - 300 = required - 310 = size - 320 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = password - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # PasswordViewHelper - 120 = maxlength - 130 = size - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.PASSWORD.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Radio.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Radio.ts deleted file mode 100644 index 9cf918ef280ad986a50acbe894c186488eaa1874..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Radio.ts +++ /dev/null @@ -1,148 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - RADIO { - 10 { - displayName = Default - partialPath = FlatElements/Radio - } - } - } - } - - settings { - registeredElements { - # RADIO - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.radio - # - # @ToDo: add more details - RADIO { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autofocus - 220 = checked - 230 = disabled - 240 = name - 250 = readonly - 260 = required - 270 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = radio - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - 120 = multiple - # RadioViewHelper - 130 = checked - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.RADIO.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Radiogroup.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Radiogroup.ts deleted file mode 100644 index 9edbc46be52480027d28895fe52be215e33d3ee1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Radiogroup.ts +++ /dev/null @@ -1,67 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - RADIOGROUP { - 10 { - displayName = Default - partialPath = ContainerElements/Radiogroup - } - } - } - } - - settings { - registeredElements { - # RADIOGROUP - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: none - # - # This defines a container element. - # @ToDo: add more details - RADIOGROUP =< .FIELDSET - RADIOGROUP { - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.RADIOGROUP.10.partialPath - - # childrenInheritName - # Used by: frontend - # Overwritable by user: FALSE - # - # If set to 1 all child elements inherit the name of the parent element. - # @ToDo: add more details - childrenInheritName = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Reset.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Reset.ts deleted file mode 100644 index 7a1ce431b00d39c4aac1f45ea3a197a506c80b53..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Reset.ts +++ /dev/null @@ -1,145 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - RESET { - 10 { - displayName = Default - partialPath = FlatElements/Reset - } - } - } - } - - settings { - registeredElements { - # RESET - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.textfield - # - # @ToDo: add more details - RESET { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autofocus - 220 = disabled - 230 = name - 240 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = reset - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # TextfieldViewHelper - 120 = autofocus - 130 = type - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.RESET.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Select.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Select.ts deleted file mode 100644 index be8760d804536e493dc8faf814dcc963026a9f67..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Select.ts +++ /dev/null @@ -1,137 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - SELECT { - 10 { - displayName = Default - partialPath = FlatElements/Select - } - } - } - } - - settings { - registeredElements { - # SELECT - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: form:select (extends f:form.select) - # - # @ToDo: add more details - SELECT { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = autofocus - 210 = disabled - 220 = multiple - 230 = name - 240 = required - 250 = size - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # SelectViewHelper - 120 = multiple - 130 = size - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.SELECT.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Submit.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Submit.ts deleted file mode 100644 index 1965b63f140b872016a573ad14940f2a7d1acfa4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Submit.ts +++ /dev/null @@ -1,141 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - SUBMIT { - 10 { - displayName = Default - partialPath = FlatElements/Submit - } - } - } - } - - settings { - registeredElements { - # SUBMIT - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.submit - # - # @ToDo: add more details - SUBMIT { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autofocus - 220 = disabled - 230 = name - 240 = value - } - - # fixedHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set as attributes. - fixedHtmlAttributeValues { - type = submit - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = dir - 20 = id - 30 = lang - 40 = style - 50 = title - 60 = accesskey - 70 = tabindex - 80 = onclick - 90 = name - 100 = value - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.SUBMIT.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Textarea.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Textarea.ts deleted file mode 100644 index c383e4dfa46370b150df0f1a3c2dc19d8f18042d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Textarea.ts +++ /dev/null @@ -1,148 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - TEXTAREA { - 10 { - displayName = Default - partialPath = FlatElements/Textarea - } - } - } - } - - settings { - registeredElements { - # TEXTAREA - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.textarea - # - # @ToDo: add more details - TEXTAREA { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = autofocus - 210 = cols - 220 = disabled - 230 = inputmode - 240 = maxlength - 250 = minlength - 260 = name - 270 = placeholder - 280 = readonly - 290 = required - 300 = rows - 310 = selectionDirection - 320 = selectionEnd - 330 = selectionStart - 340 = wrap - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # TextareaViewHelper - 120 = autofocus - 130 = rows - 140 = cols - 150 = placeholder - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.TEXTAREA.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Textblock.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Textblock.ts deleted file mode 100644 index 805f39674b49a5d7e2e05e3331e60085995817f2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Textblock.ts +++ /dev/null @@ -1,65 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - TEXTBLOCK { - 10 { - displayName = Default - partialPath = FlatElements/Textblock - } - } - } - } - - settings { - registeredElements { - # TEXTBLOCK - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:format.raw - # - # @ToDo: add more details - TEXTBLOCK { - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.TEXTBLOCK.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 0 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 0 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Elements/Textline.ts b/typo3/sysext/form/Configuration/TypoScript/Elements/Textline.ts deleted file mode 100644 index 0951d0eeebced7625bee34dd082ede53880cacc9..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Elements/Textline.ts +++ /dev/null @@ -1,160 +0,0 @@ -plugin.tx_form { - # elementPartials - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines the template selection array for the form wizard. - # Each defined item is shown as option within the wizard. - # - # If there is no partialPath property in the userdefined TypoScript - # then elementPartials.ELEMENTNAME.10.partialPath is the default. - view { - elementPartials { - TEXTLINE { - 10 { - displayName = Default - partialPath = FlatElements/Textfield - } - } - } - } - - settings { - registeredElements { - # TEXTLINE - # Used by: frontend, wizard (not implemented right now) - # Used ViewHelper: f:form.textfield - # - # @ToDo: add more details - TEXTLINE { - # htmlAttributes - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # Defines allowed HTML attributes for a specific element. - # Based on selfhtml documentation version 8.1.2 (see http://wiki.selfhtml.org/wiki/Referenz:HTML/). - # This is needed to detect and map these strings within the user configured element definition as HTML attributes. - # As soon as prefix-* is defined every attribute is registered automatically as HTML attribute. - htmlAttributes { - # generic attributes - 10 = id - 20 = class - 30 = accesskey - 40 = contenteditable - 50 = contextmenu - 60 = dir - 70 = draggable - 80 = dropzone - 90 = hidden - 100 = lang - 110 = spellcheck - 120 = style - 130 = tabindex - 140 = title - 150 = data-* - 160 = translate - # element specific attributes - 200 = type - 210 = autocomplete - 220 = autofocus - 230 = disabled - 240 = inputmode - 250 = list - 260 = maxlength - 270 = minlength - 280 = name - 290 = pattern - 300 = placeholder - 310 = readonly - 320 = required - 330 = size - 340 = value - } - - # htmlAttributesUsedByTheViewHelperDirectly - # Used by: frontend - # Overwritable by user: FALSE - # - # Each HTML attribute defined at ".htmlAttributes" is available as array within the model. - # This array will be added to the resulting HTML tag. - # For this purpose the Fluid argument "additionalAttributes" of the ViewHelper is used. - # - # Some HTML attributes have to be assigned directly as an argument to the ViewHelper. - # The htmlAttributesUsedByTheViewHelperDirectly map is used to remove the specified - # HTML attribute from the "htmlAttributes" array and sets it for the model's "additionalArguments" array. - # - # There are two attributes which special behavior: - # * disabled - # * readonly - # These attributes can be assigned to the most ViewHelpers but whenever a "disabled" attribute appears - # the browser will disable this element no matter of the value. - # See: https://forge.typo3.org/issues/42474 - # Therefore it is held in the htmlAttributes array and the code removes this attribute if its value is set to 0. - htmlAttributesUsedByTheViewHelperDirectly { - # generic attributes - 10 = class - 20 = dir - 30 = id - 40 = lang - 50 = style - 60 = title - 70 = accesskey - 80 = tabindex - 90 = onclick - 100 = name - 110 = value - # TextfieldViewHelper - 120 = autofocus - 130 = maxlength - 140 = size - 150 = placeholder - 160 = pattern - 170 = required - 180 = type - } - - # defaultHtmlAttributeValues - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The following values are automatically set if there is no entry in the user configured element. - defaultHtmlAttributeValues { - type = text - } - - # partialPath - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: TRUE - # - # The defined partial is used to render the element. - # The partial paths to the element are build based on the following rule: - # {$plugin.tx_form.view.partialRootPath}/{$themeName}/@actionName/{$partialPath}. - partialPath =< plugin.tx_form.view.elementPartials.TEXTLINE.10.partialPath - - # visibleInShowAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the form. - # @ToDo: add more details - visibleInShowAction = 1 - - # visibleInConfirmationAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the confirmation page. - # @ToDo: add more details - visibleInConfirmationAction = 1 - - # visibleInProcessAction - # Used by: frontend - # Overwritable by user: TRUE - # - # If set to 1 this element is displayed in the mail. - # @ToDo: add more details - visibleInMail = 1 - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Filters/Filters.ts b/typo3/sysext/form/Configuration/TypoScript/Filters/Filters.ts deleted file mode 100644 index 6d6c36c44b2584af1f97861cf20e3d38c9b7e6cb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Filters/Filters.ts +++ /dev/null @@ -1,66 +0,0 @@ -plugin.tx_form { - settings { - # registeredFilters - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The array holds all available filters. - # "displayName" is planned for the wizard (not implemented right now). - registeredFilters { - alphabetic { - displayName = Alphabetic - className = TYPO3\CMS\Form\Domain\Filter\AlphabeticFilter - } - - alphanumeric { - displayName = Alphanumeric - className = TYPO3\CMS\Form\Domain\Filter\AlphanumericFilter - } - - currency { - displayName = Currency - className = TYPO3\CMS\Form\Domain\Filter\CurrencyFilter - } - - digit { - displayName = Digit - className = TYPO3\CMS\Form\Domain\Filter\DigitFilter - } - - integer { - displayName = Integer - className = TYPO3\CMS\Form\Domain\Filter\IntegerFilter - } - - lowercase { - displayName = Lowercase - className = TYPO3\CMS\Form\Domain\Filter\LowerCaseFilter - } - - regexp { - displayName = Regular Expression - className = TYPO3\CMS\Form\Domain\Filter\RegExpFilter - } - - stripnewlines { - displayName = Strip New Lines - className = TYPO3\CMS\Form\Domain\Filter\StripNewLinesFilter - } - - titlecase { - displayName = Titlecase - className = TYPO3\CMS\Form\Domain\Filter\TitleCaseFilter - } - - trim { - displayName = Trim - className = TYPO3\CMS\Form\Domain\Filter\TrimFilter - } - - uppercase { - displayName = Uppercase - className = TYPO3\CMS\Form\Domain\Filter\UpperCaseFilter - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/Validators/Validators.ts b/typo3/sysext/form/Configuration/TypoScript/Validators/Validators.ts deleted file mode 100644 index d8534f1558b971d0d6058bc85cacae345e08bf25..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/Validators/Validators.ts +++ /dev/null @@ -1,111 +0,0 @@ -plugin.tx_form { - settings { - # registeredValidators - # Used by: frontend, wizard (not implemented right now) - # Overwritable by user: FALSE - # - # The array holds all available validators. - # "displayName" is planned for the form wizard (not implemented right now). - registeredValidators { - alphabetic { - displayName = Alphabetic - className = TYPO3\CMS\Form\Domain\Validator\AlphabeticValidator - } - - alphanumeric { - displayName = Alphanumeric - className = TYPO3\CMS\Form\Domain\Validator\AlphanumericValidator - } - - between { - displayName = Between - className = TYPO3\CMS\Form\Domain\Validator\BetweenValidator - } - - date { - displayName = Date - className = TYPO3\CMS\Form\Domain\Validator\DateValidator - } - - digit { - displayName = Digit - className = TYPO3\CMS\Form\Domain\Validator\DigitValidator - } - - email { - displayName = Email address - className = TYPO3\CMS\Form\Domain\Validator\EmailValidator - } - - equals { - displayName = Equals - className = TYPO3\CMS\Form\Domain\Validator\EqualsValidator - } - - fileallowedtypes { - displayName = Allowed mimetypes for file - className = TYPO3\CMS\Form\Domain\Validator\FileAllowedTypesValidator - } - - filemaximumsize { - displayName = Maximum size for file (bytes) - className = TYPO3\CMS\Form\Domain\Validator\FileMaximumSizeValidator - } - - fileminimumsize { - displayName = Minimum size for file (bytes) - className = TYPO3\CMS\Form\Domain\Validator\FileMinimumSizeValidator - } - - float { - displayName = Float - className = TYPO3\CMS\Form\Domain\Validator\FloatValidator - } - - greaterthan { - displayName = Greater than - className = TYPO3\CMS\Form\Domain\Validator\GreaterThanValidator - } - - inarray { - displayName = In array - className = TYPO3\CMS\Form\Domain\Validator\InArrayValidator - } - - integer { - displayName = Integer - className = TYPO3\CMS\Form\Domain\Validator\IntegerValidator - } - - ip { - displayName = Ip address - className = TYPO3\CMS\Form\Domain\Validator\IpValidator - } - - length { - displayName = Length - className = TYPO3\CMS\Form\Domain\Validator\LengthValidator - } - - lessthan { - displayName = Less than - className = TYPO3\CMS\Form\Domain\Validator\LessThanValidator - } - - regexp { - displayName = Regular Expression - className = TYPO3\CMS\Form\Domain\Validator\RegExpValidator - } - - required { - displayName = Required - className = TYPO3\CMS\Form\Domain\Validator\RequiredValidator - } - - uri { - displayName = Uniform Resource Identifier - className = TYPO3\CMS\Form\Domain\Validator\UriValidator - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/backend.txt b/typo3/sysext/form/Configuration/TypoScript/backend.txt new file mode 100644 index 0000000000000000000000000000000000000000..20604aa8aec75f5e3441cc3dbc53c96267315e74 --- /dev/null +++ b/typo3/sysext/form/Configuration/TypoScript/backend.txt @@ -0,0 +1,15 @@ +module.tx_form { + settings { + yamlConfigurations { + 10 = EXT:form/Configuration/Yaml/BaseSetup.yaml + 20 = EXT:form/Configuration/Yaml/FormEditorSetup.yaml + 30 = EXT:form/Configuration/Yaml/FormEngineSetup.yaml + } + } + + view { + templateRootPaths.10 = EXT:form/Resources/Private/Backend/Templates/ + partialRootPaths.10 = EXT:form/Resources/Private/Backend/Partials/ + layoutRootPaths.10 = EXT:form/Resources/Private/Backend/Layouts/ + } +} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/constants.txt b/typo3/sysext/form/Configuration/TypoScript/constants.txt deleted file mode 100644 index 55c53277bd2386a0883486d93ed58707227797c3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/TypoScript/constants.txt +++ /dev/null @@ -1,10 +0,0 @@ -plugin.tx_form { - view { - # cat=plugin.tx_form/file; type=string; label=Path to template root (FE) - templateRootPath = EXT:form/Resources/Private/Templates/ - # cat=plugin.tx_form/file; type=string; label=Path to template partials (FE) - partialRootPath = EXT:form/Resources/Private/Partials/ - # cat=plugin.tx_form/file; type=string; label=Path to template layouts (FE) - layoutRootPath = EXT:form/Resources/Private/Layouts/ - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/TypoScript/setup.txt b/typo3/sysext/form/Configuration/TypoScript/setup.txt index acb530668a1175328ef05367579ad659e0270f20..172a79d81ffbee0baa2bdaeb637e863a5785aec6 100644 --- a/typo3/sysext/form/Configuration/TypoScript/setup.txt +++ b/typo3/sysext/form/Configuration/TypoScript/setup.txt @@ -1,256 +1,26 @@ - # Replace rendering of old mailform -tt_content.mailform > -tt_content.mailform = COA -tt_content.mailform.10 = < lib.stdheader -tt_content.mailform.20 = FORM -tt_content.mailform.20 { - stdWrap.wrap = <div class="csc-mailform">|</div> - stdWrap { - editIcons = tt_content: bodytext - editIcons.iconTitle.data = LLL:EXT:css_styled_content/pi1/locallang.xlf:eIcon.form - prefixComment = 2 | Mail form inserted: - } -} - - # Include model definition for all available form elements -<INCLUDE_TYPOSCRIPT: source="DIR: EXT:form/Configuration/TypoScript/Elements" extensions="ts"> - # Include definition of filters -<INCLUDE_TYPOSCRIPT: source="DIR: EXT:form/Configuration/TypoScript/Filters" extensions="ts"> - # Include definition of filters -<INCLUDE_TYPOSCRIPT: source="DIR: EXT:form/Configuration/TypoScript/Validators" extensions="ts"> - plugin.tx_form { - features { - skipDefaultArguments = 1 - } - - view { - templateRootPaths { - 10 = {$plugin.tx_form.view.templateRootPath} - } - - partialRootPaths { - 10 = {$plugin.tx_form.view.partialRootPath} - } - - layoutRootPaths { - 10 = {$plugin.tx_form.view.layoutRootPath} - } - } - - _CSS_DEFAULT_STYLE ( - div.csc-mailform ol { - list-style-type: none; - } - - div.csc-mailform ol, - div.csc-mailform ol li { - margin: 0; - padding: 0; - } - - div.csc-mailform ol li { - overflow: hidden; - } - - div.csc-mailform fieldset { - margin: 0; - padding: 0; - position: relative; - } - - div.csc-mailform legend { - margin-left: 1em; - color: #000000; - font-weight: bold; - } - - div.csc-mailform fieldset ol { - padding: 1em 1em 0 1em; - } - - div.csc-mailform fieldset li { - padding: 0.5em; - margin-bottom: 0.5em; - list-style: none; - } - - div.csc-mailform fieldset.submit { - border-style: none; - } - - /** - * Normal label - * Left aligned, in front of input - */ - div.csc-mailform li label { - float: left; - width: 13em; - margin-right: 1em; - vertical-align: baseline; - } - - div.csc-mailform li input + label, - div.csc-mailform li textarea + label, - div.csc-mailform li select + label { - float: none; - width: auto; - margin-right: 0; - margin-left: 1em; - } - - div.csc-mailform li textarea + label { - vertical-align: top; - } - - label em, - legend em { - display: block; - color: #060; - font-size: 85%; - font-style: normal; - text-transform: uppercase; - } - - legend em { - position: absolute; - } - - label strong, - legend strong { - display: block; - color: #C00; - font-size: 85%; - font-weight: normal; - text-transform: uppercase; - } - - legend strong { - position: absolute; - top: 1.4em; - } - - /** - * Labels alignment right - */ - .labels-alignment-right label, - .labels-alignment-right .fieldset-subgroup legend, - .labels-alignment-right.fieldset-subgroup legend { - text-align: right; - } - - /** - * Horizontal fieldset - */ - fieldset.fieldset-horizontal { - border-width: 0; - } - - fieldset.fieldset-horizontal ol { - padding: 0; - } - - fieldset.fieldset-horizontal li { - float: left; - padding: 0; - margin-right: 1em; - } - - fieldset.fieldset-horizontal.label-below label { - display: block; - margin-left: 0; - margin-top: 0.2em; - font-size: 90%; - color: #999999; - text-align: left; - } - - fieldset.fieldset-horizontal label em { - display: inline; - } - - /** - * Subgroup fieldset - */ - fieldset.fieldset-subgroup { - margin-bottom: -2em; - border-style: none; - } - - fieldset.fieldset-subgroup legend { - margin-left: 0; - padding: 0; - font-weight: normal; - width: 13em; - } - - fieldset.fieldset-subgroup ol { - position: relative; - top: -1.4em; - margin: 0 0 0 14em; - padding: 0; - } - - fieldset.fieldset-subgroup li { - padding: 0; - } - - fieldset.fieldset-subgroup input + label { - float: none; - width: auto; - display: inline; - margin: 0 0 0 1em; - } - - /** - * Labels as block - * Labels displayed above or below the input fields - */ - .labels-block label { - display: block; - float: none; - margin: 0 0 0.5em; - width: auto; - } - - .labels-block input + label, - .labels-block textarea + label { - margin: 0.5em 0 0; - } - - .labels-block fieldset.fieldset-subgroup, - fieldset.labels-block.fieldset-subgroup { - margin-bottom: 0; - } - - .labels-block .fieldset-subgroup legend, - .labels-block.fieldset-subgroup legend { - width: auto; - } - - .labels-block .fieldset-subgroup legend em, - .labels-block.fieldset-subgroup legend em { - position: relative; - } - - .labels-block .fieldset-subgroup legend strong, - .labels-block.fieldset-subgroup legend strong { - position: relative; - top: 0; - } - - .labels-block .fieldset-subgroup ol, - .labels-block.fieldset-subgroup ol { - top: 0; - margin: 0; - padding: 0.5em 0 0; - } - - /** - * hide hidden elements - */ - .csc-form-element-hidden { - display: none; - } - ) + view { + templateRootPaths.5 = EXT:form/Resources/Private/Frontend/Templates/ + partialRootPaths.5 = EXT:form/Resources/Private/Frontend/Partials/ + layoutRootPaths.5 = EXT:form/Resources/Private/Frontend/Layouts/ + } + + mvc { + callDefaultActionIfActionCantBeResolved = 1 + } + + settings { + yamlConfigurations { + 10 = EXT:form/Configuration/Yaml/BaseSetup.yaml + 20 = EXT:form/Configuration/Yaml/FormEngineSetup.yaml + } + } } + +# Rendering of content elements +lib.tx_form.contentElementRendering = RECORDS +lib.tx_form.contentElementRendering { + tables = tt_content + source.current = 1 + dontCheckPid = 1 +} \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/UserTSconfig/userTSConfig.txt b/typo3/sysext/form/Configuration/UserTSconfig/userTSConfig.txt deleted file mode 100644 index bb99a382ec2386c9d9473f6ce3df8b477f97ddb7..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Configuration/UserTSconfig/userTSConfig.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Enable the FORM wizard by default for all users -setup.default.tx_form.showWizardByDefault = 1 diff --git a/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml b/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dacc84b9cffb4d9145ce0fc280aa57b2b0afd288 --- /dev/null +++ b/typo3/sysext/form/Configuration/Yaml/BaseSetup.yaml @@ -0,0 +1,340 @@ +TYPO3: + CMS: + Form: + persistenceManager: + allowedFileMounts: + 10: 1:/user_upload/ + allowSaveToExtensionPaths: false + #allowedExtensionPaths: + #10: EXT:example/Resources/Private/Forms/ + + prototypes: + standard: + + ########### DEFAULT FORM ELEMENT DEFINITIONS ########### + formElementsDefinition: + + ### BASE ELEMENTS ### + Form: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseFormElementMixin' + rendererClassName: 'TYPO3\CMS\Form\Domain\Renderer\FluidFormRenderer' + renderingOptions: + renderableNameInTemplate: 'form' + honeypot: + enable: true + formElementToUse: 'Honeypot' + + ### FORM ELEMENTS: CONTAINER ### + Page: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseFormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\Page' + renderingOptions: + renderableNameInTemplate: 'page' + + SummaryPage: + __inheritances: + 10: 'TYPO3.CMS.Form.prototypes.standard.formElementsDefinition.Page' + + Fieldset: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\Section' + renderingOptions: + renderableNameInTemplate: 'section' + + ### FORM ELEMENTS: INPUT ### + Text: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.TextMixin' + + Password: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.TextMixin' + + AdvancedPassword: + __inheritances: + 10: 'TYPO3.CMS.Form.prototypes.standard.formElementsDefinition.Password' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\AdvancedPassword' + properties: + elementClassAttribute: 'input-medium' + confirmationLabel: '' + # Optional description (hint) for the first password input element + #passwordDescription: '' + confirmationClassAttribute: 'input-medium' + + Textarea: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.TextMixin' + properties: + elementClassAttribute: 'xxlarge' + + Honeypot: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.TextMixin' + properties: + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + + ### FORM ELEMENTS: SELECT ### + Checkbox: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + properties: + elementClassAttribute: 'add-on' + value: 1 + + MultiCheckbox: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.MultiSelectionMixin' + + MultiSelect: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.MultiSelectionMixin' + properties: + elementClassAttribute: 'xlarge' + + RadioButton: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.SingleSelectionMixin' + properties: + elementClassAttribute: 'xlarge' + + SingleSelect: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.SingleSelectionMixin' + + ### FORM ELEMENTS: CUSTOM ### + DatePicker: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\DatePicker' + properties: + elementClassAttribute: 'small' + timeSelectorClassAttribute: 'mini' + dateFormat: 'Y-m-d' + enableDatePicker: true + displayTimeSelector: false + + StaticText: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.ReadOnlyFormElementMixin' + properties: + text: '' + + Hidden: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + + ContentElement: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.ReadOnlyFormElementMixin' + properties: + contentElementUid: '' + + ### FORM ELEMENTS: UPLOADS ### + FileUpload: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FileUploadMixin' + properties: + allowedMimeTypes: ['application/doc', 'application/docx', 'application/odt', 'application/pdf'] + + ImageUpload: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FileUploadMixin' + properties: + allowedMimeTypes: ['image/jpeg', 'image/png', 'image/bmp'] + elementClassAttribute: 'lightbox' + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + + ### FINISHERS ### + + finishersDefinition: + Closure: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersTranslationSettingsMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\ClosureFinisher' + options: + #closure: + + Confirmation: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersTranslationSettingsMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher' + #options: + #message: '' + + EmailToSender: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersEmailMixin' + + EmailToReceiver: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersEmailMixin' + + DeleteUploads: + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\DeleteUploadsFinisher' + + FlashMessage: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersTranslationSettingsMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\FlashMessageFinisher' + #options: + #messageBody: '' + #messageTitle: '' + #messageArguments: {} + #messageCode: 0 + #severity: 0 + + Redirect: + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\RedirectFinisher' + #options: + #pageUid: 1 + #additionalParameters: '' + #delay: 0 + #statusCode: 303 + + SaveToDatabase: + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\SaveToDatabaseFinisher' + #options: + #table: '' + #elements: + # <elementIdentifier>: + # mapOnDatabaseColumn: sender_name + # saveFileIdentifierInsteadOfUid: 'false' + + ### VALIDATORS ### + validatorsDefinition: + NotEmpty: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator' + DateTime: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\DateTimeValidator' + Alphanumeric: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\AlphanumericValidator' + Text: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\TextValidator' + StringLength: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\StringLengthValidator' + #options: + #minimum: 0 + #maximum: 0 + EmailAddress: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\EmailAddressValidator' + Integer: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\IntegerValidator' + Float: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\FloatValidator' + NumberRange: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\NumberRangeValidator' + #options: + #minimum: 0 + #maximum: 0 + RegularExpression: + implementationClassName: 'TYPO3\CMS\Extbase\Validation\Validator\RegularExpressionValidator' + #options: + #regularExpression: '/^.*$/' + Count: + implementationClassName: 'TYPO3\CMS\Form\Mvc\Validation\CountValidator' + #options: + #minimum: 0 + #maximum: 0 + + ########### MIXINS ########### + mixins: + translationSettingsMixin: + translation: + translationFile: 'EXT:form/Resources/Private/Language/locallang.xlf' + translatePropertyValueIfEmpty: true + + finishersTranslationSettingsMixin: + options: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.translationSettingsMixin' + + ########### FORM ELEMENT MIXINS ########### + formElementMixins: + BaseFormElementMixin: + renderingOptions: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.translationSettingsMixin' + + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/FormElements/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/FormElements/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/FormElements/' + + # It is possible to set a full path to a template e.g. for custom elements + # In this case 'templateRootPaths' will be ignored + # templatePathAndFilename: 'EXT:form/Resources/Private/Frontend/Templates/FormElements/RadioButton.html' + + # set this to TRUE if you want to avoid exceptions for FormElements without definitions + skipUnknownElements: true + + ReadOnlyFormElementMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseFormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement' + renderingOptions: + renderableNameInTemplate: 'element' + + FormElementMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseFormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement' + properties: + containerClassAttribute: 'input' + elementClassAttribute: '' + elementErrorClassAttribute: 'error' + renderingOptions: + renderableNameInTemplate: 'element' + + TextMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + + SelectionMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + + SingleSelectionMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.SelectionMixin' + + MultiSelectionMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.SelectionMixin' + + FileUploadMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.FormElementMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload' + properties: + saveToFileMount: '1:/user_upload/' + + finishersEmailMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.finishersTranslationSettingsMixin' + implementationClassName: 'TYPO3\CMS\Form\Domain\Finishers\EmailFinisher' + options: + #subject: '' + #recipientAddress: '' + #recipientName: '' + #senderAddress: + #senderName: '' + #replyToAddress: '' + #carbonCopyAddress: '' + #blindCarbonCopyAddress: '' + #format: 'html' + #attachUploads: true + #translation: + # language: 'default' + # {@format} depends the 'format' value + templatePathAndFilename: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Email/{@format}.html' + #partialRootPaths: [] + #layoutRootPaths: [] + #variables: {} diff --git a/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml new file mode 100644 index 0000000000000000000000000000000000000000..98edc7625355a6040c9d78685d3c0f800f75164c --- /dev/null +++ b/typo3/sysext/form/Configuration/Yaml/FormEditorSetup.yaml @@ -0,0 +1,1005 @@ +TYPO3: + CMS: + Form: + ########### FORM MANAGER CONFIGURATION ########### + formManager: + dynamicRequireJsModules: + app: 'TYPO3/CMS/Form/Backend/FormManager' + viewModel: 'TYPO3/CMS/Form/Backend/FormManager/ViewModel' + stylesheets: + 100: 'EXT:form/Resources/Public/Css/form.css' + translationFile: 'EXT:form/Resources/Private/Language/Database.xlf' + javaScriptTranslationFile: 'EXT:form/Resources/Private/Language/locallang_formManager_javascript.xlf' + selectablePrototypesConfiguration: + 100: + identifier: 'standard' + label: 'formManager.selectablePrototypesConfiguration.standard.label' + newFormTemplates: + 100: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml' + label: 'formManager.selectablePrototypesConfiguration.standard.newFormTemplates.blankForm.label' + 200: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml' + label: 'formManager.selectablePrototypesConfiguration.standard.newFormTemplates.simpleContactForm.label' + controller: + deleteAction: + errorTitle: 'formManagerController.deleteAction.error.title' + errorMessage: 'formManagerController.deleteAction.error.body' + + ########### FORMEDITOR CONFIGURATION ########### + prototypes: + standard: + formEditor: + translationFile: 'EXT:form/Resources/Private/Language/Database.xlf' + dynamicRequireJsModules: + app: 'TYPO3/CMS/Form/Backend/FormEditor' + mediator: 'TYPO3/CMS/Form/Backend/FormEditor/Mediator' + viewModel: 'TYPO3/CMS/Form/Backend/FormEditor/ViewModel' + additionalViewModelModules: + + addInlineSettings: [] + maximumUndoSteps: 10 + + stylesheets: + # @toDo: move form.less to the TYPO3 Build folder + 200: 'EXT:form/Resources/Public/Css/form.css' + + formEditorTemplates: + templateRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + + # Element options editors + FormElement-_ElementToolbar: 'Stage/_ElementToolbar' + FormElement-_UnknownElement: 'Stage/_UnknownElement' + FormElement-Page: 'Stage/Page' + FormElement-SummaryPage: 'Stage/SummaryPage' + FormElement-Fieldset: 'Stage/Fieldset' + FormElement-Text: 'Stage/Text' + FormElement-Password: 'Stage/Password' + FormElement-AdvancedPassword: 'Stage/AdvancedPassword' + FormElement-Textarea: 'Stage/Textarea' + FormElement-Checkbox: 'Stage/Checkbox' + FormElement-MultiCheckbox: 'Stage/MultiCheckbox' + FormElement-MultiSelect: 'Stage/MultiSelect' + FormElement-RadioButton: 'Stage/RadioButton' + FormElement-SingleSelect: 'Stage/SingleSelect' + FormElement-DatePicker: 'Stage/DatePicker' + FormElement-StaticText: 'Stage/StaticText' + FormElement-Hidden: 'Stage/Hidden' + FormElement-ContentElement: 'Stage/ContentElement' + FormElement-FileUpload: 'Stage/FileUpload' + FormElement-ImageUpload: 'Stage/ImageUpload' + + Modal-InsertElements: 'Modals/InsertElements' + Modal-InsertPages: 'Modals/InsertPages' + Modal-ValidationErrors: 'Modals/ValidationErrors' + + Inspector-FormElementHeaderEditor: 'Inspector/FormElementHeaderEditor' + Inspector-CollectionElementHeaderEditor: 'Inspector/CollectionElementHeaderEditor' + Inspector-TextEditor: 'Inspector/TextEditor' + Inspector-PropertyGridEditor: 'Inspector/PropertyGridEditor' + Inspector-SingleSelectEditor: 'Inspector/SingleSelectEditor' + Inspector-TextareaEditor: 'Inspector/TextareaEditor' + Inspector-RemoveElementEditor: 'Inspector/RemoveElementEditor' + Inspector-FinishersEditor: 'Inspector/FinishersEditor' + Inspector-ValidatorsEditor: 'Inspector/ValidatorsEditor' + Inspector-RequiredValidatorEditor: 'Inspector/RequiredValidatorEditor' + Inspector-CheckboxEditor: 'Inspector/CheckboxEditor' + Inspector-Typo3WinBrowserEditor: 'Inspector/Typo3WinBrowserEditor' + + formElementPropertyValidatorsDefinition: + NotEmpty: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.NotEmpty.label' + Integer: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.Integer.label' + NaiveEmail: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label' + NaiveEmailOrEmpty: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label' + FormElementIdentifierWithinCurlyBracesInclusive: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label' + FormElementIdentifierWithinCurlyBracesExclusive: + errorMessage: 'formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label' + + formElementGroups: + input: + label: 'formEditor.formElementGroups.input.label' + select: + label: 'formEditor.formElementGroups.select.label' + custom: + label: 'formEditor.formElementGroups.custom.label' + container: + label: 'formEditor.formElementGroups.container.label' + page: + label: 'formEditor.formElementGroups.page.label' + + ########### DEFAULT FORM ELEMENT DEFINITIONS ########### + formElementsDefinition: + Form: + formEditor: + _isCompositeFormElement: false + _isTopLevelFormElement: true + + saveSuccessFlashMessageTitle: 'formEditor.elements.Form.saveSuccessFlashMessageTitle' + saveSuccessFlashMessageMessage: 'formEditor.elements.Form.saveSuccessFlashMessageMessage' + + modalValidationErrorsDialogTitle: 'formEditor.modals.validationErrors.dialogTitle' + modalValidationErrorsConfirmButton: 'formEditor.modals.validationErrors.confirmButton' + + modalInsertElementsDialogTitle: 'formEditor.modals.insertElements.dialogTitle' + modalInsertPagesDialogTitle: 'formEditor.modals.newPages.dialogTitle' + + modalCloseDialogMessage: 'formEditor.modals.close.dialogMessage' + modalCloseDialogTitle: 'formEditor.modals.close.dialogTitle' + modalCloseConfirmButton: 'formEditor.modals.close.confirmButton' + modalCloseCancleButton: 'formEditor.modals.close.cancleButton' + + modalRemoveElementDialogTitle: 'formEditor.modals.removeElement.dialogTitle' + modalRemoveElementDialogMessage: 'formEditor.modals.removeElement.dialogMessage' + modalRemoveElementConfirmButton: 'formEditor.modals.removeElement.confirmButton' + modalRemoveElementCancleButton: 'formEditor.modals.removeElement.cancleButton' + modalRemoveElementLastAvailablePageFlashMessageTitle: 'formEditor.modals.removeElement.lastAvailablePageFlashMessageTitle' + modalRemoveElementLastAvailablePageFlashMessageMessage: 'formEditor.modals.removeElement.lastAvailablePageFlashMessageMessage' + + paginationTitle: 'formEditor.pagination.title' + + iconIdentifier: 'content-elements-mailform' + predefinedDefaults: + editors: + 900: + identifier: 'finishers' + templateName: 'Inspector-FinishersEditor' + label: 'formEditor.elements.Form.editor.finishers.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.Form.editor.finishers.EmptyValue.label' + 20: + value: 'EmailToSender' + label: 'formEditor.elements.Form.editor.finishers.EmailToSender.label' + 30: + value: 'EmailToReceiver' + label: 'formEditor.elements.Form.editor.finishers.EmailToReceiver.label' + 40: + value: 'Redirect' + label: 'formEditor.elements.Form.editor.finishers.Redirect.label' + 50: + value: 'DeleteUploads' + label: 'formEditor.elements.Form.editor.finishers.DeleteUploads.label' + + propertyCollections: + finishers: + 10: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.formEmailFinisherMixin' + identifier: 'EmailToSender' + + 20: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.formEmailFinisherMixin' + identifier: 'EmailToReceiver' + editors: + 100: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label' + 200: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label' + 300: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.recipientAddress.label' + 400: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.recipientName.label' + 500: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label' + 600: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label' + 700: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToAddress.label' + 800: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyAddress.label' + 900: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyAddress.label' + 1000: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.format.label' + 1100: + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label' + 1200: + identifier: 'language' + templateName: 'Inspector-SingleSelectEditor' + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label' + propertyPath: 'options.translation.language' + selectOptions: + 10: + value: 'default' + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1' + + 30: + identifier: 'Redirect' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.Redirect.editor.header.label' + 200: + identifier: 'pageUid' + templateName: 'Inspector-Typo3WinBrowserEditor' + label: 'formEditor.elements.Form.finisher.Redirect.editor.pageUid.label' + buttonLabel: 'formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel' + browsableType: pages + propertyPath: 'options.pageUid' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'Integer' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + + 300: + identifier: 'additionalParameters' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label' + propertyPath: 'options.additionalParameters' + + 40: + identifier: 'DeleteUploads' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.DeleteUploads.editor.header.label' + + 50: + identifier: 'Confirmation' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.Confirmation.editor.header.label' + + 60: + identifier: 'Closure' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.Closure.editor.header.label' + + 70: + identifier: 'FlashMessage' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.FlashMessage.editor.header.label' + + 80: + identifier: 'SaveToDatabase' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label' + + ### FORM ELEMENTS: CONTAINER ### + Fieldset: + formEditor: + label: 'formEditor.elements.Fieldset.label' + group: container + groupSorting: 100 + _isCompositeFormElement: true + iconIdentifier: 't3-form-icon-fieldset' + editors: + 200: + label: 'formEditor.elements.Fieldset.editor.label.label' + 800: null + + ### FORM ELEMENTS: PAGE TYPES ### + Page: + formEditor: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.RemovableFormElementMixin' + predefinedDefaults: + label: 'formEditor.elements.Page.label' + group: page + groupSorting: 100 + _isTopLevelFormElement: true + _isCompositeFormElement: true + iconIdentifier: 't3-form-icon-page' + editors: + 200: + label: 'formEditor.elements.Page.editor.label.label' + + SummaryPage: + formEditor: + predefinedDefaults: + label: 'formEditor.elements.SummaryPage.label' + group: page + groupSorting: 200 + _isTopLevelFormElement: true + _isCompositeFormElement: false + iconIdentifier: 't3-form-icon-summary-page' + editors: + 200: + label: 'formEditor.elements.SummaryPage.editor.label.label' + + ### FORM ELEMENTS: INPUT ### + + Text: + formEditor: + label: 'formEditor.elements.Text.label' + group: input + groupSorting: 100 + iconIdentifier: 't3-form-icon-text' + + Password: + formEditor: + label: 'formEditor.elements.Password.label' + group: input + groupSorting: 300 + iconIdentifier: 't3-form-icon-password' + + AdvancedPassword: + formEditor: + label: 'formEditor.elements.AdvancedPassword.label' + group: input + groupSorting: 400 + predefinedDefaults: + properties: + confirmationLabel: 'formEditor.element.AdvancedPassword.editor.confirmationLabel.predefinedDefaults' + defaultValue: null + iconIdentifier: 't3-form-icon-advanced-password' + editors: + 300: + identifier: 'confirmationLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.AdvancedPassword.editor.confirmationLabel.label' + propertyPath: 'properties.confirmationLabel' + 500: null + + Textarea: + formEditor: + label: 'formEditor.elements.Textarea.label' + group: input + groupSorting: 200 + iconIdentifier: 't3-form-icon-textarea' + + ### FORM ELEMENTS: SELECT ### + Checkbox: + formEditor: + label: 'formEditor.elements.Checkbox.label' + group: select + groupSorting: 100 + iconIdentifier: 't3-form-icon-checkbox' + + MultiCheckbox: + formEditor: + label: 'formEditor.elements.MultiCheckbox.label' + group: select + groupSorting: 500 + iconIdentifier: 't3-form-icon-multi-checkbox' + + MultiSelect: + formEditor: + label: 'formEditor.elements.MultiSelect.label' + group: select + groupSorting: 400 + iconIdentifier: 't3-form-icon-multi-select' + + RadioButton: + formEditor: + label: 'formEditor.elements.RadioButton.label' + group: select + groupSorting: 300 + iconIdentifier: 't3-form-icon-radio-button' + + SingleSelect: + formEditor: + label: 'formEditor.elements.SingleSelect.label' + group: select + groupSorting: 200 + iconIdentifier: 't3-form-icon-single-select' + + ### FORM ELEMENTS: CUSTOM ### + DatePicker: + formEditor: + label: 'formEditor.elements.DatePicker.label' + group: custom + groupSorting: 100 + iconIdentifier: 't3-form-icon-date-picker' + editors: + 900: + identifier: 'validators' + templateName: 'Inspector-ValidatorsEditor' + label: 'formEditor.elements.DatePicker.editor.validators.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.DatePicker.editor.validators.EmptyValue.label' + 20: + value: 'DateTime' + label: 'formEditor.elements.DatePicker.editor.validators.DateTime.label' + + propertyCollections: + validators: + 10: + identifier: 'DateTime' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.DatePicker.validators.DateTime.editor.header.label' + + StaticText: + formEditor: + label: 'formEditor.elements.StaticText.label' + group: custom + groupSorting: 400 + predefinedDefaults: + properties: + text: '' + iconIdentifier: 't3-form-icon-static-text' + editors: + 300: + identifier: 'staticText' + templateName: 'Inspector-TextareaEditor' + label: 'formEditor.elements.StaticText.editor.staticText.label' + propertyPath: 'properties.text' + + ContentElement: + formEditor: + label: 'formEditor.elements.ContentElement.label' + group: custom + groupSorting: 500 + predefinedDefaults: + properties: + contentElementUid: '' + iconIdentifier: 't3-form-icon-content-element' + editors: + 200: null + 300: + identifier: 'staticText' + templateName: 'Inspector-Typo3WinBrowserEditor' + label: 'formEditor.elements.StaticText.editor.contentElement.label' + buttonLabel: 'formEditor.elements.StaticText.editor.contentElement.buttonLabel' + browsableType: tt_content + propertyPath: 'properties.contentElementUid' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'Integer' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + + ### FORM ELEMENTS: UPLOADS ### + FileUpload: + formEditor: + label: 'formEditor.elements.FileUpload.label' + group: custom + groupSorting: 200 + predefinedDefaults: + properties: + allowedMimeTypes: ['application/doc', 'application/docx', 'application/odt', 'application/pdf'] + iconIdentifier: 't3-form-icon-file-upload' + editors: + 300: + identifier: 'allowedMimeTypes' + templateName: 'Inspector-SingleSelectEditor' + label: 'formEditor.elements.FileUpload.editor.allowedMimeTypes.label' + propertyPath: 'properties.allowedMimeTypes' + selectOptions: + 10: + value: ['application/doc', 'application/docx', 'application/odt', 'application/pdf'] + label: 'formEditor.elements.FileUpload.editor.allowedMimeTypes.1' + 20: + value: ['application/xls'] + label: 'formEditor.elements.FileUpload.editor.allowedMimeTypes.2' + + ImageUpload: + formEditor: + label: 'formEditor.elements.ImageUpload.label' + group: custom + groupSorting: 300 + predefinedDefaults: + properties: + allowedMimeTypes: ['image/jpeg', 'image/png', 'image/bmp'] + iconIdentifier: 't3-form-icon-image-upload' + + ### FINISHERS ### + finishersDefinition: + EmailToSender: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.header.label' + predefinedDefaults: + options: + subject: '' + recipientAddress: '' + recipientName: '' + senderAddress: '' + senderName: '' + replyToAddress: '' + carbonCopyAddress: '' + blindCarbonCopyAddress: '' + format: 'html' + attachUploads: true + + EmailToReceiver: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label' + predefinedDefaults: + options: + subject: '' + recipientAddress: '' + recipientName: '' + senderAddress: '' + senderName: '' + replyToAddress: '' + carbonCopyAddress: '' + blindCarbonCopyAddress: '' + format: 'html' + attachUploads: true + translation: + language: '' + + Redirect: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.Redirect.editor.header.label' + predefinedDefaults: + options: + pageUid: '' + additionalParameters: '' + + Closure: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.Closure.editor.header.label' + predefinedDefaults: + options: + closure: '' + + Confirmation: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.Confirmation.editor.header.label' + predefinedDefaults: + options: + message: '' + + FlashMessage: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.FlashMessage.editor.header.label' + predefinedDefaults: + options: + messageBody: '' + messageTitle: '' + messageArguments: '' + messageCode: 0 + severity: 0 + + SaveToDatabase: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label' + predefinedDefaults: + options: + table: '' + elements: + + DeleteUploads: + formEditor: + iconIdentifier: 't3-form-icon-finisher' + label: 'formEditor.elements.Form.finisher.DeleteUploads.editor.header.label' + + ### VALIDATORS ### + validatorsDefinition: + NotEmpty: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label : 'formEditor.elements.FormElement.editor.requiredValidator.label' + DateTime: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.DatePicker.validators.DateTime.editor.header.label' + Alphanumeric: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.Alphanumeric.label' + Text: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.Text.label' + StringLength: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.StringLength.label' + predefinedDefaults: + options: + minimum: '' + maximum: '' + EmailAddress: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.EmailAddress.label' + Integer: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.Integer.label' + Float: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.Float.label' + NumberRange: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.NumberRange.label' + predefinedDefaults: + options: + minimum: '' + maximum: '' + RegularExpression: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.TextMixin.editor.validators.RegularExpression.label' + predefinedDefaults: + options: + regularExpression: '' + Count: + formEditor: + iconIdentifier: 't3-form-icon-validator' + label: 'formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label' + predefinedDefaults: + options: + minimum: '' + maximum: '' + + ########### MIXINS ########### + mixins: + ########### FORM ELEMENT MIXINS ########### + formElementMixins: + BaseFormElementMixin: + formEditor: + predefinedDefaults: + editors: + 100: + identifier: 'header' + templateName: 'Inspector-FormElementHeaderEditor' + 200: + identifier: 'label' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.BaseFormElementMixin.editor.label.label' + propertyPath: 'label' + + RemoveButtonMixin: + 9999: + identifier: 'removeButton' + templateName: 'Inspector-RemoveElementEditor' + + RemovableFormElementMixin: + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.RemoveButtonMixin' + + BaseCollectionEditorsMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.RemoveButtonMixin' + 100: + identifier: 'header' + templateName: 'Inspector-CollectionElementHeaderEditor' + label: '' + + MinimumMaximumEditorsMixin: + 200: + identifier: 'minimum' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label' + propertyPath: 'options.minimum' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'Integer' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 300: + identifier: 'maximum' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label' + propertyPath: 'options.maximum' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'Integer' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + + ReadOnlyFormElementMixin: + formEditor: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.RemovableFormElementMixin' + editors: + 200: + label: 'formEditor.elements.ReadOnlyFormElement.editor.label.label' + + FormElementMixin: + formEditor: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.RemovableFormElementMixin' + editors: + 200: + label: 'formEditor.elements.FormElement.editor.label.label' + 800: + identifier: 'requiredValidator' + templateName: 'Inspector-RequiredValidatorEditor' + label: 'formEditor.elements.FormElement.editor.requiredValidator.label' + validatorIdentifier: 'NotEmpty' + + TextMixin: + formEditor: + predefinedDefaults: + properties: + placeholder: '' + defaultValue: '' + editors: + 400: + identifier: 'placeholder' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.TextMixin.editor.placeholder.label' + propertyPath: 'properties.placeholder' + 500: + identifier: 'defaultValue' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.TextMixin.editor.defaultValue.label' + propertyPath: 'defaultValue' + 900: + identifier: 'validators' + templateName: 'Inspector-ValidatorsEditor' + label: 'formEditor.elements.TextMixin.editor.validators.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.TextMixin.editor.validators.EmptyValue.label' + 20: + value: 'Alphanumeric' + label: 'formEditor.elements.TextMixin.editor.validators.Alphanumeric.label' + 30: + value: 'Text' + label: 'formEditor.elements.TextMixin.editor.validators.Text.label' + 40: + value: 'StringLength' + label: 'formEditor.elements.TextMixin.editor.validators.StringLength.label' + 50: + value: 'EmailAddress' + label: 'formEditor.elements.TextMixin.editor.validators.EmailAddress.label' + 60: + value: 'Integer' + label: 'formEditor.elements.TextMixin.editor.validators.Integer.label' + 70: + value: 'Float' + label: 'formEditor.elements.TextMixin.editor.validators.Float.label' + 80: + value: 'NumberRange' + label: 'formEditor.elements.TextMixin.editor.validators.NumberRange.label' + 90: + value: 'RegularExpression' + label: 'formEditor.elements.TextMixin.editor.validators.RegularExpression.label' + + propertyCollections: + validators: + 10: + identifier: 'Alphanumeric' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label' + 20: + identifier: 'Text' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.Text.editor.header.label' + 30: + identifier: 'StringLength' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 20: 'TYPO3.CMS.Form.mixins.formElementMixins.MinimumMaximumEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.StringLength.editor.header.label' + 40: + identifier: 'EmailAddress' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label' + 50: + identifier: 'Integer' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.Integer.editor.header.label' + 60: + identifier: 'Float' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.Float.editor.header.label' + 70: + identifier: 'NumberRange' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 20: 'TYPO3.CMS.Form.mixins.formElementMixins.MinimumMaximumEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.NumberRange.editor.header.label' + 80: + identifier: 'RegularExpression' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label' + 200: + identifier: 'regex' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label' + fieldExplanationText: 'formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.fieldExplanationText' + propertyPath: 'options.regularExpression' + propertyValidators: + 10: 'NotEmpty' + + SelectionMixin: + formEditor: + predefinedDefaults: + properties: + options: [] + editors: + 300: + identifier: 'options' + templateName: 'Inspector-PropertyGridEditor' + label: 'formEditor.elements.SelectionMixin.editor.options.label' + propertyPath: 'properties.options' + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: 'formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle' + removeLastAvailableRowFlashMessageMessage: 'formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage' + + SingleSelectionMixin: + formEditor: + editors: + 300: + shouldShowPreselectedValueColumn: 'single' + multiSelection: false + + MultiSelectionMixin: + formEditor: + editors: + 300: + shouldShowPreselectedValueColumn: 'multiple' + multiSelection: true + 900: + identifier: 'validators' + templateName: 'Inspector-ValidatorsEditor' + label: 'formEditor.elements.MultiSelectionMixin.editor.validators.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label' + 20: + value: 'Count' + label: 'formEditor.elements.MultiSelectionMixin.editor.validators.Count.label' + + propertyCollections: + validators: + 10: + identifier: 'Count' + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 20: 'TYPO3.CMS.Form.mixins.formElementMixins.MinimumMaximumEditorsMixin' + 100: + label: 'formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label' + + FileUploadMixin: + formEditor: + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + editors: + 400: + identifier: 'saveToFileMount' + templateName: 'Inspector-SingleSelectEditor' + label: 'formEditor.elements.FileUploadMixin.editor.saveToFileMount.label' + propertyPath: 'properties.saveToFileMount' + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + + formEmailFinisherMixin: + editors: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin' + 100: + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.header.label' + 200: + identifier: 'subject' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.subject.label' + propertyPath: 'options.subject' + propertyValidators: + 10: 'NotEmpty' + 20: 'FormElementIdentifierWithinCurlyBracesInclusive' + 300: + identifier: 'recipientAddress' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.recipientAddress.label' + propertyPath: 'options.recipientAddress' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'NaiveEmail' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 400: + identifier: 'recipientName' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.recipientName.label' + propertyPath: 'options.recipientName' + 500: + identifier: 'senderAddress' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label' + propertyPath: 'options.senderAddress' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'NaiveEmail' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 600: + identifier: 'senderName' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label' + propertyPath: 'options.senderName' + 700: + identifier: 'replyToAddress' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.replyToAddress.label' + propertyPath: 'options.replyToAddress' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'NaiveEmailOrEmpty' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 800: + identifier: 'carbonCopyAddress' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyAddress.label' + propertyPath: 'options.carbonCopyAddress' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'NaiveEmailOrEmpty' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 900: + identifier: 'blindCarbonCopyAddress' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyAddress.label' + propertyPath: 'options.blindCarbonCopyAddress' + propertyValidatorsMode: 'OR' + propertyValidators: + 10: 'NaiveEmailOrEmpty' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + 1000: + identifier: 'format' + templateName: 'Inspector-SingleSelectEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.format.label' + propertyPath: 'options.format' + selectOptions: + 10: + value: 'plaintext' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.format.1' + 20: + value: 'html' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.format.2' + 1100: + identifier: 'attachUploads' + templateName: 'Inspector-CheckboxEditor' + label: 'formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label' + propertyPath: 'options.attachUploads' \ No newline at end of file diff --git a/typo3/sysext/form/Configuration/Yaml/FormEngineSetup.yaml b/typo3/sysext/form/Configuration/Yaml/FormEngineSetup.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e67943029be475e3fb787ed3096ef3774d987d15 --- /dev/null +++ b/typo3/sysext/form/Configuration/Yaml/FormEngineSetup.yaml @@ -0,0 +1,132 @@ +TYPO3: + CMS: + Form: + prototypes: + standard: + ########### TCE Forms CONFIGURATION ########### + + ### FINISHERS ### + finishersDefinition: + EmailToSender: + FormEngine: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.FormEngineEmailMixin' + + EmailToReceiver: + FormEngine: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.FormEngineEmailMixin' + label: 'tt_content.finishersDefinition.EmailToReceiver.label' + elements: + subject: + label: 'tt_content.finishersDefinition.EmailToReceiver.subject.label' + recipientAddress: + label: 'tt_content.finishersDefinition.EmailToReceiver.recipientAddress.label' + recipientName: + label: 'tt_content.finishersDefinition.EmailToReceiver.recipientName.label' + senderAddress: + label: 'tt_content.finishersDefinition.EmailToReceiver.senderAddress.label' + senderName: + label: 'tt_content.finishersDefinition.EmailToReceiver.senderName.label' + replyToAddress: + label: 'tt_content.finishersDefinition.EmailToReceiver.replyToAddress.label' + carbonCopyAddress: + label: 'tt_content.finishersDefinition.EmailToReceiver.carbonCopyAddress.label' + blindCarbonCopyAddress: + label: 'tt_content.finishersDefinition.EmailToReceiver.blindCarbonCopyAddress.label' + format: + label: 'tt_content.finishersDefinition.EmailToReceiver.format.label' + translation: + language: + label: 'tt_content.finishersDefinition.EmailToReceiver.language.label' + config: + type: select + renderType: 'selectSingle' + minitems: 1 + maxitems: 1 + size: 1 + items: + 10: + 0: 'tt_content.finishersDefinition.EmailToReceiver.language.1' + 1: 'default' + + Redirect: + FormEngine: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.FormEngineTranslationSettingsMixin' + label: 'tt_content.finishersDefinition.Redirect.label' + elements: + pageUid: + label: 'tt_content.finishersDefinition.Redirect.pageUid.label' + config: + type: 'group' + internal_type: 'db' + allowed: 'pages' + size: 1 + minitems: 1 + maxitems: 1 + show_thumbs: 0 + additionalParameters: + label: 'tt_content.finishersDefinition.Redirect.additionalParameters.label' + config: + type: 'input' + + ########### MIXINS ########### + mixins: + FormEngineTranslationSettingsMixin: + translationFile: 'EXT:form/Resources/Private/Language/Database.xlf' + + FormEngineEmailMixin: + __inheritances: + 10: 'TYPO3.CMS.Form.mixins.FormEngineTranslationSettingsMixin' + label: 'tt_content.finishersDefinition.EmailToSender.label' + elements: + subject: + label: 'tt_content.finishersDefinition.EmailToSender.subject.label' + config: + type: 'input' + recipientAddress: + label: 'tt_content.finishersDefinition.EmailToSender.recipientAddress.label' + config: + type: 'input' + eval: 'required' + recipientName: + label: 'tt_content.finishersDefinition.EmailToSender.recipientName.label' + config: + type: 'input' + senderAddress: + label: 'tt_content.finishersDefinition.EmailToSender.senderAddress.label' + config: + type: 'input' + eval: 'required' + senderName: + label: 'tt_content.finishersDefinition.EmailToSender.senderName.label' + config: + type: 'input' + replyToAddress: + label: 'tt_content.finishersDefinition.EmailToSender.replyToAddress.label' + config: + type: 'input' + carbonCopyAddress: + label: 'tt_content.finishersDefinition.EmailToSender.carbonCopyAddress.label' + config: + type: 'input' + blindCarbonCopyAddress: + label: 'tt_content.finishersDefinition.EmailToSender.blindCarbonCopyAddress.label' + config: + type: 'input' + format: + label: 'tt_content.finishersDefinition.EmailToSender.format.label' + config: + type: select + renderType: 'selectSingle' + minitems: 1 + maxitems: 1 + size: 1 + items: + 10: + 0: 'tt_content.finishersDefinition.EmailToSender.format.1' + 1: 'html' + 20: + 0: 'tt_content.finishersDefinition.EmailToSender.format.2' + 1: 'plaintext' \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/.gitignore b/typo3/sysext/form/Documentation/.gitignore deleted file mode 100644 index 6cd159f2dad9a4583183510425d81e948207903b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# this is file .gitignore - -# ignore everything in this directory -_make/* - -# but do not ignore this file -!_not_versioned/.gitignore diff --git a/typo3/sysext/form/Documentation/Administration/DefaultNewRecord/Index.rst b/typo3/sysext/form/Documentation/Administration/DefaultNewRecord/Index.rst deleted file mode 100644 index 2d3fafad982d76d48d7a569e71a3c214ccca4a67..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/DefaultNewRecord/Index.rst +++ /dev/null @@ -1,38 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _default-new-record: - -================== -Default new record -================== - -When an editor creates a new FORM record, the bodytext will be filled by -default with some simple form settings which are displayed below. The -integrator can change this setting to specific needs, but this string -**cannot be big due to some core limitations**. It is impossible to add -the configuration for a complete form, although it might be a simple one. -This restriction is caused by the fact that the whole string is put in -a URI as parameter. - -Furthermore this only works when the editor is using the web module, i.e. -the functionality is not supported by the list module. - -.. code-block:: typoscript - - mod.wizards { - newContentElement.wizardItems { - forms.elements { - mailform { - tt_content_defValues { - bodytext ( - enctype = multipart/form-data - method = post - prefix = tx_form - ) - } - } - } - } - } - diff --git a/typo3/sysext/form/Documentation/Administration/Index.rst b/typo3/sysext/form/Documentation/Administration/Index.rst deleted file mode 100644 index e04e183534481963f0dd1d30cb118a9f95367545..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/Index.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. include:: ../Includes.txt - - -.. _administration: - -============== -Administration -============== - -Upon installation, the extension will set default properties in the page -TSconfig in the variable :ts:`mod.wizards`. - -These properties may be modified for any particular page, BE user or BE -user group and are described below. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - DefaultNewRecord/Index - WizardSettings/Index - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ElementsTab/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ElementsTab/Index.rst deleted file mode 100644 index ad2f016ce0b2bbdfd9b24063680bdc60b6f6d10f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ElementsTab/Index.rst +++ /dev/null @@ -1,131 +0,0 @@ -.. include:: ../../../../Includes.txt - - -.. _wizard-settings-defaults-elements-tab: - -============== -Tab "Elements" -============== - -The elements tab contains an accordion with buttons, grouped by their -type. These buttons identify a form element, like a text field, password -field or submit button. When dragging a button to the form on the right -and dropping it at a certain point in the form, the element will be added -to the form at that point. An editor can also double click a button. When -doing so, the element will be added at the end of the form. - -.. figure:: ../../../../Images/FormCreationWizardElementsTab.png - :alt: The form wizard with the tab "Elements". - -.. contents:: - :local: - :depth: 1 - - -.. _wizard-settings-defaults-elements-showaccordions: - -showAccordions -============== - -(:ts:`mod.wizards.form.defaults.tabs.elements.showAccordions`) - -:aspect:`Property:` - showAccordions - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the accordions that will be shown in the - wizard. Each of the three accordions contain a single showButton - property which defines which form elements will be shown in a given - accordion. - -:aspect:`Default:` - basic, predefined, content - - -.. _wizard-settings-defaults-elements-accordions-showbuttons: - -showButtons -=========== - -(:ts:`mod.wizards.form.defaults.tabs.elements.accordions.[NameOfAccordion].showButtons`) - -:aspect:`Property:` - showButtons - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the buttons that will be shown in the accordion. - Please note, in the shown path has [NameOfAccordion] to be replaced with - the name of the specific accordion. - -:aspect:`Default:` - **"basic" elements** - - - textline (Text Field) - - textarea (Textarea) - - checkbox (Checkbox) - - radio (Radio Button) - - select (Drop Down) - - fileupload (Upload Field) - - hidden (Hidden Field) - - password (Password Field) - - fieldset (Fieldset) - - submit (Submit Button) - - reset (Reset Button) - - button (Button) - - | - - **"predefined" elements** - - - name (Full Name) - - email (Email) - - checkboxgroup (Checkbox Group) - - radiogroup (Radio Button Group) - - | - - **"content" elements** - - - header (Header) - - textblock (Text Block) - - -.. _wizard-settings-defaults-elements-tab-configuration: - -Default configuration -===================== - -The default configuration of the elements tab is as follows. - -.. code-block:: typoscript - - mod.wizards { - form { - defaults { - showTabs = elements, options, form - tabs { - elements { - showAccordions = basic, predefined, content - accordions { - basic { - showButtons = textline, textarea, checkbox, radio, select, fileupload, hidden, password, fieldset, submit, reset, button - } - predefined { - showButtons = name, email, checkboxgroup, radiogroup - } - content { - showButtons = header, textblock - } - } - } - } - } - } - } - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/FormTab/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/FormTab/Index.rst deleted file mode 100644 index d6f2066ad1667ec1b0a79d6018888e57decd170a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/FormTab/Index.rst +++ /dev/null @@ -1,187 +0,0 @@ -.. include:: ../../../../Includes.txt - - -.. _wizard-settings-defaults-form-tab: - -========== -Tab "Form" -========== - -The form tab shows the configuration of the outer form, like the attributes -of the form or the prefix as well as the post-processor configuration. - -.. figure:: ../../../../Images/FormCreationWizardFormTab.png - :alt: The form wizard with the tab "Form". - -.. contents:: - :local: - :depth: 1 - - -.. _wizard-settings-defaults-form-showaccordions: - -showAccordions -============== - -(:ts:`mod.wizards.form.defaults.tabs.form.showAccordions`) - -:aspect:`Property:` - showAccordions - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the accordions that are allowed to be shown in - the wizard. This does not mean they are all shown by default, but - depends on the chosen element type. - - Some accordions have further properties, which are described below. - -:aspect:`Default:` - The following accordions are available in the form tab: - - * behaviour - * prefix - * :ref:`attributes <wizard-settings-defaults-form-attributes>` - * :ref:`postProcessor <wizard-settings-defaults-form-postprocessor>` - - -.. _wizard-settings-defaults-form-attributes: - -Attributes accordion -==================== - - -.. _wizard-settings-defaults-form-attributes-showproperties: - -showProperties --------------- - -.. attention:: - - The configuration of the attributes accordion is not working as - expected and has to be fixed in a coming version of TYPO3. There is - a workaround which is shown below. - -(:ts:`mod.wizards.form.defaults.tabs.form.accordions.attributes.showProperties`) - -:aspect:`Property:` - showProperties - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the form attributes that are allowed to be shown - in the accordion. - -:aspect:`Default:` - accept, action, dir, enctype, lang, method, novalidate, class, id, style, title - -Since the above shown configuration is not working, the following workaround can -be applied. To configure the attribute accordion of the form element, address the -object directly via :ts:`mod.wizards.form.elements.form.accordions.attributes.showProperties`. - - -.. _wizard-settings-defaults-form-postprocessor: - -Post-processors accordion -========================= - - -.. _wizard-settings-defaults-form-postprocessor-showpostprocessors: - -showPostProcessors ------------------- - -(:ts:`mod.wizards.form.defaults.tabs.form.accordions.postProcessor.showPostProcessors`) - -:aspect:`Property:` - showPostProcessors - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the post-processors that are allowed to be shown - in the wizard. - - For each post-processors a list of properties to be shown can be defined. - -:aspect:`Default:` - mail, redirect - - -.. _wizard-settings-defaults-options-postprocessor-postprocessors: - -postProcessors.[post-processor].showProperties ----------------------------------------------- - -(:ts:`mod.wizards.form.defaults.tabs.form.accordions.postProcessor.postProcessors.[post-processor].showProperties`) - -:aspect:`Property:` - postProcessors.[post-processor].showProperties - -:aspect:`Data type:` - string - -:aspect:`Description:` - Configuration for the post-processors individually. - - The syntax is :ts:`postProcessors.[name of the post-processor].showProperties`. - -:aspect:`Default:` - The following element properties are available: - - .. t3-field-list-table:: - :header-rows: 1 - - - :Field: - Element: - :Description: - Properties: - - :Field: - mail - :Description: - recipientEmail, senderEmail, subject - - :Field: - redirect - :Description: - destination - - -.. _wizard-settings-defaults-form-tab-configuration: - -Default configuration -===================== - -The default configuration of the form tab looks as follows: - -.. code-block:: typoscript - - mod.wizards { - form { - defaults { - tabs { - form { - showAccordions = behaviour, prefix, attributes, postProcessor - accordions { - postProcessor { - showPostProcessors = mail, redirect - postProcessors { - mail { - showProperties = recipientEmail, senderEmail, subject - } - redirect { - showProperties = destination - } - } - } - } - } - } - } - } - } - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/Index.rst deleted file mode 100644 index 44a5e56f60baa3474032aea5f8acbfa53384ffee..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/Index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _wizard-settings-defaults: - -================== -Defaults reference -================== - -This chapter describes the settings for the visible tabs, the accordions -available inside these tabs and the default configuration for all element -types. - - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - ShowTabs/Index - ElementsTab/Index - OptionsTab/Index - FormTab/Index - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/OptionsTab/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/OptionsTab/Index.rst deleted file mode 100644 index 8b0b89f3a1abde168fb0d8cb79c512b73b40d6a7..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/OptionsTab/Index.rst +++ /dev/null @@ -1,404 +0,0 @@ -.. include:: ../../../../Includes.txt - - -.. _wizard-settings-defaults-options-tab: - -============= -Tab "Options" -============= - -The options tab will show the configuration of a particular element in -the form. When no element has been selected, it will show a message that -the editor has to select an element in the form. - -The content of this tab depends on the type of element the editor has chosen -in the form. - -.. figure:: ../../../../Images/FormCreationWizardOptionsTab.png - :alt: The form wizard with the tab "Options". - -.. contents:: - :local: - :depth: 1 - - -.. _wizard-settings-defaults-options-showaccordions: - -showAccordions -============== - -:aspect:`Property:` - showAccordions - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.showAccordions` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the accordions that are allowed to be shown - in the wizard. This does not mean they are all shown by default, - but depends on the chosen element type. - - Some tabs have further configuration which is described below. - -:aspect:`Default:` - The following accordions are available: - - - *legend*: Legend Properties - - *label*: :ref:`Label Properties <wizard-settings-defaults-options-label>` - - *attributes*: :ref:`Attributes Properties <wizard-settings-defaults-options-attributes>` - - *options*: Field Options - - *validation*: :ref:`Validation <wizard-settings-defaults-validation-label>` - - *filters*: :ref:`Filters <wizard-settings-defaults-filters-label>` - - *various*: Various Properties - -:aspect:`Example:` - .. code-block:: typoscript - - mod.wizards { - form { - defaults { - tabs { - options { - showAccordions = legend, label, attributes, options, validation, filters, various - } - } - } - - } - } - - -.. _wizard-settings-defaults-options-label: - -Label accordion -=============== - - -.. _wizard-settings-defaults-options-label-showproperties: - -showProperties --------------- - -:aspect:`Property:` - showProperties - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.label.showProperties` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the label options that are allowed to be shown - in the accordion. The appearance of an option depends on the chosen - element type. If an element type does not support an option, it will not - be shown. - -:aspect:`Default:` - label - - -.. _wizard-settings-defaults-options-attributes: - -Attributes accordion -==================== - - -.. _wizard-settings-defaults-options-attributes-showproperties: - -showProperties --------------- - -:aspect:`Property:` - showProperties - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.attributes.showProperties` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of attributes that are allowed to be shown in the - accordion. The appearance of an attribute depends on the chosen element - type. If an element type does not support an attribute, it will not be - shown. - - -:aspect:`Default:` - accept, accept-charset, accesskey, action, alt, autocomplete, autofocus, - checked, class, cols, contenteditable, contextmenu, dir, draggable, - dropzone, disabled, enctype, hidden, height, id, inputmode, label, lang, - list, max, maxlength, method, min, minlength, multiple, name, - novalidate, pattern, placeholder, readonly, required, rows, selected, - selectionDirection, selectionEnd, selectionStart, size, spellcheck, src, - step, style, tabindex, text, title, translate, type, value, width, wrap - - -.. _wizard-settings-defaults-validation-label: - -Validation accordion -==================== - - -.. _wizard-settings-defaults-options-validation-showrules: - -showRules ---------- - -:aspect:`Property:` - showRules - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.validation.showRules` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of rules that are allowed to be shown in the - wizard. - -:aspect:`Default:` - alphabetic, alphanumeric, between, date, digit, email, equals, - fileallowedtypes, filemaximumsize, fileminimumsize, float, greaterthan, - inarray, integer, ip, length, lessthan, regexp, required, uri - - -.. _wizard-settings-defaults-options-validation-rules: - -rules.[rule].showProperties ---------------------------- - -:aspect:`Property:` - rules.[rule].showProperties - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.validation.rules.[rule].showProperties` - -:aspect:`Data type:` - [array of objects] - -:aspect:`Description:` - For each rule one can define which properties should appear. - The syntax is :ts:`rules.[name of the rule].showProperties`. - -:aspect:`Default:` - The following element properties are available: - - =================== ======================================================== - Element Properties - =================== ======================================================== - alphabetic message, error, showMessage, allowWhiteSpace - alphanumeric message, error, showMessage, allowWhiteSpace - between message, error, showMessage, minimum, maximum, inclusive - date message, error, showMessage, format - digit message, error, showMessage - email message, error, showMessage - equals message, error, showMessage, field - fileallowedtypes message, error, showMessage, types - filemaximumsize message, error, showMessage, maximum - fileminimumsize message, error, showMessage, minimum - float message, error, showMessage - greaterthan message, error, showMessage, minimum - inarray message, error, showMessage, array, strict - integer message, error, showMessage - ip message, error, showMessage - length message, error, showMessage, minimum, maximum - lessthan message, error, showMessage, maximum - regexp message, error, showMessage, expression - required message, error, showMessage - uri message, error, showMessage - =================== ======================================================== - - -.. _wizard-settings-defaults-filters-label: - -Filters accordion -================= - - -.. _wizard-settings-defaults-options-filtering-showfilters: - -showFilters ------------ - -:aspect:`Property:` - showFilters - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.filtering.showFilters` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the filters that are allowed to be shown in - the wizard. - - For each filter a list of properties to be shown can be defined. - -:aspect:`Default:` - alphabetic, alphanumeric, currency, digit, integer, lowercase, regexp, - stripnewlines, titlecase, trim, uppercase - - -.. _wizard-settings-defaults-options-filtering-filters: - -filters.[filter].showProperties -------------------------------- - -:aspect:`Property:` - filters.[filter].showProperties - -:aspect:`TypoScript Path:` - :ts:`mod.wizards.form.defaults.tabs.options.accordions.filtering.filters.[filter].showProperties` - -:aspect:`Data type:` - string - -:aspect:`Description:` - Configuration for the filters individually. Not all filters have a - configuration. Only the filters which are mentioned below can be - configured. - - The syntax is :ts:`filters.[name of the filter].showProperties`. - -:aspect:`Default:` - The following element properties are available: - - =================== =============================== - Element Properties - =================== =============================== - alphabetic allowWhiteSpace - alphanumeric allowWhiteSpace - currency decimalPoint, thousandSeparator - regexp expression - trim characterList - =================== =============================== - - -.. _wizard-settings-defaults-options-tab-configuration: - -Default configuration -===================== - -The default configuration of the options tab looks like this: - -.. code-block:: typoscript - - options { - showAccordions = legend, label, attributes, options, validation, filters, various - accordions { - label { - showProperties = label - } - attributes { - showProperties = accept, accept-charset, accesskey, action, alt, autocomplete, autofocus, checked, class, cols, contenteditable, contextmenu, dir, draggable, dropzone, disabled, enctype, hidden, height, id, inputmode, label, lang, list, max, maxlength, method, min, minlength, multiple, name, novalidate, pattern, placeholder, readonly, required, rows, selected, selectionDirection, selectionEnd, selectionStart, size, spellcheck, src, step, style, tabindex, text, title, translate, type, value, width, wrap - } - validation { - showRules = alphabetic, alphanumeric, between, date, digit, email, equals, fileallowedtypes, filemaximumsize, fileminimumsize, float, greaterthan, inarray, integer, ip, length, lessthan, regexp, required, uri - rules { - alphabetic { - showProperties = message, error, showMessage, allowWhiteSpace - } - alphanumeric { - showProperties = message, error, showMessage, allowWhiteSpace - } - between { - showProperties = message, error, showMessage, minimum, maximum, inclusive - } - date { - showProperties = message, error, showMessage, format - } - digit { - showProperties = message, error, showMessage - } - email { - showProperties = message, error, showMessage - } - equals { - showProperties = message, error, showMessage, field - } - fileallowedtypes { - showProperties = message, error, showMessage, types - } - filemaximumsize { - showProperties = message, error, showMessage, maximum - } - fileminimumsize { - showProperties = message, error, showMessage, minimum - } - float { - showProperties = message, error, showMessage - } - greaterthan { - showProperties = message, error, showMessage, minimum - } - inarray { - showProperties = message, error, showMessage, array, strict - } - integer { - showProperties = message, error, showMessage - } - ip { - showProperties = message, error, showMessage - } - length { - showProperties = message, error, showMessage, minimum, maximum - } - lessthan { - showProperties = message, error, showMessage, maximum - } - regexp { - showProperties = message, error, showMessage, expression - } - required { - showProperties = message, error, showMessage - } - uri { - showProperties = message, error, showMessage - } - } - } - filtering { - showFilters = alphabetic, alphanumeric, currency, digit, integer, lowercase, regexp, stripnewlines, titlecase, trim, uppercase - filters { - alphabetic { - showProperties = allowWhiteSpace - } - alphanumeric { - showProperties = allowWhiteSpace - } - currency { - showProperties = decimalPoint, thousandSeparator - } - digit { - showProperties = - } - integer { - showProperties = - } - lowercase { - showProperties = - } - regexp { - showProperties = expression - } - titlecase { - showProperties = - } - trim { - showProperties = characterList - } - uppercase { - showProperties = - } - } - } - } - } - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ShowTabs/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ShowTabs/Index.rst deleted file mode 100644 index 667d2e35641fffc06cf0f37d04e6ab0746a34aee..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/DefaultsReference/ShowTabs/Index.rst +++ /dev/null @@ -1,75 +0,0 @@ -.. include:: ../../../../Includes.txt - - -.. _wizard-settings-defaults-showtabs: - -======== -showTabs -======== - -(:ts:`mod.wizards.form.defaults.showTabs`) - -The configuration "showTabs" defines the outermost tabs on the left -side of the form wizard. - -.. figure:: ../../../../Images/FormCreationWizardShowTabs.png - :alt: The form wizard with the main tabs. - -:aspect:`Property:` - showTabs - -:aspect:`Data type:` - string - -:aspect:`Description:` - Comma-separated list of the tabs that will be shown in the wizard. - -:aspect:`Default:` - elements, options, form - - -.. _wizard-settings-defaults-tabs: - -tabs -==== - -(:ts:`mod.wizards.form.defaults.tabs`) - -Each of the 3 tabs can be further customized. - -:aspect:`Property:` - tabs - -:aspect:`Data type:` - [array of objects] - - ->tabs.[tabName] - -:aspect:`Description:` - Configuration for each tab. - - -Example -======= - -.. code-block:: typoscript - - mod.wizards { - form { - defaults { - showTabs = elements, options, form - tabs { - elements { - ... - } - options { - ... - } - form { - ... - } - } - } - } - } - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/ElementsReference/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/ElementsReference/Index.rst deleted file mode 100644 index ba46630a4e4a74431dd17df1da07a472c9d189a9..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/ElementsReference/Index.rst +++ /dev/null @@ -1,41 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _wizard-settings-elements: - -================== -Elements reference -================== - -Overrule the default settings of the :ref:`option <wizard-settings-defaults-options-tab>` -tab for specific element types. - -In the left "settings" part there is a tab called "Options". The contents -of this tab will adapt itself to the selected element type in the form. -If no elements configuration exists, the default settings will be used. - - -.. _overriding-element-settings: - -Overriding element settings -=========================== - -It is possible to override the default option tab settings for each -element individually. This is done by using the same configuration as -in :ts:`mod.wizards.form.defaults.tabs.options`, but using this -configuration in :ts:`mod.wizards.form.elements.[elementName]`. - -The example below will hide all the accordions within the option tab for -a text field (TEXTLINE element), except the filters: - -.. code-block:: typoscript - - mod.wizards.form.elements { - textline { - showAccordions = filters - } - } - -By using this setting you can show or hide accordions, attributes, -validation rules or filters, for each and every individual element. - diff --git a/typo3/sysext/form/Documentation/Administration/WizardSettings/Index.rst b/typo3/sysext/form/Documentation/Administration/WizardSettings/Index.rst deleted file mode 100644 index 403d263bbeeaf65c074470d12c2b600e47a51da0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Administration/WizardSettings/Index.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _wizard-settings: - -=============== -Wizard settings -=============== - -The wizard basically consists of two parts on the screen, the left -"settings" part and the right "form" part. With TSconfig settings it -is possible to configure the contents of the left "settings" part. The -integrator can remove tabs, accordions or a specific setting for a single -type of form element, or for all element types at once. - -The basic configuration has two settings: **defaults** and **elements**. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - DefaultsReference/Index - ElementsReference/Index - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Alphabetic/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Alphabetic/Index.rst deleted file mode 100644 index fe954f8816d8c908b55e98962d9796fe1f064512..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Alphabetic/Index.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-alphabetic: - -========== -alphabetic -========== - -Removes all characters which are not in the range a-z or A-Z. With the -setting allowWhiteSpace, spaces are allowed as well. - - -.. _reference-filters-alphabetic-allowwhitespace: - -allowWhiteSpace -=============== - -:aspect:`Property:` - allowWhiteSpace - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - If allowWhiteSpace = 1, whitespace is allowed in front of, after or - between the characters. - -:aspect:`Default:` - 0 - -[tsref:(cObject).FORM->filters.alphabetic] - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Alphanumeric/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Alphanumeric/Index.rst deleted file mode 100644 index 437e71a2a8f2191e93ad316b10b53e74d1d135f7..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Alphanumeric/Index.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-alphanumeric: - -============ -alphanumeric -============ - -Removes all characters which are not in the range a-z, A-Z or 0-9. With the -setting allowWhiteSpace, spaces are allowed as well. - - -.. _reference-filters-alphanumeric-allowwhitespace: - -allowWhiteSpace -=============== - -:aspect:`Property:` - allowWhiteSpace - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - If allowWhiteSpace = 1, whitespace is allowed in front of, after or - between the characters. - -:aspect:`Default:` - 0 - -[tsref:(cObject).FORM->filters.alphanumeric] - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Currency/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Currency/Index.rst deleted file mode 100644 index 6e85c765e3c0c7a4db1535b6227651166f80fb28..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Currency/Index.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-currency: - -======== -currency -======== - -Changes a number to a formatted version with two decimals. The decimals -point and thousands separator are configurable. - -**Example** - -- Submitted data: 100000.99 - -- Filtered: 100 000,99 - -.. code-block:: typoscript - - filters { - 1 = currency - 1 { - decimalPoint = , - thousandSeparator = space - } - } - - -.. _reference-filters-currency-decimalpoint: - -decimalPoint -============ - -:aspect:`Property:` - decimalPoint - -:aspect:`Data type:` - string - -:aspect:`Description:` - Value for the decimal point, mostly a dot '.' or a comma ',' - -:aspect:`Default:` - . - - -.. _reference-filters-currency-thousandseparator: - -thousandSeparator -================= - -:aspect:`Property:` - thousandSeparator - -:aspect:`Data type:` - string - -:aspect:`Description:` - Value for the thousand separator. - - Special values: - - - **space** : Adds a space as thousand separator - - **none** : No thousand separator - -:aspect:`Default:` - , - -[tsref:(cObject).FORM->filters.currency] - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Digit/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Digit/Index.rst deleted file mode 100644 index 8c3602ee48d5c91e313ed4966693c490e3f26f37..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Digit/Index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-digit: - -===== -digit -===== - -Removes all characters which are not in the range 0-9. - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Index.rst deleted file mode 100644 index 733579287f8eebf8f240caea7b8016a858a5faae..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Index.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _reference-filters: - -Filters -======= - -Add filters to the FORM objects. - -It is possible to have multiple filters for one FORM object, but the filters -have to be added one by one. - -The submitted data for this particular object will be filtered by the -assigned filters in the given order. The filtered data will be shown to the -visitor when there are errors in the form or on a confirmation page. -Otherwise the filtered data will be send by mail to the receiver. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - Alphabetic/Index.rst - Alphanumeric/Index.rst - Currency/Index.rst - Digit/Index.rst - Integer/Index.rst - Lowercase/Index.rst - Regexp/Index.rst - Stripnewlines/Index.rst - Titlecase/Index.rst - Trim/Index.rst - Uppercase/Index.rst - -**Example** - -The example shown below applies two filters to a FORM object. - -- Submitted data: john doe3 - -- Filtered: John Doe - -.. code-block:: typoscript - - filters { - 1 = alphabetic - 1 { - allowWhiteSpace = 1 - } - 2 = titlecase - } - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Integer/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Integer/Index.rst deleted file mode 100644 index a05461bab644adb07d48ea82d4dbcb2f83fea2f1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Integer/Index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-integer: - -======= -integer -======= - -Integers can be specified in decimal (10-based), optionally preceded by a -sign (- or +). - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Lowercase/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Lowercase/Index.rst deleted file mode 100644 index ab78c2374bd956dad6507032afc08e1eb55c46cd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Lowercase/Index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-lowercase: - -========= -lowercase -========= - -Returns the incoming value with all alphabetic characters converted to -lowercase. Alphabetic is determined by the Unicode character properties. - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Regexp/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Regexp/Index.rst deleted file mode 100644 index 2e2bf116940846cd76032d2c518d5e9e503e0b88..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Regexp/Index.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-regexp: - -====== -regexp -====== - -Removes matches in the submitted data found by the defined pattern. - - -.. _reference-filters-regexp-expression: - -expression -========== - -:aspect:`Property:` - expression - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - The pattern holding the characters which need to be deleted. - -[tsref:(cObject).FORM->filters.regexp] - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Stripnewlines/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Stripnewlines/Index.rst deleted file mode 100644 index 943570d5c315883739942ef3678f19c919e20ffb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Stripnewlines/Index.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-stripnewlines: - -============= -stripnewlines -============= - -Convenient for textareas. It removes new lines from the submitted value. - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Titlecase/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Titlecase/Index.rst deleted file mode 100644 index 9f30a8b438d2a0b400cd6505e41be0f80970a0d8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Titlecase/Index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-titlecase: - -========= -titlecase -========= - -Returns the incoming value with all alphabetic characters converted to title -case. Alphabetic is determined by the Unicode character properties. - -**Example** - -- Submitted data: kasper skårhøj - -- Filtered: Kasper Skårhøj - -.. code-block:: typoscript - - filters { - 1 = titlecase - } - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Trim/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Trim/Index.rst deleted file mode 100644 index 6b457f484bcf9cb9a8ca31904a58527c71478857..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Trim/Index.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-trim: - -==== -trim -==== - -Strips characters from the beginning and the end of the submitted value -according to the list of characters. If no character list is set, it will -only trim an ordinary space, a tab, a new line, a carriage return, the -NUL-byte and a vertical tab. - - -.. _reference-filters-trim-characterlist: - -characterList -============= - -:aspect:`Property:` - characterList - -:aspect:`Data type:` - string - -:aspect:`Description:` - List of characters to be trimmed. - - See the PHP-manual (trim) for the options of the charlist. - -[tsref:(cObject).FORM->filters.regexp] - diff --git a/typo3/sysext/form/Documentation/Configuration/Filters/Uppercase/Index.rst b/typo3/sysext/form/Documentation/Configuration/Filters/Uppercase/Index.rst deleted file mode 100644 index b4e7276194d98e02db44965355606724dcd59b11..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Filters/Uppercase/Index.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-filters-uppercase: - -========= -uppercase -========= - -Returns the incoming value with all alphabetic characters converted to -uppercase. Alphabetic is determined by the Unicode character properties. - diff --git a/typo3/sysext/form/Documentation/Configuration/Index.rst b/typo3/sysext/form/Documentation/Configuration/Index.rst deleted file mode 100644 index baeea5914b7a7b9653c3cfa7366d2b9ec7796f1a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Index.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. include:: ../Includes.txt - - -.. _configuration: - -============= -Configuration -============= - -.. only:: html - - .. tip:: - - Whenever there is a reference to anything named an "object" in this - section it is a reference to a "FORM object" and not the "cObjects" - unless it is clearly stated. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - Objects/Index - Layout/Index - Rules/Index - Filters/Index - Postprocessors/Index - diff --git a/typo3/sysext/form/Documentation/Configuration/Layout/Index.rst b/typo3/sysext/form/Documentation/Configuration/Layout/Index.rst deleted file mode 100644 index 92e5b74750b266f3e11c18dbbc12ba8e4719f265..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Layout/Index.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _reference-layout: - -====== -Layout -====== - -.. attention:: - - The form wizard (available in the TYPO3 backend) does not support the - complex layout mechanism described in this chapter. As soon as the - integrator has applied custom layout settings, the form wizard should - not be used anymore. When opening the customized form inside the form - wizard and hitting the "Save" button, all custom layout settings will be - lost. - -Using layout allows the integrator to change the default visual appearance -of the FORM objects. - -The FORM consists of FORM objects, which have their own layout each. The -layout of these objects can be changed for the whole form, for a specific -view or just for a particular object. - -By default, the overall markup is based on ordered lists with list elements -in it, to have a proper layout framework which is also accessible for people -with disabilities. - -Some objects are considered being container objects, as they have child -objects. These objects are FORM, FIELDSET, CHECKBOXGROUP and RADIOGROUP. To -have a proper markup for these objects, nested ordered lists are used. - -**Example** - -.. code-block:: html - - <form> - <ol> - <li> - <fieldset> - <ol> - <li> - <input /> - </li> - </ol> - </fieldset> - </li> - <li> - <input /> - </li> - </ol> - </form> - -It could be stated that SELECT and OPTGROUP elements are container objects -as well, and actually this is correct. They also contain child objects. But -these objects are not allowed to use the above mentioned markup. - -There are 3 ways to modify the layout: - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - LayoutWholeForm/Index - LayoutViewSpecific/Index - LayoutObjectSpecific/Index - diff --git a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutObjectSpecific/Index.rst b/typo3/sysext/form/Documentation/Configuration/Layout/LayoutObjectSpecific/Index.rst deleted file mode 100644 index 84e51101aedbd4c2d189f2e94b41ec4c46901519..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutObjectSpecific/Index.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _change-layout-individual-form: - -=============================================== -Change the layout for an individual FORM object -=============================================== - -It is also possible to override the layout setting of a particular object -within the form, like a checkbox. The layout function within an object only -accepts the markup, like the following one. - -.. code-block:: typoscript - - tt_content.mailform.20 { - 10 = CHECKBOX - 10 { - label = I want to receive the monthly newsletter by email. - layout ( - <input /> - <label /> - ) - } - } - -The example shows how to switch the input field and the label, just for this -particular checkbox. - diff --git a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutViewSpecific/Index.rst b/typo3/sysext/form/Documentation/Configuration/Layout/LayoutViewSpecific/Index.rst deleted file mode 100644 index 30b70de679d638c00568301ce2cbf55c04f95995..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutViewSpecific/Index.rst +++ /dev/null @@ -1,1592 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _change-layout-specific-view: - -===================================== -Change the layout for a specific view -===================================== - -.. contents:: - :local: - :depth: 1 - - -.. _change-layout-specific-view-available-views: - -Available views -=============== - -There are 3 views available: - -form: - This view displays the form with its form fields which can be filled by - the user and submitted. - -confirmation: - If activated, this view shows a confirmation page which has to be - confirmed by the user. - -postProcessor: - The mail postProcessor has its own view for rendering the mail which is - sent to the receiver. - -It is not recommended to change the layout of a FORM object for all views. -For example when customizing the TEXTLINE object the integrator will get -strange results based on the following example: - -.. code-block:: typoscript - - tt_content.mailform.20 { - layout { - textline ( - <div class="form-group"> - <div class="col-sm-3 control-label"> - <label /> - </div> - <div class="col-sm-5"> - <input class="form-control" /> - </div> - </div> - ) - } - } - -The setup shown above changes the appearance of all TEXTLINE objects for all -views. That is, the user will get a confirmation page and a mail with -broken/ senseless input fields instead of the user data. - -In order to only change the TEXTLINE object specific to all of the 3 views, -the following code could be applied. - -.. code-block:: typoscript - - tt_content.mailform.20 { - # customize form view - form { - layout { - textline ( - <div class="form-group"> - <div class="col-sm-3 control-label"> - <label /> - </div> - <div class="col-sm-5"> - <input class="form-control" /> - </div> - </div> - ) - } - } - - # customize confirmation view - confirmation { - layout { - textline ( - <div class="form-group"> - <div class="col-sm-3"> - <strong><label /></strong> - </div> - <div class="col-sm-5"> - <inputvalue /> - </div> - </div> - ) - } - } - - # customize postProcessor/ mail - postProcessor { - layout { - textline ( - <td colspan="2"> - <div class="textline"><inputvalue /></div> - </td> - ) - } - } - } - - -.. _change-layout-specific-view-properties: - -Properties and defaults -======================= - -If the integrator does not define any :ts:`.layout` setting the default -layout defined in the PHP classes will be used. - -The following list shows all available elements within all the different -views including their corresponding default layouts. - -.. contents:: - :local: - :depth: 1 - - -.. _reference-layout-form: - -form -^^^^ - -:aspect:`Property:` - form - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout of the FORM object/ outer wrap. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <form> - <containerWrap /> - </form> - - -.. _reference-layout-confirmation: - -confirmation -^^^^^^^^^^^^ - -:aspect:`Property:` - confirmation - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - confirmation - -:aspect:`Description:` - Layout of the outer wrap. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **confirmation view**: - - .. code-block:: html - - <containerWrap /> - - -.. _reference-layout-html: - -html -^^^^ - -:aspect:`Property:` - html - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - postProcessor - -:aspect:`Description:` - Layout of the outer wrap. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **postProcessor view**: - - .. code-block:: html - - <html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - </head> - <body> - <table cellspacing="0"> - <containerWrap /> - </table> - </body> - </html> - - -.. _reference-layout-containerwrap: - -containerWrap -^^^^^^^^^^^^^ - -:aspect:`Property:` - containerWrap - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Inner wrap for container objects. - - The <elements /> tag will be substituted with all the child elements, - including their element wraps. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <ol> - <elements /> - </ol> - - Default layout **confirmation view**: - - .. code-block:: html - - <ol> - <elements /> - </ol> - - Default layout **postProcessor view**: - - .. code-block:: html - - <tbody> - <elements /> - </tbody> - - -.. _reference-layout-elementwrap: - -elementWrap -^^^^^^^^^^^ - -:aspect:`Property:` - elementWrap - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Outer wrap for regular objects. - - The <element /> tag will be substituted with the child element. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <li> - <element /> - </li> - - Default layout **confirmation view**: - - .. code-block:: html - - <li> - <element /> - </li> - - Default layout **postProcessor view**: - - .. code-block:: html - - <tr> - <element /> - </tr> - - -.. _reference-layout-label: - -label -^^^^^ - -:aspect:`Property:` - label - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the labels. - - The <labelvalue /> tag will be substituted with the label text. - - If available, the <mandatory /> tag will be substituted with the - validation rule message, styled by its own layout. - - If available, the <error /> tag will be substituted with the error - message from the validation rule when the submitted value is not valid. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label> - <labelvalue /> - <mandatory /> - <error /> - </label> - - Default layout **confirmation view**: - - .. code-block:: html - - <label> - <labelvalue /> - </label> - - Default layout **postProcessor view**: - - .. code-block:: html - - <em> - <labelvalue /> - </em> - - -.. _reference-layout-mandatory: - -mandatory -^^^^^^^^^ - -:aspect:`Property:` - mandatory - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the validation rule message to describe the rule. - - The <mandatoryvalue /> tag will be substituted with the validation rule - message. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <em> - <mandatoryvalue /> - </em> - - -.. _reference-layout-error: - -error -^^^^^ - -:aspect:`Property:` - error - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the validation rule error message when the submitted data - does not validate. - - The <errorvalue /> tag will be substituted with the validation rule - error message. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <strong> - <errorvalue /> - </strong> - - -.. _reference-layout-legend: - -legend -^^^^^^ - -:aspect:`Property:` - legend - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the legend. - - The <legendvalue /> tag will be substituted with the legend text. - - If available, the <mandatory /> tag will be substituted with the - validation rule message, styled by its own layout. - - If available, the <error /> tag will be substituted with the error - message from the validation rule when the submitted value is not valid. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <legend> - <legendvalue /> - <mandatory /> - <error /> - </legend> - - Default layout **confirmation view**: - - .. code-block:: html - - <legend> - <legendvalue /> - </legend> - - - Default layout **postProcessor view**: - - .. code-block:: html - - <thead> - <tr> - <th colspan="2" align="left"> - <legendvalue /> - </th> - </tr> - </thead> - - -.. _reference-layout-button: - -button -^^^^^^ - -:aspect:`Property:` - button - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the BUTTON object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - -.. _reference-layout-checkbox: - -checkbox -^^^^^^^^ - -:aspect:`Property:` - checkbox - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the CHECKBOX object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - - -.. _reference-layout-checkboxgroup: - -checkboxgroup -^^^^^^^^^^^^^ - -:aspect:`Property:` - checkboxgroup - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the CHECKBOXGROUP object. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - Default layout **confirmation view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - - -.. _reference-layout-fieldset: - -fieldset -^^^^^^^^ - -:aspect:`Property:` - fieldset - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the FIELDSET object. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - Default layout **confirmation view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - - -.. _reference-layout-fileupload: - -fileupload -^^^^^^^^^^ - -:aspect:`Property:` - fileupload - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the FILEUPLOAD object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - - -.. _reference-layout-hidden: - -hidden -^^^^^^ - -:aspect:`Property:` - hidden - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - postProcessor - -:aspect:`Description:` - Layout for the HIDDEN object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <input /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <em> - <label /> - </em> - </td> - <td> - <inputvalue /> - </td> - - -.. _reference-layout-optgroup: - -optgroup -^^^^^^^^ - -:aspect:`Property:` - optgroup - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the OPTGROUP object. - - The <elements /> tag will be substituted with all the child elements, - which actually can only be OPTION objects. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <optgroup> - <elements /> - </optgroup> - - Default layout **confirmation view**: - - .. code-block:: html - - <elements /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <elements /> - - -.. _reference-layout-option: - -option -^^^^^^ - -:aspect:`Property:` - option - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the OPTION object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <option /> - - Default layout **confirmation view**: - - .. code-block:: html - - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <div> - <inputvalue /> - </div> - - -.. _reference-layout-password: - -password -^^^^^^^^ - -:aspect:`Property:` - password - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the PASSWORD object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - -.. _reference-layout-radio: - -radio -^^^^^ - -:aspect:`Property:` - radio - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the RADIO object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - - -.. _reference-layout-radiogroup: - -radiogroup -^^^^^^^^^^ - -:aspect:`Property:` - radiogroup - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the RADIOGROUP object. - - The <containerwrap /> tag will be substituted by the outer container - wrap and includes all child elements. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - - Default layout **confirmation view**: - - .. code-block:: html - - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - - -.. _reference-layout-reset: - -reset -^^^^^ - -:aspect:`Property:` - reset - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the RESET object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - -.. _reference-layout-select: - -select -^^^^^^ - -:aspect:`Property:` - select - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the SELECT object. - - The <elements /> tag will be substituted with all the child elements, - which only can be OPTGROUP or OPTION objects. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <select> - <elements /> - </select> - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <ol> - <elements /> - </ol> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <label /> - </td> - <td> - <elements /> - </td> - - -.. _reference-layout-submit: - -submit -^^^^^^ - -:aspect:`Property:` - submit - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the SUBMIT object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - -.. _reference-layout-textarea: - -textarea -^^^^^^^^ - -:aspect:`Property:` - textarea - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the TEXTAREA object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <textarea /> - - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;" valign="top"> - <label /> - </td> - <td> - <inputvalue /> - </td> - - -.. _reference-layout-textblock: - -textblock -^^^^^^^^^ - -:aspect:`Property:` - textblock - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - -:aspect:`Description:` - Layout for the TEXTBLOCK object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <textblock /> - - -.. _reference-layout-textline: - -textline -^^^^^^^^ - -:aspect:`Property:` - textline - -:aspect:`Data type:` - string - -:aspect:`Available in views:` - - form - - confirmation - - postProcessor - -:aspect:`Description:` - Layout for the TEXTLINE object. - -:aspect:`Default:` - Default layout **form view**: - - .. code-block:: html - - <label /> - <input /> - - Default layout **confirmation view**: - - .. code-block:: html - - <label /> - <inputvalue /> - - Default layout **postProcessor view**: - - .. code-block:: html - - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - - -.. _change-layout-specific-view-example: - -Example showing all .layout properties and defaults -=================================================== - -The code snippets below shows all available settings across all views -including their default layout. - -.. code-block:: typoscript - - tt_content.mailform.20 { - # ### - # form view - # #### - - form { - layout { - form ( - <form> - <containerWrap /> - </form> - ) - - containerWrap ( - <ol> - <elements /> - </ol> - ) - - elementWrap ( - <li> - <element /> - </li> - ) - - label ( - <label> - <labelvalue /> - <mandatory /> - <error /> - </label> - ) - - mandatory ( - <em> - <mandatoryvalue /> - </em> - ) - - error ( - <strong> - <errorvalue /> - </strong> - ) - - legend ( - <legend> - <legendvalue /> - <mandatory /> - <error /> - </legend> - ) - - button ( - <label /> - <input /> - ) - - checkbox ( - <label /> - <input /> - ) - - checkboxgroup ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - fieldset ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - - fileupload ( - <label /> - <input /> - ) - - hidden ( - <input /> - ) - - optgroup ( - <optgroup> - <elements /> - </optgroup> - ) - - option ( - <option /> - ) - - password ( - <label /> - <input /> - ) - - radio ( - <label /> - <input /> - ) - - radiogroup ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - - reset ( - <label /> - <input /> - ) - - select ( - <label /> - <select> - <elements /> - </select> - ) - - submit ( - <label /> - <input /> - ) - - textarea ( - <label /> - <textarea /> - ) - - textblock ( - <textblock /> - ) - - textline ( - <label /> - <input /> - ) - } - } - - # ### - # confirmation view - # ### - - confirmation { - layout { - confirmation ( - <containerWrap /> - ) - - containerWrap ( - <ol> - <elements /> - </ol> - ) - - elementWrap ( - <li> - <element /> - </li> - ) - - label ( - <label> - <labelvalue /> - </label> - ) - - legend ( - <legend> - <legendvalue /> - </legend> - ) - - checkbox ( - <label /> - <inputvalue /> - ) - - checkboxgroup ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - - fieldset ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - - fileupload ( - <label /> - <inputvalue /> - ) - - optgroup ( - <elements /> - ) - - option ( - <inputvalue /> - ) - - radio ( - <label /> - <inputvalue /> - ) - - radiogroup ( - <fieldset> - <legend /> - <containerWrap /> - </fieldset> - ) - - select ( - <label /> - <ol> - <elements /> - </ol> - ) - - textarea ( - <label /> - <inputvalue /> - ) - - textline ( - <label /> - <inputvalue /> - ) - } - } - - # ### - # postProcesso view - # ### - - postProcessor { - layout { - html ( - <html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - </head> - <body> - <table cellspacing="0"> - <containerWrap /> - </table> - </body> - </html> - ) - - containerWrap ( - <tbody> - <elements /> - </tbody> - ) - - elementWrap ( - <tr> - <element /> - </tr> - ) - - label ( - <em> - <labelvalue /> - </em> - ) - - legend ( - <thead> - <tr> - <th colspan="2" align="left"> - <legendvalue /> - </th> - </tr> - </thead> - ) - - checkbox ( - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - ) - - checkboxgroup ( - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - ) - - fieldset ( - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - ) - - fileupload ( - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - ) - - hidden ( - <td style="width: 200px;"> - <em> - <label /> - </em> - </td> - <td> - <inputvalue /> - </td> - ) - - optgroup ( - <elements /> - ) - - option ( - <div> - <inputvalue /> - </div> - ) - - radio ( - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - ) - - radiogroup ( - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <legend /> - <containerWrap /> - </table> - </td> - ) - - select ( - <td style="width: 200px;"> - <label /> - </td> - <td> - <elements /> - </td> - ) - - textarea ( - <td style="width: 200px;" valign="top"> - <label /> - </td> - <td> - <inputvalue /> - </td> - ) - - textline ( - <td style="width: 200px;"> - <label /> - </td> - <td> - <inputvalue /> - </td> - ) - } - } - } - diff --git a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutWholeForm/Index.rst b/typo3/sysext/form/Documentation/Configuration/Layout/LayoutWholeForm/Index.rst deleted file mode 100644 index 5ee35260eed02084aa36516ca9fb26035c133e1c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Layout/LayoutWholeForm/Index.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _change-layout-of-whole-form: - -=================================== -Change the layout of the whole form -=================================== - -.. attention:: - - It is not recommended to change the layout globally for the whole form. - Unfortunately, using view specific layout settings did not work for a - long time and is now widely used by integrators. - - There are several reasons for not to use global layout settings: - - - Some objects cannot be changed globally. - - Changing some objects will cause problems which lead to failures in - the processing. The code will die with PHP errors. - - Quite often it does not make sense to do these changes globally. - - Instead change the layout for a :ref:`specific view <change-layout-specific-view>`! - -Apart from the above mentioned problems one could change the layout globally -using the following TypoScript setup. Using :ts:`tt_content.mailform.20` -registers the chances for all forms of the below the page tree. If one wants -to change the layout only for a specific form, a TypoScript library could be -build as shown :ref:`here <reference-form-example>`. - -.. code-block:: typoscript - - tt_content.mailform.20 { - layout { - # changing the layout of the form object globally - form ( - <form class="form-class"> - <containerWrap /> - </form> - ) - } - } - -As one can see, an (X)HTML kind of markup is used. Actually it is XML, with -some extra tags like the :ts:`containerWrap`. - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Button/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Button/Index.rst deleted file mode 100644 index 06eec34f78287bf71fe22940ebccefe7730107d3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Button/Index.rst +++ /dev/null @@ -1,158 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-button: - -====== -BUTTON -====== - -Creates a push button. User agents should use the value of the value -attribute as the button's label. - -Push buttons have no default behavior. Each push button may have -client-side scripts associated with the element's event attributes. -When an event occurs (e.g., the user presses the button, releases it, -etc.), the associated script is triggered. - - -.. _reference-button-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-button-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-button-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-button-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-button-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-button-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-button-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-button-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-button-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-button` - specific information. - - -.. _reference-button-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-button-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-button-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-button-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-button-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - button - - -.. _reference-button-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.BUTTON] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Checkbox/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Checkbox/Index.rst deleted file mode 100644 index 3de4a636112d3498123350ee3b9a33654f1e8380..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Checkbox/Index.rst +++ /dev/null @@ -1,169 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-checkbox: - -======== -CHECKBOX -======== - -Creates a checkbox. - -Checkboxes are on/off switches that may be toggled by the user. A switch is -"on" when the control element's checked attribute is set. When a form is -submitted, only "on" checkbox controls can become successful. - -Several checkboxes in a form may share the same control name. Thus, for -example, checkboxes allow users to select several values for the same -property. A CHECKBOX object only displays one checkbox in the form. - - -.. _reference-checkbox-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-checkbox-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-checkbox-checked: - -checked -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-checked`. - - -.. _reference-checkbox-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-checkbox-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-checkbox-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-checkbox-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-checkbox-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-checkbox-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-checkbox-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-checkbox` - specific information. - - -.. _reference-checkbox-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-checkbox-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-checkbox-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-checkbox-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-checkbox-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - checkbox - - -.. _reference-checkbox-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.CHECKBOX] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Fieldset/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Fieldset/Index.rst deleted file mode 100644 index 7884cca96e626a10d633b4816242d31581c26c01..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Fieldset/Index.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-fieldset: - -======== -FIELDSET -======== - -The FIELDSET element allows authors to group thematically related controls -and labels. Grouping controls makes it easier for users to understand the -purpose while simultaneously facilitating tabbing navigation for visual user -agents and speech navigation for speech-oriented user agents. The proper use -of this element makes documents more accessible. - - -.. _reference-fieldset-1-2-3-4: - -1, 2, 3, 4 ... -============== - -:aspect:`Property:` - 1, 2, 3, 4 ... - -:aspect:`Data type:` - [array of FORM objects] - -:aspect:`Description:` - FORM objects that are part of the FIELDSET. - - -.. _reference-fieldset-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-fieldset-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-fieldset-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-fieldset-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-fieldset-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-fieldset` - specific information. - - -.. _reference-fieldset-legend: - -legend -====== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-legend`. - - -.. _reference-fieldset-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - -[tsref:(cObject).FORM.FormObject.FIELDSET] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Fileupload/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Fileupload/Index.rst deleted file mode 100644 index d7490ed27dde5834a5912af72cf6ca4ea9f44061..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Fileupload/Index.rst +++ /dev/null @@ -1,156 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-fileupload: - -========== -FILEUPLOAD -========== - -Creates a file select control. User agents may use the value of the value -attribute as the initial file name. - -This control type allows the user to select files so that their contents may -be submitted with a form. - - -.. _reference-fileupload-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-fileupload-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-fileupload-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-fileupload-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-fileupload-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-fileupload-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-fileupload-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-fileupload-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-fileupload-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-fileupload` - specific information. - - -.. _reference-fileupload-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-fileupload-size: - -size -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-size`. - - -.. _reference-fileupload-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-fileupload-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-fileupload-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-fileupload-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - file - -[tsref:(cObject).FORM.FormObject.FILEUPLOAD] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Form/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Form/Index.rst deleted file mode 100644 index 928d05c5168831a8d1efcfc46dc867ce4bbd3a69..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Form/Index.rst +++ /dev/null @@ -1,313 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-form: - -==== -FORM -==== - -A form will always start with the FORM object. TYPO3 recognizes this object -and sends all TypoScript data to the FORM extension. - - -.. _reference-form-accept: - -accept -====== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accept`. - - -.. _reference-form-accept-charset: - -accept-charset -============== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accept-charset`. - - -.. _reference-form-action: - -action -====== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-action`. - - -.. _reference-form-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-form-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-form-enctype: - -enctype -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-enctype`. - - -.. _reference-form-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-form-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-form-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-form` - specific information. - - -.. _reference-form-method: - -method -====== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-method`. - - -.. _reference-form-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-form-postprocessor: - -postProcessor -============= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-postProcessor`. - - -.. _reference-form-prefix: - -prefix -====== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-prefix`. - - -.. _reference-form-rules: - -rules -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-rules`. - - -.. _reference-form-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-form-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -[tsref:(cObject).FORM] - -.. _reference-form-example: - -Example -======= - -This example shows a simple payment form. At the beginning the layout of the -radio buttons is changed for the form view. The label and the input field -are switched. - -The example builds a form as TypoScript library which can be assigned to a -marker or used inside a fluid template. The defined layout settings are only -valid within this TS library. - -.. code-block:: typoscript - - lib.form = FORM - lib.form { - method = post - - postProcessor { - # ... - } - - form { - layout { - radio ( - <input /> - <label /> - ) - } - } - - 10 = FIELDSET - 10 { - legend = Name - - 10 = SELECT - 10 { - label = Title - - 10 = OPTION - 10 { - data = Mr. - selected = 1 - } - - 20 = OPTION - 20 { - data = Mrs. - } - - 30 = OPTION - 30 { - data = Ms. - } - - 40 = OPTION - 40 { - data = Dr. - } - - 50 = OPTION - 50 { - data = Viscount - } - } - - 20 = TEXTLINE - 20 { - label = First name - } - - 30 = TEXTLINE - 30 { - label = Last name - } - } - - 20 = FIELDSET - 20 { - legend = Address - - 10 = TEXTLINE - 10 { - label = Street - } - - 20 = TEXTLINE - 20 { - label = City - } - - 30 = TEXTLINE - 30 { - label = State - } - - 40 = TEXTLINE - 40 { - label = ZIP code - } - } - - 30 = FIELDSET - 30 { - legend = Payment details - - 10 = FIELDSET - 10 { - legend = Credit card - - 10 = RADIO - 10 { - label = American Express - name = creditcard - } - - 20 = RADIO - 20 { - label = Mastercard - name = creditcard - } - - 30 = RADIO - 30 { - label = Visa - name = creditcard - } - - 40 = RADIO - 40 { - label = Blockbuster Card - name = creditcard - } - } - - 20 = TEXTLINE - 20 { - label = Card number - } - - 30 = TEXTLINE - 30 { - label = Expiry date - } - } - - 40 = SUBMIT - 40 { - value = Submit my details - } - } - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Header/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Header/Index.rst deleted file mode 100644 index 3b8940f963e8228fdafb0b1f946298020df2f9e4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Header/Index.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-header: - -====== -HEADER -====== - -Creates a textual headline wrapped with a headline tag (e.g. h1). This -element can be used for a visual separation or transportation of content. It -is neither displayed on the confirmation page nor in the email. - -.. _reference-header-content: - -content -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-content`. - - -.. _reference-header-headingSize: - -headingSize -=========== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-headingSize`. - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Hidden/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Hidden/Index.rst deleted file mode 100644 index 727c6d6fb6dc49c174c2166ba77f3cd0b00a6484..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Hidden/Index.rst +++ /dev/null @@ -1,100 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-hidden: - -====== -HIDDEN -====== - -Creates a hidden control. - -Authors may create controls that are not rendered (visually) but whose -values are submitted with a form. This control type can generally be used to -store information between client/ server exchanges that would otherwise -be lost due to the stateless nature of HTTP (see [RFC2616]). - - -.. _reference-hidden-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-hidden-filters: - -filters -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-filters`. - - -.. _reference-hidden-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-hidden-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-hidden-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-hidden` - specific information. - - -.. _reference-hidden-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-hidden-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-hidden-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - - -.. _reference-hidden-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.HIDDEN] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Index.rst deleted file mode 100644 index 1ef14fbab5ef4562c5cf529d0c3decf8eb671073..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Index.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _form-objects: - -============ -FORM objects -============ - -The editor is not bound to FORM objects shown below. Whenever FORM will be -put in TypoScript, the contents of this property will be sent to the -FORM plugin. However, one can use regular TYPO3 content objects (cObjects) -as well. This means the integrator has the possibility to add COA, TEXT or -even HMENU in the FORM TypoScript. - -Due to technical limitations it is **not** possible to nest form objects -inside content objects. The following nesting will not work: -:ts:`FORM` > :ts:`COA` > :ts:`TEXTLINE`. - -Furthermore, using cObjects is only allowed when **not** using the form -content element/ wizard in the backend. This is due to security reasons. -The functionality is only available when embedding a form directly in the -TypoScript setup. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - ObjectAttributes/Index - Button/Index - Checkbox/Index - Fieldset/Index - Fileupload/Index - Form/Index - Header/Index - Hidden/Index - Optgroup/Index - Option/Index - Password/Index - Radio/Index - Reset/Index - Select/Index - Submit/Index - Textarea/Index - Textblock/Index - Textline/Index - -============== ================================================= ================================================= ================================================= ================================================= ====================================================== =================================================== -Element BUTTON CHECKBOX FIELDSET FILEUPLOAD FORM HEADER -============== ================================================= ================================================= ================================================= ================================================= ====================================================== =================================================== -accept :ref:`X <reference-objects-attributes-accept>` -accept-charset :ref:`X <reference-objects-attributes-accept-charset>` -accesskey :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` -action :ref:`X <reference-objects-attributes-action>` -alt :ref:`X <reference-objects-attributes-alt>` :ref:`X <reference-objects-attributes-alt>` :ref:`X <reference-objects-attributes-alt>` -checked :ref:`X <reference-objects-attributes-checked>` -class :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` -content :ref:`X <reference-objects-attributes-content>` -cols -data -dir :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` -disabled :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` -enctyp :ref:`X <reference-objects-attributes-enctype>` -filters -headingSize :ref:`X <reference-objects-attributes-headingSize>` -id :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` -label :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` -lang :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` -layout :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` -legend :ref:`X <reference-objects-attributes-legend>` -maxlength -method :ref:`X <reference-objects-attributes-method>` -multiple -name :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` -postProcessor :ref:`X <reference-objects-attributes-postProcessor>` -prefix :ref:`X <reference-objects-attributes-prefix>` -readonly -rows -rules :ref:`X <reference-objects-attributes-rules>` -selected -size :ref:`X <reference-objects-attributes-size>` -src -style :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` -tabindex :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` -title :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` -type :ref:`X <reference-objects-attributes-type>` :ref:`X <reference-objects-attributes-type>` :ref:`X <reference-objects-attributes-type>` -value :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` -============== ================================================= ================================================= ================================================= ================================================= ====================================================== =================================================== - -============== ================================================= ================================================= ================================================= ================================================= ================================================= ================================================= -Element HIDDEN OPTGROUP OPTION PASSWORD RADIO RESET -============== ================================================= ================================================= ================================================= ================================================= ================================================= ================================================= -accept -accept-charset -accesskey :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` -action -alt :ref:`X <reference-objects-attributes-alt>` :ref:`X <reference-objects-attributes-alt>` :ref:`X <reference-objects-attributes-alt>` -checked :ref:`X <reference-objects-attributes-checked>` -class :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` -content -cols -data :ref:`X <reference-objects-attributes-data>` -dir :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` -disabled :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` -enctype -filters :ref:`X <reference-objects-attributes-filters>` :ref:`X <reference-objects-attributes-filters>` -headingSize -id :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` -label :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` -lang :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` -layout :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` :ref:`X <reference-layout>` -legend -maxlength :ref:`X <reference-objects-attributes-maxlength>` -method -multiple -name :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` -postProcessor -prefix -readonly :ref:`X <reference-objects-attributes-readonly>` -rows -rules -selected :ref:`X <reference-objects-attributes-selected>` -size :ref:`X <reference-objects-attributes-size>` -style :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` -tabindex :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` -title :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` -type :ref:`X <reference-objects-attributes-type>` :ref:`X <reference-objects-attributes-type>` :ref:`X <reference-objects-attributes-type>` :ref:`X <reference-objects-attributes-type>` -value :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` -============== ================================================= ================================================= ================================================= ================================================= ================================================= ================================================= - -============== ================================================= ================================================= ================================================= ================================================= ================================================= -Element SELECT SUBMIT TEXTAREA TEXTBLOCK TEXTLINE -============== ================================================= ================================================= ================================================= ================================================= ================================================= -accept -accept-charset -accesskey :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` :ref:`X <reference-objects-attributes-accesskey>` -action -alt :ref:`X <reference-objects-attributes-alt>` :ref:`X <reference-objects-attributes-alt>` -checked -class :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` :ref:`X <reference-objects-attributes-class>` -content :ref:`X <reference-objects-attributes-content>` -cols :ref:`X <reference-objects-attributes-cols>` -data -dir :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` :ref:`X <reference-objects-attributes-dir>` -disabled :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` :ref:`X <reference-objects-attributes-disabled>` -enctype -filters -headingSize -id :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` :ref:`X <reference-objects-attributes-id>` -label :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` :ref:`X <reference-objects-attributes-label>` -lang :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` :ref:`X <reference-objects-attributes-lang>` -layout :ref:`X <reference-layout>` :ref:`X <reference-layout>` -legend -maxlength :ref:`X <reference-objects-attributes-maxlength>` -method -multiple :ref:`X <reference-objects-attributes-multiple>` -name :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` :ref:`X <reference-objects-attributes-name>` -postProcessor -prefix -readonly :ref:`X <reference-objects-attributes-readonly>` :ref:`X <reference-objects-attributes-readonly>` -rows :ref:`X <reference-objects-attributes-rows>` -rules -selected -size :ref:`X <reference-objects-attributes-size>` :ref:`X <reference-objects-attributes-size>` -style :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` :ref:`X <reference-objects-attributes-style>` -tabindex :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` :ref:`X <reference-objects-attributes-tabindex>` -title :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` :ref:`X <reference-objects-attributes-title>` -type :ref:`X <reference-objects-attributes-type>` -value :ref:`X <reference-objects-attributes-value>` :ref:`X <reference-objects-attributes-value>` -============== ================================================= ================================================= ================================================= ================================================= ================================================= - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/ObjectAttributes/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/ObjectAttributes/Index.rst deleted file mode 100644 index a95d2f1d9d52d7851a292db4c753013bc4f69fbb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/ObjectAttributes/Index.rst +++ /dev/null @@ -1,973 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-object-attributes: - -================= -Object Attributes -================= - -.. contents:: - :local: - :depth: 1 - - -.. _reference-objects-attributes-accept: - -accept -====== - -:aspect:`Property:` - accept - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies a comma-separated list of content types that a - server processing this form will handle correctly. - - User agents may use this information to filter out non-conforming files - when prompting a user to select files to be sent to the server (cf. the - INPUT element when type="file"). - - RFC2045: For a complete list, see http://www.iana.org/assignments/media-types/ - - -.. _reference-objects-attributes-accept-charset: - -accept-charset -============== - -:aspect:`Property:` - accept-charset - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies the list of character encodings for input data - that is accepted by the server processing this form. - - The value is a space- and/or comma-delimited list of charset values. - - The client must interpret this list as an exclusive-or list. I.e., the - server is able to accept any single character encoding per entity - received. - - The default value for this attribute is the reserved string "UNKNOWN". - User agents may interpret this value as the character encoding that was - used to transmit the document containing this FORM element. - - RFC2045: For a complete list, see http://www.iana.org/assignments/character-sets/ - - -.. _reference-objects-attributes-accesskey: - -accesskey -========= - -:aspect:`Property:` - accesskey - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute assigns an access key to an element. - - An access key is a single character from the document character set. - - **Note**: Authors should consider the input method of the expected - reader when specifying an accesskey. - - Pressing an access key assigned to an element gives focus to the - element. - - The action that occurs when an element receives focus depends on the - element. For example, when a user activates a link defined by the - element, the user agent generally follows the link. When a user - activates a radio button, the user agent changes the value of the radio - button. When the user activates a text field, it allows input, etc. - - -.. _reference-objects-attributes-action: - -action -====== - -:aspect:`Property:` - action - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies a form processing agent. - - In normal circumstances the action attribute will be filled - automatically, because the form must call the same URI where the form - resides. - - Besides specifying a page uid it is also possible to set an anchor. See - the examples below. - - .. code-block:: typoscript - - action = #anchor - action = 4#anchor - - -.. _reference-objects-attributes-alt: - -alt -=== - -:aspect:`Property:` - alt - -:aspect:`Data type:` - string - -:aspect:`Description:` - For user agents that cannot display images, forms, or applets, this - attribute specifies alternative text. The language of this text is - specified by the lang attribute. - - -.. _reference-objects-attributes-checked: - -checked -======= - -:aspect:`Property:` - checked - -:aspect:`Data type:` - boolean/ checked - -:aspect:`Description:` - When the type attribute has the value "radio" or "checkbox", this - boolean attribute specifies that the button is activated. - - User agents must ignore this attribute for other control types. - - **Examples:** - - .. code-block:: typoscript - - checked = 1 - checked = 0 - checked = checked - - -.. _reference-objects-attributes-class: - -class -===== - -:aspect:`Property:` - class - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute assigns a class name or set of class names to an element. - - Any number of elements may be assigned the same class name or names. - - Multiple class names must be separated by white space characters. - - -.. _reference-objects-attributes-cols: - -cols -==== - -:aspect:`Property:` - cols - -:aspect:`Data type:` - integer - -:aspect:`Description:` - This attribute specifies the visible width. - - Users should be able to enter longer lines than this, so user agents - should provide some means to scroll through the contents of the control - when the contents extend beyond the visible area. User agents may wrap - visible text lines to keep long lines visible without the need for - scrolling. - -:aspect:`Default:` - 40 - - -.. _reference-objects-attributes-content: - -content -======= - -:aspect:`Property:` - content - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute contains the content of a FORM object. - - -.. _reference-objects-attributes-data: - -data -==== - -:aspect:`Property:` - data - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute contains the content of a FORM object. - - -.. _reference-objects-attributes-dir: - -dir -=== - -:aspect:`Property:` - dir - -:aspect:`Data type:` - ltr/ rtl - -:aspect:`Description:` - This attribute specifies the base direction of directionally neutral - text (i.e., text that does not have inherent directionality as defined - in [UNICODE]) in an element's content and attribute values. - - It also specifies the directionality of tables. Possible values: - - - LTR: Left-to-right text or table. - - - RTL: Right-to-left text or table. - - In addition to specifying the language of a document with the lang - attribute, authors may need to specify the base directionality - (left-to-right or right-to-left) of portions of a document's text, of a - table structure, etc. This is done with the dir attribute. - - -.. _reference-objects-attributes-disabled: - -disabled -======== - -:aspect:`Property:` - disabled - -:aspect:`Data type:` - boolean/ disabled - -:aspect:`Description:` - When set for a form control, this boolean attribute disables the control - for user input. - - When set, the disabled attribute has the following effects on an - element: - - - Disabled controls do not receive focus. - - - Disabled controls are skipped in tabbing navigation. - - - Disabled controls cannot be successful. - - This attribute is inherited but local declarations override the - inherited value. - - How disabled elements are rendered depends on the user agent. For - example, some user agents "gray out" disabled menu items, button labels, - etc. - - **Examples:** - - .. code-block:: typoscript - - disabled = 1 - disabled = 0 - disabled = disabled - - -.. _reference-objects-attributes-enctype: - -enctype -======= - -:aspect:`Property:` - enctype - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies the content type used to submit the form to the - server (when the value of method is "post"). The default value for this - attribute is "application/x-www-form-urlencoded". - - The value "multipart/form-data" should be used in combination with the - INPUT element, type="file". - -:aspect:`Default:` - application/x-www-form-urlencoded - - -.. _reference-objects-attributes-filters: - -filters -======= - -:aspect:`Property:` - filters - -:aspect:`Data type:` - [array of numbers] - - ->filters - -:aspect:`Description:` - Add filters to the FORM object. - - This accepts multiple filters for one FORM object, but you have to add - these filters one by one. The submitted data for this particular object - will be filtered by the assigned filters in the given order. - - The filtered data will be shown to the visitor when there are errors in - the form or on a confirmation page. Otherwise the filtered data will be - send by mail to the receiver. - - **Example:** - - .. code-block:: typoscript - - filters { - 1 = alphabetic - 1 ( - allowWhiteSpace = 1 - ) - 2 = titlecase - } - - **Submitted data:** john doe3 - - **Filtered:** John Doe - -:aspect:`Default:` - .. code-block:: typoscript - - filters { - 0 = trim - } - - -.. _reference-objects-attributes-headingSize: - -headingSize -=========== - -:aspect:`Property:` - headingSize - -:aspect:`Data type:` - h1, h2, h3, h4, h5 - -:aspect:`Description:` - This attributes allows to wrap the content of a FORM object with a - headline tag. - -:aspect:`Default:` - h1 - - -.. _reference-objects-attributes-id: - -id -== - -:aspect:`Property:` - id - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute assigns an id to an element. - - This id must be unique in a document. - - If an id has been assigned to the object and a value has been entered - for the label, the "for" attribute will inherit the id. - - **Example for FORM object BUTTON:** - - .. code-block:: html - - <label for="click">Push this button</label> - <input type="button" id="click" value="Click me" /> - - -.. _reference-objects-attributes-label: - -label -===== - -:aspect:`Property:` - label - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - The value of the label of a FORM object. - - By default the value of the label is a TEXT cObject, but you can use - other cObjects as well. When no cObject type is used it assumes you want - to use TEXT. In this case you can assign the value directly to the label - property or indirectly to the value property of the label. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - label = TEXT - label { - value = First name - } - - **Example:** - - .. code-block:: typoscript - - label = First name - - **Example:** - - .. code-block:: typoscript - - label.value = First name - - -.. _reference-objects-attributes-lang: - -lang -==== - -:aspect:`Property:` - lang - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies the base language of an element's attribute - values and text content. The default value of this attribute is unknown. - - Briefly, language codes consist of a primary code and a possibly empty - series of subcodes: - - - language-code = primary-code ( "-" subcode )\* - - Here are some sample language codes: - - - *en*: English - - - *en-US*: the U.S. version of English - - - *en-cockney*: the Cockney version of English - - - *i-navajo*: the Navajo language spoken by some Native Americans - - - *x-klingon*: The primary tag "x" indicates an experimental language tag - - -.. _reference-objects-attributes-layout: - -layout -====== - -:aspect:`Property:` - layout - -:aspect:`Data type:` - string - -:aspect:`Description:` - See general information for :ref:`reference-layout`. - - -.. _reference-objects-attributes-legend: - -legend -====== - -:aspect:`Property:` - legend - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - The value of the legend of a FORM object. - - By default the value of the legend is a TEXT cObject, but you can use - other cObjects as well. When no cObject type is used it assumes you want - to use TEXT. In this case you can assign the value directly to the - legend property or indirectly to the value property of the legend. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - legend = TEXT - legend { - value = Personal information - } - - - **Example:** - - .. code-block:: typoscript - - legend = Personal information - - - **Example:** - - .. code-block:: typoscript - - legend.value = Personal information - - -.. _reference-objects-attributes-maxlength: - -maxlength -========= - -:aspect:`Property:` - maxlength - -:aspect:`Data type:` - integer - -:aspect:`Description:` - This attribute specifies the maximum number of characters the user may - enter. This number may exceed the specified size, in which case the user - agent should offer a scrolling mechanism. The default value for this - attribute is an unlimited number. - - -.. _reference-objects-attributes-method: - -method -====== - -:aspect:`Property:` - method - -:aspect:`Data type:` - post/ get - -:aspect:`Description:` - Specifies which HTTP method will be used to submit form data. - - Only form data submitted with the entered or default method will be - processed. - -:aspect:`Default:` - get - - -.. _reference-objects-attributes-multiple: - -multiple -======== - -:aspect:`Property:` - multiple - -:aspect:`Data type:` - boolean/ multiple - -:aspect:`Description:` - If set, this boolean attribute allows multiple selections. - - If not set, the SELECT element only permits single selections. - - **Examples:** - - .. code-block:: typoscript - - multiple = 1 - multiple = 0 - multiple = multiple - - -.. _reference-objects-attributes-name: - -name -==== - -:aspect:`Property:` - name - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute names the element so that submitted data can be - identified by processing the form server side. - - If no name has been given, it will get assigned an internal counter - together with the prefix, like: - - .. code-block:: html - - <input type="button" name="tx_form[21]" value="click" /> - <input type="checkbox" name="tx_form[22]" value="click" /> - - -.. _reference-objects-attributes-postProcessor: - -postProcessor -============= - -:aspect:`Property:` - postProcessor - -:aspect:`Data type:` - [array of numbers] - -:aspect:`Description:` - Add postprocessors to the FORM. - - This accepts multiple postprocessors for one FORM object, but they have - to be added one by one. - - **Example** : - - .. code-block:: typoscript - - postProcessor { - 1 = mail - 1 { - recipientEmail = bar@foo.org - senderEmail = foo@bar.com - } - } - - -.. _reference-objects-attributes-prefix: - -prefix -====== - -:aspect:`Property:` - prefix - -:aspect:`Data type:` - string - -:aspect:`Description:` - The prefix of the values in the name attributes of the FORM objects. - - <input name=" **prefix** [first\_name]" value="" /> - -:aspect:`Default:` - tx\_form - - -.. _reference-objects-attributes-readonly: - -readonly -======== - -:aspect:`Property:` - readonly - -:aspect:`Data type:` - boolean/ readonly - -:aspect:`Description:` - When set for a form control, this boolean attribute prohibits changes to - the control. - - The readonly attribute specifies whether the control may be modified by - the user. - - When set, the readonly attribute has the following effects on an - element: - - - Read-only elements receive focus but cannot be modified by the user. - - - Read-only elements are included in tabbing navigation. - - - Read-only elements may be successful. - - How read-only elements are rendered depends on the user agent. - - **Examples:** - - .. code-block:: html - - readonly = 1 - readonly = 0 - readonly = disabled - - **Note**: The only way to modify dynamically the value of the readonly - attribute is through a script. - - -.. _reference-objects-attributes-rows: - -rows -==== - -:aspect:`Property:` - rows - -:aspect:`Data type:` - integer - -:aspect:`Description:` - This attribute specifies the number of visible text lines. - - Users should be able to enter more lines than this, so user agents - should provide some means to scroll through the contents of the control - when the contents extend beyond the visible area. - -:aspect:`Default:` - 5 - - -.. _reference-objects-attributes-rules: - -rules -===== - -:aspect:`Property:` - rules - -:aspect:`Data type:` - [array of numbers] - -:aspect:`Description:` - Add validation rules to the FORM. - - This accepts multiple validation rules for one FORM object, but the - rules have to be added one by one. It is also possible to add validation - rules for different FORM objects. - - **Example:** - - .. code-block:: typoscript - - rules { - 1 = required - 1 { - element = first_name - } - 2 = required - 2 { - element = last_name - showMessage = 0 - error = TEXT - error { - value = Please enter your last name - } - } - } - - Validation rules are a powerful tool to add validation to the form. - Please take a look at the rules section in this manual. - - -.. _reference-objects-attributes-selected: - -selected -======== - -:aspect:`Property:` - selected - -:aspect:`Data type:` - boolean/ selected - -:aspect:`Description:` - When set, this boolean attribute specifies that a option is pre- - selected. - - **Examples:** - - .. code-block:: typoscript - - selected = 1 - selected = 0 - selected = selected - - -.. _reference-objects-attributes-size: - -size -==== - -:aspect:`Property:` - size - -:aspect:`Data type:` - integer - -:aspect:`Description:` - This attribute tells the user agent the initial width of the control. - The size has to be entered as integer without any measuring unit. - - -.. _reference-objects-attributes-src: - -src -=== - -:aspect:`Property:` - src - -:aspect:`Data type:` - imgResource - -:aspect:`Description:` - This attribute specifies the location of the image to be used to - decorate the graphical submit button. GIFBUILDER objects are not - allowed. - - -.. _reference-objects-attributes-style: - -style -===== - -:aspect:`Property:` - style - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute specifies CSS style information for the current element. - - -.. _reference-objects-attributes-tabindex: - -tabindex -======== - -:aspect:`Property:` - tabindex - -:aspect:`Data type:` - integer - -:aspect:`Description:` - This attribute specifies the position of the current element in the - tabbing order for the current document. This value must be a number - between 0 and 32767. User agents should ignore leading zeros. - - The tabbing order defines the order in which elements will receive focus - when navigated by the user via the keyboard. The tabbing order may - include elements nested within other elements. - - Elements that may receive focus should be navigated by user agents - according to the following rules: - - #. Those elements that support the tabindex attribute and assign a - positive value to it are navigated first. Navigation proceeds from - the element with the lowest tabindex value to the element with the - highest value. Values neither need to be sequential nor must begin - with any particular value. Elements that have identical tabindex - values should be navigated in the order they appear in the character - stream. - - #. Those elements that do not support the tabindex attribute or support - it and assign it a value of "0" are navigated next. These elements - are navigated in the order they appear in the character stream. - - #. Elements that are disabled do not participate in the tabbing order. - - The actual key sequence that causes tabbing navigation or element - activation depends on the configuration of the user agent (e.g., the - "tab" key is used for navigation and the "enter" key is used to activate - a selected element), - - User agents may also define key sequences to navigate the tabbing order - in reverse. When the end (or beginning) of the tabbing order is reached, - user agents may circle back to the beginning (or end). - - -.. _reference-objects-attributes-title: - -title -===== - -:aspect:`Property:` - title - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute offers advisory information about the element for which - it is set. Unlike the TITLE element, which provides information about an - entire document and may only appear once, the title attribute may - annotate any number of elements. Please consult an element's definition - to verify that it supports this attribute. - - Values of the title attribute may be rendered by user agents in a - variety of ways. For instance, visual browsers frequently display the - title as a "tool tip" (a short message that appears when the pointing - device pauses over an object). Audio user agents may speak the title - information in a similar context. - - -.. _reference-objects-attributes-type: - -type -==== - -:aspect:`Property:` - type - -:aspect:`Data type:` - string - -:aspect:`Description:` - Defines the type of form input control to create. - - -.. _reference-objects-attributes-value: - -value -===== - -:aspect:`Property:` - value - -:aspect:`Data type:` - string - -:aspect:`Description:` - This attribute assigns the initial value to the object. - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Optgroup/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Optgroup/Index.rst deleted file mode 100644 index 5a9e74266d96857239656fb5b5843810da21b098..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Optgroup/Index.rst +++ /dev/null @@ -1,110 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-optgroup: - -======== -OPTGROUP -======== - -The OPTGROUP element allows authors to group choices logically. This is -particularly helpful when the user must choose from a long list of options; -groups of related choices are easier to grasp and remember than a single -long list of options. All OPTGROUP elements must be specified directly -within a SELECT element (i.e., groups may not be nested). - -An OPTGROUP object can only exist between a SELECT object. - - -.. _reference-optgroup-1-2-3-4: - -1, 2, 3, 4 ... -============== - -:aspect:`Property:` - 1, 2, 3, 4 ... - -:aspect:`Data type:` - [array of FORM objects] - -:aspect:`Description:` - OPTION objects, part of the OPTGROUP - - -.. _reference-optgroup-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-optgroup-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-optgroup-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-optgroup-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - -:aspect:`Default:` - optgroup - - -.. _reference-optgroup-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-optgroup-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-optgroup` - specific information. - - -.. _reference-optgroup-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-optgroup-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - -[tsref:(cObject).FORM.FormObject.OPTGROUP] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Option/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Option/Index.rst deleted file mode 100644 index 6db85eedc0f2d235bc03e129da85a29807ea4534..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Option/Index.rst +++ /dev/null @@ -1,115 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-option: - -====== -OPTION -====== - -Defines an element inside a select/ drop-down list. - -An OPTION object can only exist "between" a SELECT or OPTGROUP object. - - -.. _reference-option-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-option-data: - -data -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-data`. - - -.. _reference-option-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-option-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-option-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-option-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-option-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-option` - specific information. - - -.. _reference-option-selected: - -selected -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-selected`. - - -.. _reference-option-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-option-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-option-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.OPTION] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Password/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Password/Index.rst deleted file mode 100644 index be61de88fc218be9c989fce61ab28f1d9ea04159..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Password/Index.rst +++ /dev/null @@ -1,198 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-password: - -======== -PASSWORD -======== - -Creates a single-line text input control, but the input text is rendered in -such a way as to hide the characters (e.g., a series of asterisks). This -control type is often used for sensitive input such as passwords. Note that -the current value is the text entered by the user, not the text rendered by -the user agent. - -**Note** . Form designers should note that this mechanism affords only light -security protection. Although the password is masked by user agents from -casual observers, it is transmitted to the server in clear text, and may be -read by anyone with low-level access to the network. - - -.. _reference-password-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-password-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-password-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-password-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-password-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-password-filters: - -filters -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-filters`. - - -.. _reference-password-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-password-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-password-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - tag - - -.. _reference-password-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-password` - specific information. - - -.. _reference-password-maxlength: - -maxlength -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-maxlength`. - - -.. _reference-password-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-password-readonly: - -readonly -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-readonly`. - - -.. _reference-password-size: - -size -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-size`. - - -.. _reference-password-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-password-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-password-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-password-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - password - - -.. _reference-password-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.PASSWORD] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Radio/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Radio/Index.rst deleted file mode 100644 index ce3df5edd327f03c120483602fe9c786f99f676d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Radio/Index.rst +++ /dev/null @@ -1,190 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-radio: - -===== -RADIO -===== - -Creates a radio button. - -Radio buttons are on/ off switches that may be toggled by the user. A switch -is "on" when the control element's checked attribute is set. When a form is -submitted, only "on" radio button controls can become successful. - -Several radio buttons in a form may share the same control name. Thus, for -example, radio buttons allow users to select several values for the same -property. - -Radio buttons are like checkboxes except that when several share the same -control name, they are mutually exclusive: when one is switched "on", all -others with the same name are switched "off". - -Radio buttons are normally grouped in a FIELDSET object. - -**Note from W3C for user agent behaviour**: If no radio button in a set -sharing the same control name is initially "on", user agent behavior for -choosing which control is initially "on" is undefined. - -**Note**: Since existing implementations handle this case differently, the -current specification differs from RFC 1866 ([RFC1866] section 8.1.2.4), -which states: - -At all times, exactly one of the radio buttons in a set is checked. If -none of the elements of a set of radio buttons specifies \`checked', -then the user agent must check the first radio button of the set initially. - -Since user agent behavior differs, authors should ensure that in each set of -radio buttons that one is initially "on". - - -.. _reference-radio-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-radio-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-radio-checked: - -checked -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-checked`. - - -.. _reference-radio-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-radio-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-radio-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-radio-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-radio-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-radio-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-radio-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-radio` - specific information. - - -.. _reference-radio-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-radio-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-radio-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-radio-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-radio-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - radio - - -.. _reference-radio-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.RADIO] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Reset/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Reset/Index.rst deleted file mode 100644 index 6854cdd9772da0788389f67244d59d2d0a26bc86..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Reset/Index.rst +++ /dev/null @@ -1,154 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-reset: - -===== -RESET -===== - -Creates a reset button. - -When activated, a reset button resets all controls to their initial values. - - -.. _reference-reset-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-reset-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-reset-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-reset-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-reset-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-reset-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-reset-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-reset-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-reset-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-reset` - specific information. - - -.. _reference-reset-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-reset-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-reset-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-reset-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-reset-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - -:aspect:`Default:` - reset - - -.. _reference-reset-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.RESET] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Select/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Select/Index.rst deleted file mode 100644 index 314b2119397d8adf9d529d14eafe8acd60618e78..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Select/Index.rst +++ /dev/null @@ -1,165 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-select: - -====== -SELECT -====== - -The SELECT object creates a menu. Each choice offered by the menu is -represented by an OPTION object. A SELECT object must contain at least one -OPTION object - -**Pre-selected options** - -Zero or more choices may be pre-selected for the user. User agents should -determine which choices are pre-selected as follows: - -- If no OPTION object has the selected attribute set, user agent behavior - for choosing which option is initially selected is undefined. - **Note**: Since existing implementations handle this case differently, the - current specification differs from RFC 1866 ([RFC1866] section 8.1.3), - which states: The initial state has the first option selected, unless a - SELECTED attribute is present on any of the <OPTION> elements. Since user - agent behavior differs, one should ensure that each menu includes a - default pre-selected OPTION. - -- If one OPTION object has the selected attribute set, it should be pre- - selected. - -- If the SELECT object has the multiple attribute set and more than one - OPTION object has the selected attribute set, they should all be pre- - selected. - -- It is considered an error if more than one OPTION object has the selected - attribute set and the SELECT object does not have the multiple attribute - set. User agents may vary in how they handle this error, but should not - pre-select more than one choice. - - -.. _reference-select-1-2-3-4: - -1, 2, 3, 4 ... -============== - -:aspect:`Property:` - 1, 2, 3, 4 ... - -:aspect:`Data type:` - [array of FORM objects] - -:aspect:`Description:` - OPTION and/ or OPTGROUP objects, part of the SELECT. - - -.. _reference-select-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-select-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-select-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-select-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-select-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-select-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-select` - specific information. - - -.. _reference-select-multiple: - -multiple -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-multiple`. - - -.. _reference-select-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-select-size: - -size -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-size`. - - -.. _reference-select-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-select-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-select-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - -[tsref:(cObject).FORM.FormObject.SELECT] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Submit/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Submit/Index.rst deleted file mode 100644 index e7dc89d511cdbc5dfcd9e1f8ea20800f9893fc47..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Submit/Index.rst +++ /dev/null @@ -1,152 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-submit: - -====== -SUBMIT -====== - -Creates a submit button. - -When activated, a submit button submits a form. A form may contain more than -one submit button. - - -.. _reference-submit-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-submit-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-submit-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-submit-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-submit-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-submit-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-submit-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-submit-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-submit-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-submit` - specific information. - - -.. _reference-submit-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-submit-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-submit-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-submit-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-submit-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - - -.. _reference-submit-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.SUBMIT] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Textarea/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Textarea/Index.rst deleted file mode 100644 index 2c731ec92e4d0241314a996da6c3b9632db51a02..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Textarea/Index.rst +++ /dev/null @@ -1,169 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-textarea: - -======== -TEXTAREA -======== - -The TEXTAREA object creates a multi-line text input control. User agents -should use the contents of this object as the initial value of the control -and should render this text initially. - - -.. _reference-textarea-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-textarea-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-textarea-cols: - -cols -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-cols`. - - -.. _reference-textarea-data: - -data -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-data`. - - -.. _reference-textarea-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-textarea-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-textarea-filters: - -filters -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-filters`. - - -.. _reference-textarea-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-textarea-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-textarea-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-textarea-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-textarea` - specific information. - - -.. _reference-textarea-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-textarea-readonly: - -readonly -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-readonly`. - - -.. _reference-textarea-rows: - -rows -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-rows`. - - -.. _reference-textarea-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-textarea-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex`. - - -.. _reference-textarea-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - -[tsref:(cObject).FORM.FormObject.TEXTAREA] - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Textblock/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Textblock/Index.rst deleted file mode 100644 index e3e219c4459f9301437623357ff2a3e36b80e1cc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Textblock/Index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-textblock: - -========= -TEXTBLOCK -========= - -Creates a block of text. This element can be used for a visual separation or -transportation of content. It is neither displayed on the confirmation page -nor in the email. - - -.. _reference-textblock-content: - -content -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-content`. - diff --git a/typo3/sysext/form/Documentation/Configuration/Objects/Textline/Index.rst b/typo3/sysext/form/Documentation/Configuration/Objects/Textline/Index.rst deleted file mode 100644 index 905f9a850437d13edf2094ba9b1b9b3b637f4369..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Objects/Textline/Index.rst +++ /dev/null @@ -1,185 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-textline: - -======== -TEXTLINE -======== - -Creates a single-line text input control. - - -.. _reference-textline-accesskey: - -accesskey -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-accesskey`. - - -.. _reference-textline-alt: - -alt -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-alt`. - - -.. _reference-textline-class: - -class -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-class`. - - -.. _reference-textline-dir: - -dir -=== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-dir`. - - -.. _reference-textline-disabled: - -disabled -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-disabled`. - - -.. _reference-textline-filters: - -filters -======= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-filters`. - - -.. _reference-textline-id: - -id -== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-id`. - - -.. _reference-textline-label: - -label -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-label`. - - -.. _reference-textline-lang: - -lang -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-lang`. - - -.. _reference-textline-layout: - -layout -====== - -:aspect:`Description:` - See general information for :ref:`reference-layout` and the :ref:`reference-layout-textline` - specific information. - - -.. _reference-textline-maxlength: - -maxlength -========= - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-maxlength`. - - -.. _reference-textline-name: - -name -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-name`. - - -.. _reference-textline-readonly: - -readonly -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-readonly`. - - -.. _reference-textline-size: - -size -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-size`. - - -.. _reference-textline-style: - -style -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-style`. - - -.. _reference-textline-tabindex: - -tabindex -======== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-tabindex` - - -.. _reference-textline-title: - -title -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-title`. - - -.. _reference-textline-type: - -type -==== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-type`. - - -.. _reference-textline-value: - -value -===== - -:aspect:`Description:` - See general information for :ref:`reference-objects-attributes-value`. - -[tsref:(cObject).FORM.FormObject.TEXTLINE] - diff --git a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Index.rst b/typo3/sysext/form/Documentation/Configuration/Postprocessors/Index.rst deleted file mode 100644 index 10ecace040e3a8d76c8180a2416fc89943b27dad..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Index.rst +++ /dev/null @@ -1,61 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _reference-postprocessors: - -============== -postProcessors -============== - -Add postProcessors to the FORM. - -postProcessors define how TYPO3 processes submitted forms after the form is -rendered according to filters and rules. - -Multiple postProcessors are accepted for one FORM object, but you have to -add these postProcessors one by one. - -Currently there are two postProcessors: - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - Mail/Index.rst - Redirect/Index.rst - -The processing will be done in the order of the postProcessors. - -Custom postProcessors -===================== - -It is also possible to configure a custom class as a postProcessor. Just use -the class name as the postProcessor name. -The postProcessor class should implement `TYPO3\CMS\Form\PostProcess\PostProcessorInterface` - -The custom postProcessor is not available within the form wizard. Currently, -there is no possibility to extend the wizard. - -**Example:** - -.. code-block:: typoscript - - postProcessor { - 1 = mail - 1 { - recipientEmail = bar@foo.org - senderEmail = foo@bar.com - subject = Baz - } - - 2 = redirect - 2 { - destination = 5 - } - - 3 = Vendor\ExtensionName\Folder\ClassName - 3 { - } - } - diff --git a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Mail/Index.rst b/typo3/sysext/form/Documentation/Configuration/Postprocessors/Mail/Index.rst deleted file mode 100644 index 2ecf92029cfd3e9e9aa9a71704b162162834c12a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Mail/Index.rst +++ /dev/null @@ -1,321 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-postprocessors-mail: - -==== -mail -==== - -The mail postProcessor sends submitted data by mail. - -.. _reference-postProcessor-mail-mail: - -Mail -==== - -Configuration options for the mail to deliver. - - -.. _reference-postprocessors-mail-ccemail: - -ccEmail -------- - -:aspect:`Property:` - ccEmail - -:aspect:`Data type:` - string - -:aspect:`Description:` - Email address the submitted data is sent to as a carbon copy. - - -.. _reference-postprocessors-mail-organization: - -organization ------------- - -:aspect:`Property:` - organization - -:aspect:`Data type:` - string - -:aspect:`Description:` - Organization mail header. - - -.. _reference-postprocessors-mail-priority: - -priority --------- - -:aspect:`Property:` - priority - -:aspect:`Data type:` - integer - -:aspect:`Description:` - Priority of the email. Integer value between 1 and 5. If the priority is - configured, but too high, it will be set to 5, which means very low - priority. - -:aspect:`Default:` - 3 - - -.. _reference-postprocessors-mail-recipientemail: - -recipientEmail --------------- - -:aspect:`Property:` - recipientEmail - -:aspect:`Data type:` - string - -:aspect:`Description:` - Email address the submitted data is sent to. - - -.. _reference-postprocessors-mail-senderemail: - -senderEmail ------------ - -:aspect:`Property:` - senderEmail - -:aspect:`Data type:` - string - -:aspect:`Description:` - Email address which is shown as sender of the email (from header). - -:aspect:`Default:` - TYPO3\_CONF\_VARS['MAIL']['defaultMailFromAddress'] - - -.. _reference-postprocessors-mail-senderemailfield: - -senderEmailField ----------------- - -:aspect:`Property:` - senderEmailField - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the form field which holds the sender's email address (from - header). - - Normally, you can find the (filtered) name in the HTML output between - the square brackets like tx\_form[name] where name is the name of the - object. - - Only used if senderEmail is not set. - - -.. _reference-postprocessors-mail-sendername: - -senderName ----------- - -:aspect:`Property:` - senderName - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name which is shown as sender of the email (from header). - -:aspect:`Default:` - TYPO3\_CONF\_VARS['MAIL']['defaultMailFromName'] - - -.. _reference-postprocessors-mail-sendernamefield: - -senderNameField ---------------- - -:aspect:`Property:` - senderNameField - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the form field which holds the sender's name (from header). - - Normally you can find the (filtered) name in the HTML output between the - square brackets like tx\_form[name] where name is the name of the - object. - - Only used if senderName is not set. - - -.. _reference-form-subject: - -subject -------- - -:aspect:`Property:` - subject - -:aspect:`Data type:` - string - -:aspect:`Description:` - Subject of the email sent by the form. - -:aspect:`Default:` - Formmail on 'Your\_HOST' - - -.. _reference-postprocessors-mail-subjectfield: - -subjectField ------------- - -:aspect:`Property:` - subjectField - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the form field which holds the subject. - - Normally you can find the (filtered) name in the HTML output between the - square brackets like tx\_form[name] where name is the name of the - object. - - Only used if subject is not set. - -[tsref:(cObject).FORM->postProcessor.mail] - - -.. _reference-postprocessors-mail-htmlMailTemplatePath: - -htmlMailTemplatePath --------------------- - -:aspect:`Property:` - htmlMailTemplatePath - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the template to use for HTML-Content. - - Default is `Html`. Useful to use multiple Mail Postprocessors with different templates. - - -.. _reference-postprocessors-mail-plaintextMailTemplatePath: - -plaintextMailTemplatePath -------------------------- - -:aspect:`Property:` - plaintextMailTemplatePath - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the template to use for Plaintext-Content. - - Default is `Plain`. Useful to use multiple Mail Postprocessors with different templates. - -.. _reference-postProcessor-mail-messages: - -Messages -======== - -.. _reference-postprocessors-mail-messages-error: - -messages.error --------------- - -:aspect:`Property:` - messages.error - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - Overriding the default text of the error message, describing the error. - - When no cObject type is set, the message is a simple string. The value - can directly be assigned to the messages.error property. If one needs - the functionality of cObjects, just define the message appropriately. - Any cObject is allowed. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - messages.error = TEXT - messages.error { - data = LLL:EXT:theme/Resources/Private/Language/Form/locallang.xlf:messagesError - } - - **Example:** - - .. code-block:: typoscript - - messages.error = Error while submitting form - -:aspect:`Description:` - *Local language:*"There was an error when sending the form by mail" - - -.. _reference-postprocessors-mail-messages-success: - -messages.success ----------------- - -:aspect:`Property:` - messages.success - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - Overriding the default text of the confirmation message. - - When no cObject type is set, the message is a simple string. The value - can directly be assigned to the messages.success property. If one needs - the functionality of cObjects, just define the message appropriately. - Any cObject is allowed. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - messages.success = TEXT - messages.success { - data = LLL:EXT:theme/Resources/Private/Language/Form/locallang.xlf:messagesSuccess - } - - **Example:** - - .. code-block:: typoscript - - messages.success = Thanks for submitting - -:aspect:`Default:` - *Local language:*"The form has been sent successfully by mail" - diff --git a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Redirect/Index.rst b/typo3/sysext/form/Documentation/Configuration/Postprocessors/Redirect/Index.rst deleted file mode 100644 index 6fabe9d06b5d33170845051428d1718327b5d368..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Postprocessors/Redirect/Index.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-postprocessors-redirect: - -======== -redirect -======== - -The redirect postProcessor redirects the user to a defined destination. - -.. _reference-postprocessors-redirect-destination: - -destination -=========== - -:aspect:`Property:` - destination - -:aspect:`Data type:` - string - -:aspect:`Description:` - One can supply a uid of a page (e.g. 5) or a url (e.g. www.typo3.org). - The user will be redirected to this destination. - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Alphabetic/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Alphabetic/Index.rst deleted file mode 100644 index 2f05287cfff00f901d26a734aa2c9388ea492106..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Alphabetic/Index.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-alphabetic: - -========== -alphabetic -========== - -Checks if the submitted value only has the characters a-z or A-Z. - - -.. _reference-rules-alphabetic-allowwhitespace: - -allowWhiteSpace -=============== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-allowwhitespace`. - - -.. _reference-rules-alphabetic-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-alphabetic-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value contains not only alphabetic characters" - - -.. _reference-rules-alphabetic-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - For this specific rule the default message consists of two parts, the - second one will only be added when **allowWhiteSpace** is set. This - functionality is not possible when defining an own message as shown - below. - -:aspect:`Default:` - *local language:*"Use alphabetic characters(, whitespace allowed)" - - -.. _reference-rules-alphabetic-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.alphabetic] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Alphanumeric/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Alphanumeric/Index.rst deleted file mode 100644 index e3b8151170231de9cbc291e5808b598b2e181ef2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Alphanumeric/Index.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-alphanumeric: - -============ -alphanumeric -============ - -Checks if the submitted value only has the characters a-z, A-Z or 0-9. - - -.. _reference-rules-alphanumeric-allowwhitespace: - -allowWhiteSpace -=============== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-allowwhitespace`. - - -.. _reference-rules-alphanumeric-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-alphanumeric-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value contains not only alphanumeric characters" - - -.. _reference-rules-alphanumeric-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - For this specific rule the default message consists of two parts, the - second one will only be added when **allowWhiteSpace** is set. This - functionality is not possible when defining an own message as shown - below. - -:aspect:`Default:` - *local language:*"Use alphanumeric characters(, whitespace allowed)" - - -.. _reference-rules-alphanumeric-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.alphanumeric] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Between/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Between/Index.rst deleted file mode 100644 index 4a848cf4c17addd289f2a91c66b8a8a67f2ba2cb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Between/Index.rst +++ /dev/null @@ -1,122 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-between: - -======= -between -======= - -Checks if the submitted value is between the given minimum and maximum -value. By default, minimum and maximum are excluded, but can be included in -the validation. - - -.. _reference-rules-between-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-between-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - - For this specific rule the default error message consists of two parts, - the second one will only be added when **inclusive** is set. This - functionality is not possible when defining an own message as shown - below. - The markers %minimum and %maximum will be replaced with the values set - by TypoScript. - -:aspect:`Default:` - *local language:*"The value is not between %minimum and %maximum(, - inclusively)" - - -.. _reference-rules-between-inclusive: - -inclusive -========= - -:aspect:`Property:` - inclusive - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - If inclusive = 1, the minimum and maximum value are included in the - comparison. - -:aspect:`Default:` - 0 - - -.. _reference-rules-between-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - For this specific rule the default message consists of two parts, the - second one will only be added when **inclusive** is set. This - functionality is not possible when defining an own message as shown - below. - The markers %minimum and %maximum will be replaced with the values set - by TypoScript. - -:aspect:`Default:` - *local language:*"The value must be between %minimum and %maximum(, - inclusively)" - - -.. _reference-rules-between-maximum: - -maximum -======= - -:aspect:`Property:` - maximum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The maximum value of the comparison. - - -.. _reference-rules-between-minimum: - -minimum -======= - -:aspect:`Property:` - minimum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The minimum value of the comparison. - - -.. _reference-rules-between-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.between] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Date/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Date/Index.rst deleted file mode 100644 index 4781cc3a4287ad9ac7dd9fea4f6e2786caffe0af..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Date/Index.rst +++ /dev/null @@ -1,85 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-date: - -==== -date -==== - -Checks if the submitted value is a valid date, and the format is equal to -the one set in TypoScript. - -The format configuration is like the PHP strftime() conversion specifiers. -The message shown to the visitor supports the format as well, but will be -shown to the visitor in a human readable way. -%e-%m-%Y becomes d-mm-yyyy in English. - - -.. _reference-rules-date-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-date-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be a valid date" - - -.. _reference-rules-date-format: - -format -====== - -:aspect:`Property:` - format - -:aspect:`Data type:` - strftime-conf - -:aspect:`Description:` - The format of the submitted data. - - See the PHP-manual (strftime) for the codes, or datatype "strftime-conf" - in the TYPO3 document TSref. - -:aspect:`Default:` - %e-%m-%Y - - -.. _reference-rules-date-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - The %format marker will be replaced with a human readable format. - %e-%m-%Y becomes d-mm-yyyy in English. - -:aspect:`Default:` - *local language:*"(%format)" - - -.. _reference-rules-date-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.date] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Digit/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Digit/Index.rst deleted file mode 100644 index 3aedee4d27f97ce4833821bcb96f3dd38237258c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Digit/Index.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-digit: - -===== -digit -===== - -Checks if the submitted value only has the characters 0-9. - - -.. _reference-rules-digit-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-digit-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value contains not only digit characters" - - -.. _reference-rules-digit-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Use digit characters" - - -.. _reference-rules-digit-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.digit] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Email/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Email/Index.rst deleted file mode 100644 index fdd51d558344e784416d82eab15738b34eeb544d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Email/Index.rst +++ /dev/null @@ -1,60 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-email: - -===== -email -===== - -Checks if the submitted value is a valid email address. - -Validates an RFC 2822 email address, except does not allow most punctuation -and non-ascii alphanumeric characters. Also does not take length -requirements into account. Allows domain name and IP addresses, and ensures -that the IP address entered is valid. - - -.. _reference-rules-email-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-email-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"This is not a valid email address" - - -.. _reference-rules-email-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"(john.doe@domain.com)" - - -.. _reference-rules-email-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.email] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Equals/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Equals/Index.rst deleted file mode 100644 index ec82581fefa2cbac69dbdde7d0e38833ee8e408f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Equals/Index.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-equals: - -====== -equals -====== - -Compares the submitted data of two FORM objects. If they are not equal, the -rule does not validate. - -The rule and error messages will be put in the label of the object the rule -is attached with by the property "element". - - -.. _reference-rules-equals-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-equals-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - - The %field marker will be replaces with the property "field". - -:aspect:`Default:` - *local language:*"The value does not equal the value in field '%field'" - - -.. _reference-rules-equals-field: - -field -===== - -:aspect:`Property:` - field - -:aspect:`Data type:` - string - -:aspect:`Description:` - The name of the object to compare with. - - See explanation of "element" property. - - -.. _reference-rules-equals-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - The %field marker will be replaces with the property "field". - -:aspect:`Default:` - *local language:*"This field must be equal to '%field'" - - -.. _reference-rules-equals-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.equals] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Float/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Float/Index.rst deleted file mode 100644 index 97f02d75c6dc0c4ff9030c48198a13f507a0b1e2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Float/Index.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-float: - -===== -float -===== - -Checks if the submitted value is a floating point number (aka floats, -doubles or real numbers). - -Float depends on your config.locale\_all setting. For German -(config.locale\_all = de\_DE) one will get the following values (partly) -with the PHP function localeconv(): - -- 'decimal\_point' => string '.' Decimal point character -- 'thousands\_sep' => string '' Thousands separator -- 'mon\_decimal\_point' => string ',' Monetary decimal point character -- 'mon\_thousands\_sep' => string '.' Monetary thousands separator - -First both thousands separators are deleted from the float, then the decimal -points are replaced by a dot to get a proper float which PHP can handle -properly. - - -.. _reference-rules-float-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-float-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be a float" - - -.. _reference-rules-float-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Enter a float" - - -.. _reference-rules-float-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.float] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Greaterthan/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Greaterthan/Index.rst deleted file mode 100644 index e2d7574e3e97d54f9eb8cf63abf5877196a71d5d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Greaterthan/Index.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-greaterthan: - -=========== -greaterthan -=========== - -Checks if the submitted value is greater than the integer set in TypoScript. - - -.. _reference-rules-greaterthan-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-greaterthan-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - - The marker %minimum will be replaced with the value set in TypoScript. - -:aspect:`Default:` - *local language:*"The value does not appear to be greater than %minimum" - - -.. _reference-rules-greaterthan-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - The marker %minimum will be replaced with the value set by TypoScript. - -:aspect:`Default:` - *local language:*"The value must be greater than %minimum" - - -.. _reference-rules-greaterthan-minimum: - -minimum -======= - -:aspect:`Property:` - minimum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The submitted value must be greater than the minimum value. - - -.. _reference-rules-greaterthan-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.greaterthan] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Inarray/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Inarray/Index.rst deleted file mode 100644 index 8aa5b07f4756cbc1255b404ee1edd13075dd049c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Inarray/Index.rst +++ /dev/null @@ -1,99 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-inarray: - -======= -inarray -======= - -Compares the submitted value with the values in the array set in TypoScript. - - -.. _reference-rules-inarray-array: - -array -===== - -:aspect:`Property:` - array - -:aspect:`Data type:` - [array of numbers] - -:aspect:`Description:` - The array containing the values which will be compared with the incoming - data. - - **Example:** - - .. code-block:: html - - array { - 1 = TYPO3 4.5 LTS - 2 = TYPO3 6.2 LTS - 3 = TYPO3 7 LTS - } - - -.. _reference-rules-inarray-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-inarray-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be valid" - - -.. _reference-rules-inarray-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Only a few values are possible" - - -.. _reference-rules-inarray-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - - -.. _reference-rules-inarray-strict: - -strict -====== - -:aspect:`Property:` - strict - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - The types of the needle in the haystack are also checked if strict = 1. - -:aspect:`Default:` - 0 - -[tsref:(cObject).FORM->rules.inarray] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Index.rst deleted file mode 100644 index 37a49aee48f6da69ac79ab776d7f9fa491485939..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Index.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. include:: ../../Includes.txt - - -.. _reference-rules: - -================ -Validation Rules -================ - -Validation rules are a powerful tool to add validation to the form. The -rules function will always be used at the beginning of the form and belongs -to the FORM object. - -It is possible to have multiple validation rules for one FORM object, but -the rules have to be added one by one. - -**Example** - -.. code-block:: typoscript - - rules { - 1 = required - 1 ( - element = first_name - ) - 2 = required - 2 { - element = last_name - showMessage = 0 - error = TEXT - error { - value = Please enter your last name - } - } - 3 = required - 3 { - element = email_address - } - 4 = email - 4 { - element = email_address - } - } - - -When a rule is defined, it will automatically add a message to the object -the rule is connected with. This message will be shown in the local language -and will tell the user the input needs to be according to this rule. The -message can be hidden or overruled with a user defined string/ cObject. - -The validation will be done by the order of the rules. The validation can be -stopped when a certain rule is not valid. By default all validation rules -will be processed. - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - ValidationAttributes/Index.rst - Alphabetic/Index.rst - Alphanumeric/Index.rst - Between/Index.rst - Date/Index.rst - Digit/Index.rst - Email/Index.rst - Equals/Index.rst - Float/Index.rst - Greaterthan/Index.rst - Inarray/Index.rst - Integer/Index.rst - Ip/Index.rst - Length/Index.rst - Lessthan/Index.rst - Regexp/Index.rst - Required/Index.rst - Uri/Index.rst - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Integer/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Integer/Index.rst deleted file mode 100644 index 5d94c1e241b7c6742ea8c767a4fb0acf5a573c2d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Integer/Index.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-integer: - -======= -integer -======= - -Checks if the submitted value is an integer. - - -.. _reference-rules-integer-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-integer-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be an integer" - - -.. _reference-rules-integer-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Use a integer" - - -.. _reference-rules-integer-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.integer] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Ip/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Ip/Index.rst deleted file mode 100644 index 0d29fac9eef2f8bc3cc0350d113fd6ba78f2a041..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Ip/Index.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-ip: - -== -ip -== - -Checks if the submitted value is an IP address. - - -.. _reference-rules-ip-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-ip-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be a valid IP address" - - -.. _reference-rules-ip-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"(123.123.123.123)" - - -.. _reference-rules-ip-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.ip] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Length/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Length/Index.rst deleted file mode 100644 index 264e4b9864d917eaa9bd0a107849f0d1f9151923..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Length/Index.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-length: - -====== -length -====== - -Checks if the submitted value is of a certain length. A minimum length can -be used or a minimum and a maximum length. - - -.. _reference-rules-length-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-length-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - - For this specific rule the default error message consists of two parts, - the second one will only be added when **maximum** is set. This - functionality is not possible when defining an own message as shown - below. - The markers %minimum and %maximum will be replaced with the values set - by TypoScript. - -:aspect:`Default:` - *local language:*"The value is less than %minimum characters long - (, or longer than %maximum)" - - -.. _reference-rules-length-maximum: - -maximum -======= - -:aspect:`Property:` - maximum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The maximum length of the submitted value. Maximum can only be used in - combination with minimum. - - -.. _reference-rules-length-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - For this specific rule the default message consists of two parts, the - second one will only be added when **maximum** is set. This - functionality is not possible when defining an own message as shown - below. - The markers %minimum and %maximum will be replaced with the values set - by TypoScript. - -:aspect:`Default:` - *local language:*"The length of the value must have a minimum of - %minimum characters(, and a maximum of %maximum)" - - -.. _reference-rules-length-minimum: - -minimum -======= - -:aspect:`Property:` - minimum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The minimum length of the submitted value. - - -.. _reference-rules-length-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.length] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Lessthan/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Lessthan/Index.rst deleted file mode 100644 index 4c2a479e71fa7fe1ce0ecdd7de81384be9ebb0b3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Lessthan/Index.rst +++ /dev/null @@ -1,74 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-lessthan: - -======== -lessthan -======== - -Checks if the submitted value is less than the integer set in TypoScript. - - -.. _reference-rules-lessthan-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-lessthan-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - - The marker %maximum will be replaced with the value set in TypoScript. - -:aspect:`Default:` - *local language:*"The value does not appear to be less than %maximum" - - -.. _reference-rules-lessthan-maximum: - -maximum -======= - -:aspect:`Property:` - maximum - -:aspect:`Data type:` - integer - -:aspect:`Description:` - The submitted value must be less than the maximum value. - - -.. _reference-rules-lessthan-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - - The marker %maximum will be replaced with the value set in TypoScript. - -:aspect:`Default:` - *local language:*"The value must be less than %maximum" - - -.. _reference-rules-lessthan-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.lessthan] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Regexp/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Regexp/Index.rst deleted file mode 100644 index cc0a8cbca7fd51d4bd7ed92e4e98eaff6bde6035..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Regexp/Index.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-regexp: - -====== -regexp -====== - -Checks if the submitted value matches your own regular expression, using PHP -function preg\_match(). - - -.. _reference-rules-regexp-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-regexp-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not match against pattern" - - -.. _reference-rules-regexp-expression: - -expression -========== - -:aspect:`Property:` - expression - -:aspect:`Data type:` - string - -:aspect:`Description:` - The submitted value needs to match the expression, given in your - pattern. - - -.. _reference-rules-regexp-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Use the right pattern" - - - -.. _reference-rules-regexp-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.regexp] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Required/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Required/Index.rst deleted file mode 100644 index 103e3935b3481f350cbd2c1071bf9f8e719307f8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Required/Index.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-required: - -======== -required -======== - -Checks if the submitted value exists and is not empty. - -0 or "0" are allowed and the rule will return true. - - -.. _reference-rules-required-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-required-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"This field is required" - - -.. _reference-rules-required-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"Required" - - -.. _reference-rules-required-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.required] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/Uri/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/Uri/Index.rst deleted file mode 100644 index 43d0cc37b1e67ffc10cbea265747d923fbc3c5af..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/Uri/Index.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-rules-uri: - -=== -uri -=== - -This validation rule checks on a URI, which can include all of the -following: - -- scheme://usern:passw@domain:port/path/file.ext?querystring#fragment - - -.. _reference-rules-uri-element: - -element -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-element`. - - -.. _reference-rules-uri-error: - -error -===== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-error`. - -:aspect:`Default:` - *local language:*"The value does not appear to be a hostname" - - -.. _reference-rules-uri-message: - -message -======= - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-message`. - -:aspect:`Default:` - *local language:*"The value must be a hostname" - - -.. _reference-rules-uri-showmessage: - -showMessage -=========== - -:aspect:`Description:` - See general information for :ref:`reference-validation-attributes-showmessage`. - -[tsref:(cObject).FORM->rules.uri] - diff --git a/typo3/sysext/form/Documentation/Configuration/Rules/ValidationAttributes/Index.rst b/typo3/sysext/form/Documentation/Configuration/Rules/ValidationAttributes/Index.rst deleted file mode 100644 index 93e4347018c8bf092db89b6c60190b2b1dbc1667..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Configuration/Rules/ValidationAttributes/Index.rst +++ /dev/null @@ -1,148 +0,0 @@ -.. include:: ../../../Includes.txt - - -.. _reference-validation-attributes: - -===================== -Validation Attributes -===================== - -.. contents:: - :local: - :depth: 1 - - -.. _reference-validation-attributes-allowwhitespace: - -allowWhiteSpace -=============== - -:aspect:`Property:` - allowWhiteSpace - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - If allowWhiteSpace = 1, whitespace is allowed in front of, after or - between the characters. - -:aspect:`Default:` - 0 - - -.. _reference-validation-attributes-element: - -element -======= - -:aspect:`Property:` - element - -:aspect:`Data type:` - string - -:aspect:`Description:` - Name of the object. Normally the "filtered" name can be found in the - HTML output between the square brackets like tx\_form[name] where "name" - is the name of the object. - - -.. _reference-validation-attributes-error: - -error -===== - -:aspect:`Property:` - error - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - Overriding the default text of the error message, describing the error. - - When no cObject type is set, the message is a simple string. The value - can directly be assigned to the message property. If one needs the - functionality of cObjects, just define the message appropriately. Any - cObject is allowed. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - error = TEXT - error { - data = LLL:EXT:theme/Resources/Private/Language/Form/locallang.xlf:alphabeticError - } - - **Example:** - - .. code-block:: typoscript - - error = The value contains not only alphabetic characters - -:aspect:`Default:` - Depends on the rule. Check over there. - - -.. _reference-validation-attributes-message: - -message -======= - -:aspect:`Property:` - message - -:aspect:`Data type:` - string/ cObject - -:aspect:`Description:` - Overriding the default text of the message, describing the rule. - - When no cObject type is set, the message is a simple string. The value - can directly be assigned to the message property. If one needs the - functionality of cObjects, just define the message appropriately. Any - cObject is allowed. - - For more information about cObjects, take a look in the document TSREF. - - **Example:** - - .. code-block:: typoscript - - message = TEXT - message { - data = LLL:EXT:theme/Resources/Private/Language/Form/locallang.xlf:betweenMessage - } - - **Example:** - - .. code-block:: typoscript - - message = The value must be between %minimum and %maximum - -:aspect:`Default:` - Depends on the rule. Check over there. - - -.. _reference-validation-attributes-showmessage: - -showMessage -=========== - -:aspect:`Property:` - showMessage - -:aspect:`Data type:` - boolean - -:aspect:`Description:` - If showMessage = 0, a message describing the rule will not be added to - the label of the object. - -:aspect:`Default:` - 1 - diff --git a/typo3/sysext/form/Documentation/Images/FormCreationWizard.png b/typo3/sysext/form/Documentation/Images/FormCreationWizard.png deleted file mode 100644 index 2256bbc51c0a4019f45db0757cae217d64fbd88c..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Documentation/Images/FormCreationWizard.png and /dev/null differ diff --git a/typo3/sysext/form/Documentation/Images/FormCreationWizardElementsTab.png b/typo3/sysext/form/Documentation/Images/FormCreationWizardElementsTab.png deleted file mode 100644 index c3478cb504f6f91f51781d6396b02f43a5f6688f..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Documentation/Images/FormCreationWizardElementsTab.png and /dev/null differ diff --git a/typo3/sysext/form/Documentation/Images/FormCreationWizardFormTab.png b/typo3/sysext/form/Documentation/Images/FormCreationWizardFormTab.png deleted file mode 100644 index 02bcb573374073be78f922b97e6d0aabd476c59c..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Documentation/Images/FormCreationWizardFormTab.png and /dev/null differ diff --git a/typo3/sysext/form/Documentation/Images/FormCreationWizardOptionsTab.png b/typo3/sysext/form/Documentation/Images/FormCreationWizardOptionsTab.png deleted file mode 100644 index 22a3affa1a8dfd3003d3cfc365841af60b0babb2..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Documentation/Images/FormCreationWizardOptionsTab.png and /dev/null differ diff --git a/typo3/sysext/form/Documentation/Images/FormCreationWizardShowTabs.png b/typo3/sysext/form/Documentation/Images/FormCreationWizardShowTabs.png deleted file mode 100644 index 0195c2f99f88429222a51c882eeb28bee25d01b7..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Documentation/Images/FormCreationWizardShowTabs.png and /dev/null differ diff --git a/typo3/sysext/form/Documentation/Includes.txt b/typo3/sysext/form/Documentation/Includes.txt deleted file mode 100644 index efbb82abf298298edbc9364bd4eac44ee59b46b4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Includes.txt +++ /dev/null @@ -1,13 +0,0 @@ -.. This is 'Includes.txt'. It is included at the very top of each and - every ReST source file in THIS documentation project (= manual). - -.. role:: aspect(emphasis) -.. role:: html(code) -.. role:: js(code) -.. role:: php(code) -.. role:: typoscript(code) -.. role:: ts(typoscript) - :class: typoscript - -.. highlight:: php -.. default-role:: code \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Index.rst b/typo3/sysext/form/Documentation/Index.rst deleted file mode 100644 index 7edcdb088cd3b8493bba69c479fab30291e55a1b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Index.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. include:: Includes.txt - - -.. _start: - -==== -Form -==== - -:Extension key: - form - -:Version: - 8 - -:Language: - en - -:Description: - Form Library, Plugin and Wizard - -:Keywords: - form - -:Copyright: - 2000-2016 - -:Author: - TYPO3 CMS Core Development Team - -:License: - Open Content License available from `www.opencontent.org/opl.shtml - <http://www.opencontent.org/opl.shtml>`_ - -:Rendered: - |today| - -The content of this document is related to TYPO3, - -a GNU/GPL CMS/Framework available from `www.typo3.org -<http://www.typo3.org/>`_ - - - - -**Table of Contents** - -.. toctree:: - :maxdepth: 5 - :titlesonly: - :glob: - - Introduction/Index - Administration/Index - Configuration/Index - Targets diff --git a/typo3/sysext/form/Documentation/Introduction/Index.rst b/typo3/sysext/form/Documentation/Introduction/Index.rst deleted file mode 100644 index fc1a6b6182502b806d922768994e9d03ec61d734..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Introduction/Index.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. include:: ../Includes.txt - - -.. _introduction: - -============ -Introduction -============ - - -.. _what-does-it-do: - -What does it do? -================ - -This extension allows editors to easily build forms using a drag and drop -interface. A WYSIWYG view simplifies the process of building a form, and -relatively non-technical editors can easily add chained validation rules -on a field-by-field basis (e.g., email and/ or alphanumeric validation). -Furthermore, filters can be added to each field to manipulate the entered -form data. - -Experienced integrators do not have to use the wizard. Instead, the form -configuration can be created just using a TypoScript like syntax. - -.. figure:: ../Images/FormCreationWizard.png - :alt: The form wizard with some predefined form elements. - -The screenshot shows the form wizard with some predefined form elements. - diff --git a/typo3/sysext/form/Documentation/Settings.cfg b/typo3/sysext/form/Documentation/Settings.cfg deleted file mode 100644 index bcc46bc7d96100c451d52644e673e3daa3cd8d72..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Settings.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[general] - -project = Form Library, Plugin and Wizard -version = 8 -release = 8 -t3author = Patrick Broens, Ralf Zimmermann -copyright = 1997-2016 - -description = This is the documentation of TYPO3's system - extension 'form'. This extension brings along the - content element 'form' and a wizard. - - -[html_theme_options] - -project_issues = https://forge.typo3.org/projects/typo3cms-core/issues -project_repository = https://git.typo3.org/Packages/TYPO3.CMS.git diff --git a/typo3/sysext/form/Documentation/Targets.rst b/typo3/sysext/form/Documentation/Targets.rst deleted file mode 100644 index 8b5ef39fa6a11f822a8b5f792a201b683eb6614f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Targets.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. include:: Includes.txt - -.. _index-labels-for-crossreferencing: - -================================== -Index: Labels for Crossreferencing -================================== - -.. ref-targets-list:: diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/button.txt b/typo3/sysext/form/Documentation/Tests/Attributes/button.txt deleted file mode 100644 index 2087507751b20675d708b0b0a5bc54d29660529d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/button.txt +++ /dev/null @@ -1,205 +0,0 @@ -form.attributes.button = FORM -form.attributes.button { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = BUTTON - 10 { - label = label - } - 20 = BUTTON - 20 { - label.value = label.value - } - 30 = BUTTON - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = BUTTON - 10 { - label = label in front of input (default) - } - 20 = BUTTON - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = BUTTON - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = BUTTON - 10 { - label = This button has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = BUTTON - 10 { - label = This button has an alt attribute - alt = This is the alt attribute content - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = BUTTON - 10 { - label = This button has a class attribute - class = classAtribute - } - 20 = BUTTON - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = BUTTON - 10 { - label = Dir ltr - dir = ltr - } - 20 = BUTTON - 20 { - label = Dir rtl - dir = rtl - } - 30 = BUTTON - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = BUTTON - 10 { - label = disabled=1 - disabled = 1 - } - 20 = BUTTON - 20 { - label = disabled=0 - disabled = 0 - } - 30 = BUTTON - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = BUTTON - 10 { - label = This button has an id attribute and the label a for attribute - id = buttonId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = BUTTON - 10 { - label = This button has a lang attribute - lang = en-US - } - } - - # Name - 100 = FIELDSET - 100 { - legend = Name test - 10 = BUTTON - 10 { - label = This button has a name attribute - name = buttonName - } - } - - # Style - 110 = FIELDSET - 110 { - legend = style test - 10 = BUTTON - 10 { - label = This button has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 120 = FIELDSET - 120 { - legend = Tabindex test - 10 = BUTTON - 10 { - label = This button has a tabindex attribute - tabindex = 1 - } - } - - # Title - 130 = FIELDSET - 130 { - legend = Title test - 10 = BUTTON - 10 { - label = This button has a title attribute - title = This is the title text - } - } - - # Value - 140 = FIELDSET - 140 { - legend = Value test - 10 = BUTTON - 10 { - label = This button has a value attribute - value = Don't you dare to push this button - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/checkbox.txt b/typo3/sysext/form/Documentation/Tests/Attributes/checkbox.txt deleted file mode 100644 index e169068b60689a79fb74bf67fcff00ae44ff4f4b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/checkbox.txt +++ /dev/null @@ -1,226 +0,0 @@ -form.attributes.checkbox = FORM -form.attributes.checkbox { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = CHECKBOX - 10 { - label = label - } - 20 = CHECKBOX - 20 { - label.value = label.value - } - 30 = CHECKBOX - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = CHECKBOX - 10 { - label = label in front of input (default) - } - 20 = CHECKBOX - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = CHECKBOX - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = CHECKBOX - 10 { - label = This checkbox has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = CHECKBOX - 10 { - label = This checkbox has an alt attribute - alt = This is the alt attribute content - } - } - - # Checked - 50 = FIELDSET - 50 { - legend = Checked test - 10 = CHECKBOX - 10 { - label = checked=1 - checked = 1 - } - 20 = CHECKBOX - 20 { - label = checked=0 - checked = 0 - } - 30 = CHECKBOX - 30 { - label = checked=checked - checked = checked - } - } - - # Class - 60 = FIELDSET - 60 { - legend = Class test - 10 = CHECKBOX - 10 { - label = This checkbox has a class attribute - class = classAtribute - } - 20 = CHECKBOX - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 70 = FIELDSET - 70 { - legend = Dir test - 10 = CHECKBOX - 10 { - label = Dir ltr - dir = ltr - } - 20 = CHECKBOX - 20 { - label = Dir rtl - dir = rtl - } - 30 = CHECKBOX - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 80 = FIELDSET - 80 { - legend = Disabled test - 10 = CHECKBOX - 10 { - label = disabled=1 - disabled = 1 - } - 20 = CHECKBOX - 20 { - label = disabled=0 - disabled = 0 - } - 30 = CHECKBOX - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 90 = FIELDSET - 90 { - legend = Id test - 10 = CHECKBOX - 10 { - label = This checkbox has an id attribute and the label a for attribute - id = checkboxId - } - } - - # Lang - 100 = FIELDSET - 100 { - legend = Lang test - 10 = CHECKBOX - 10 { - label = This checkbox has a lang attribute - lang = en-US - } - } - - # Name - 110 = FIELDSET - 110 { - legend = Name test - 10 = CHECKBOX - 10 { - label = This checkbox has a name attribute - name = checkboxName - } - } - - # Style - 120 = FIELDSET - 120 { - legend = style test - 10 = CHECKBOX - 10 { - label = This checkbox has a style attribute - style = width: 4em; height: 4em; - } - } - - # Tabindex - 130 = FIELDSET - 130 { - legend = Tabindex test - 10 = CHECKBOX - 10 { - label = This checkbox has a tabindex attribute - tabindex = 1 - } - } - - # Title - 140 = FIELDSET - 140 { - legend = Title test - 10 = CHECKBOX - 10 { - label = This checkbox has a title attribute - title = This is the title text - } - } - - # Value - 150 = FIELDSET - 150 { - legend = Value test - 10 = CHECKBOX - 10 { - label = This checkbox has a value attribute - value = checkboxValue - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/checkboxgroup.txt b/typo3/sysext/form/Documentation/Tests/Attributes/checkboxgroup.txt deleted file mode 100644 index 16544eb0554d4dc6c8999d8f27e96cb9c5753b83..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/checkboxgroup.txt +++ /dev/null @@ -1,39 +0,0 @@ -form.attributes.checkboxgroup = FORM -form.attributes.checkboxgroup { - method = post - - rules { - 1 = required - 1 { - element = checkboxgroup - } - } - - 10 = CHECKBOXGROUP - 10 { - legend = Checkbox Group test - name = checkboxgroup - - 10 = CHECKBOX - 10 { - label = Option 1 - } - 20 = CHECKBOX - 20 { - label = Option 2 - } - 30 = CHECKBOX - 30 { - label = Option 3 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/fieldset.txt b/typo3/sysext/form/Documentation/Tests/Attributes/fieldset.txt deleted file mode 100644 index 35b2cc8cbd56d4079afe3a1b578c34e831f1c499..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/fieldset.txt +++ /dev/null @@ -1,95 +0,0 @@ -form.attributes.fieldset = FORM -form.attributes.fieldset { - method = post - - # Legend - 10 = FIELDSET - 10 { - legend = Legend test - 10 = FIELDSET - 10 { - legend = legend - } - 20 = FIELDSET - 20 { - legend.value = legend.value - } - 30 = FIELDSET - 30 { - legend = TEXT - legend { - value = TEXT - } - } - } - - # Layout - 20 = FIELDSET - 20 { - legend = Layout test - 10 = FIELDSET - 10 { - legend = This should be at the bottom in the HTML source - layout ( - <fieldset> - <containerWrap /> - <legend /> - </fieldset> - ) - 10 = BUTTON - } - } - - # Class - 30 = FIELDSET - 30 { - legend = Class test - 10 = FIELDSET - 10 { - legend = One class - class = fieldsetClass - } - 20 = FIELDSET - 20 { - legend = Multiple classes - class = fieldsetClass1 fieldsetClass2 - } - } - - # Dir - 40 = FIELDSET - 40 { - legend = Dir test - 10 = FIELDSET - 10 { - legend = ltr - dir = ltr - } - 20 = FIELDSET - 20 { - legend = rtl - dir = rtl - } - } - - # Id - 50 = FIELDSET - 50 { - legend = Id test - id = fieldsetId - } - - # Lang - 60 = FIELDSET - 60 { - legend = Lang test - lang = en-US - } - - # Style - 70 = FIELDSET - 70 { - legend = Style test - style = background-color: red; - } -} diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/hidden.txt b/typo3/sysext/form/Documentation/Tests/Attributes/hidden.txt deleted file mode 100644 index 3e00780af3524ecd8550eeaa253a98a9c9d34039..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/hidden.txt +++ /dev/null @@ -1,76 +0,0 @@ -form.attributes.hidden = FORM -form.attributes.hidden { - method = post - - # Class - 10 = FIELDSET - 10 { - legend = Class test - 10 = FIELDSET - 10 { - legend = Single class - 10 = HIDDEN - 10 { - class = hiddenClass - } - } - 20 = FIELDSET - 20 { - legend = Multiple classes - 10 = HIDDEN - 10 { - class = hiddenClass1 hiddenClass2 - } - } - } - - # Id - 20 = FIELDSET - 20 { - legend = Id test - 10 = HIDDEN - 10 { - id = hiddenId - } - } - - # Lang - 30 = FIELDSET - 30 { - legend = Lang test - 10 = HIDDEN - 10 { - lang = en-US - } - } - - # Name - 40 = FIELDSET - 40 { - legend = Name test - 10 = HIDDEN - 10 { - name = hiddenName - } - } - - # Style - 50 = FIELDSET - 50 { - legend = Style test - 10 = HIDDEN - 10 { - style = background-color: red; - } - } - - # Value - 60 = FIELDSET - 60 { - legend = Value test - 10 = HIDDEN - 10 { - value = hiddenValue - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/optgroup.txt b/typo3/sysext/form/Documentation/Tests/Attributes/optgroup.txt deleted file mode 100644 index fe79cc9482f93600a4922b2b59449cafb90a5c43..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/optgroup.txt +++ /dev/null @@ -1,172 +0,0 @@ -form.attributes.optgroup = FORM -form.attributes.optgroup { - method = post - - # Basics - 10 = FIELDSET - 10 { - legend = Basics, already shows label - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = Option Group 1 - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - 2 = OPTION - 2 { - data = optgroup 1 option 2 - } - } - 2 = OPTGROUP - 2 { - label = Option Group 2 - 1 = OPTION - 1 { - data = optgroup 2 option 1 - } - 2 = OPTION - 2 { - data = optgroup 2 option 2 - } - } - } - } - - # Class - 20 = FIELDSET - 20 { - legend = Class - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = Single Class - class = singleClass - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - 2 = OPTGROUP - 2 { - label = Multiple classes - class = class1 class2 - 1 = OPTION - 1 { - data = optgroup 2 option 1 - } - } - } - } - - # Disabled - 30 = FIELDSET - 30 { - legend = Disabled - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = disabled=1 - disabled = 1 - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - 2 = OPTGROUP - 2 { - label = disabled=0 - disabled = 0 - 1 = OPTION - 1 { - data = optgroup 2 option 1 - } - } - 3 = OPTGROUP - 3 { - label = disabled=disabled - disabled = disabled - 1 = OPTION - 1 { - data = optgroup 3 option 1 - } - } - } - } - - # Id - 40 = FIELDSET - 40 { - legend = Id - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = Option group 1 - id = optgroup1 - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - } - } - - # Lang - 50 = FIELDSET - 50 { - legend = Lang - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = has Lang - lang = en-US - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - } - } - - # Style - 60 = FIELDSET - 60 { - legend = Style - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = has Style - style = background-color: red; - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - } - } - - # Title - 70 = FIELDSET - 70 { - legend = Title - 10 = SELECT - 10 { - 1 = OPTGROUP - 1 { - label = has Title - title = This is the OPTGROUP title - 1 = OPTION - 1 { - data = optgroup 1 option 1 - } - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/option.txt b/typo3/sysext/form/Documentation/Tests/Attributes/option.txt deleted file mode 100644 index d79cf77ddd97399c56adc2ccbb1ed06e46b9b62b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/option.txt +++ /dev/null @@ -1,176 +0,0 @@ -form.attributes.option = FORM -form.attributes.option { - method = post - - # Data - 10 = FIELDSET - 10 { - legend = Data - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - } - } - } - - # Class - 20 = FIELDSET - 20 { - legend = Class - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = Single class - class = singleClass - } - 2 = OPTION - 2 { - data = Multiple classes - class = class1 class2 - } - } - } - - # Disabled - 30 = FIELDSET - 30 { - legend = Disabled - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = disabled=1 - disabled = 1 - } - 2 = OPTION - 2 { - data = disabled=0 - disabled = 0 - } - 3 = OPTION - 3 { - data = disabled=disabled - disabled = disabled - } - } - } - - # Id - 40 = FIELDSET - 40 { - legend = Id - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - id = optionId - } - } - } - - # Label - 50 = FIELDSET - 50 { - legend = Label - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = This is a long data text - label = short - } - } - } - - # Lang - 60 = FIELDSET - 60 { - legend = Lang - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - lang = en-US - } - } - } - - # Selected - 70 = FIELDSET - 70 { - legend = Selected - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = selected=0 - selected = 0 - } - 2 = OPTION - 2 { - data = selected=1 - selected = 1 - } - } - 20 = SELECT - 20 { - 1 = OPTION - 1 { - data = selected=0 - selected = 0 - } - 2 = OPTION - 2 { - data = selected=selected - selected = selected - } - } - } - - # Style - 80 = FIELDSET - 80 { - legend = Style - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - style = height: 4em; - } - } - } - - # Title - 90 = FIELDSET - 90 { - legend = Title - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - title = This is the option title - } - } - } - - # Value - 100 = FIELDSET - 100 { - legend = Value - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = optionData - value = This is the option value - } - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/password.txt b/typo3/sysext/form/Documentation/Tests/Attributes/password.txt deleted file mode 100644 index 7bc66fab1002862d1c204f15e64d3eb25db894b3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/password.txt +++ /dev/null @@ -1,251 +0,0 @@ -form.attributes.password = FORM -form.attributes.password { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = PASSWORD - 10 { - label = label - } - 20 = PASSWORD - 20 { - label.value = label.value - } - 30 = PASSWORD - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = PASSWORD - 10 { - label = label in front of input (default) - } - 20 = PASSWORD - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = PASSWORD - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = PASSWORD - 10 { - label = This field has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = PASSWORD - 10 { - label = This field has an alt attribute - alt = This is the alt attribute content - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = PASSWORD - 10 { - label = This field has a class attribute - class = classAtribute - } - 20 = PASSWORD - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = PASSWORD - 10 { - label = Dir ltr - dir = ltr - } - 20 = PASSWORD - 20 { - label = Dir rtl - dir = rtl - } - 30 = PASSWORD - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = PASSWORD - 10 { - label = disabled=1 - disabled = 1 - } - 20 = PASSWORD - 20 { - label = disabled=0 - disabled = 0 - } - 30 = PASSWORD - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = PASSWORD - 10 { - label = This field has an id attribute and the label a for attribute - id = passwordId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = PASSWORD - 10 { - label = This field has a lang attribute - lang = en-US - } - } - - # Maxlength - 95 = FIELDSET - 95 { - legend = Maxlength test - 10 = PASSWORD - 10 { - label = This field has a maxlength attribute - maxlength = 10 - } - } - - # Name - 100 = FIELDSET - 100 { - legend = Name test - 10 = PASSWORD - 10 { - label = This field has a name attribute - name = passwordName - } - } - - # Readonly - 103 = FIELDSET - 103 { - legend = Readonly test - 10 = PASSWORD - 10 { - label = readonly=1 - readonly = 1 - value = thevalue - } - 20 = PASSWORD - 20 { - label = readonly=0 - readonly = 0 - value = thevalue - } - 30 = PASSWORD - 30 { - label = readonly=readonly - readonly = readonly - value = thevalue - } - } - - # Size - 106 = FIELDSET - 106 { - legend = Size test - 10 = PASSWORD - 10 { - label = This field has a size attribute - size = 10 - } - } - - # Style - 110 = FIELDSET - 110 { - legend = Style test - 10 = PASSWORD - 10 { - label = This field has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 120 = FIELDSET - 120 { - legend = Tabindex test - 10 = PASSWORD - 10 { - label = This field has a tabindex attribute - tabindex = 1 - } - } - - # Title - 130 = FIELDSET - 130 { - legend = Title test - 10 = PASSWORD - 10 { - label = This field has a title attribute - title = This is the title text - } - } - - # Value - 140 = FIELDSET - 140 { - legend = Value test - 10 = PASSWORD - 10 { - label = This field has a value attribute - value = The value attribute - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/radio.txt b/typo3/sysext/form/Documentation/Tests/Attributes/radio.txt deleted file mode 100644 index f461cfca212a59fff1f5f4a6f00358be4a69ef79..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/radio.txt +++ /dev/null @@ -1,226 +0,0 @@ -form.attributes.radio = FORM -form.attributes.radio { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = RADIO - 10 { - label = label - } - 20 = RADIO - 20 { - label.value = label.value - } - 30 = RADIO - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = RADIO - 10 { - label = label in front of input (default) - } - 20 = RADIO - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = RADIO - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = RADIO - 10 { - label = This radio button has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = RADIO - 10 { - label = This radio button has an alt attribute - alt = This is the alt attribute content - } - } - - # Checked - 45 = FIELDSET - 45 { - legend = Checked test - 10 = RADIO - 10 { - label = checked=1 - checked = 1 - } - 20 = RADIO - 20 { - label = checked=0 - checked = 0 - } - 30 = RADIO - 30 { - label = checked=checked - checked = checked - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = RADIO - 10 { - label = This radio button has a class attribute - class = classAtribute - } - 20 = RADIO - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = RADIO - 10 { - label = Dir ltr - dir = ltr - } - 20 = RADIO - 20 { - label = Dir rtl - dir = rtl - } - 30 = RADIO - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = RADIO - 10 { - label = disabled=1 - disabled = 1 - } - 20 = RADIO - 20 { - label = disabled=0 - disabled = 0 - } - 30 = RADIO - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = RADIO - 10 { - label = This radio button has an id attribute and the label a for attribute - id = radioId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = RADIO - 10 { - label = This radio button has a lang attribute - lang = en-US - } - } - - # Name - 100 = FIELDSET - 100 { - legend = Name test - 10 = RADIO - 10 { - label = This radio button has a name attribute - name = radioName - } - } - - # Style - 110 = FIELDSET - 110 { - legend = style test - 10 = RADIO - 10 { - label = This radio button has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 120 = FIELDSET - 120 { - legend = Tabindex test - 10 = RADIO - 10 { - label = This radio button has a tabindex attribute - tabindex = 1 - } - } - - # Title - 130 = FIELDSET - 130 { - legend = Title test - 10 = RADIO - 10 { - label = This radio button has a title attribute - title = This is the title text - } - } - - # Value - 140 = FIELDSET - 140 { - legend = Value test - 10 = RADIO - 10 { - label = This radio button has a value attribute - value = buttonValue - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/radiogroup.txt b/typo3/sysext/form/Documentation/Tests/Attributes/radiogroup.txt deleted file mode 100644 index eb918cf324a04413de08f7cb1bf1f521abac12df..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/radiogroup.txt +++ /dev/null @@ -1,39 +0,0 @@ -form.attributes.radiogroup = FORM -form.attributes.radiogroup { - method = post - - rules { - 1 = required - 1 { - element = radiogroup - } - } - - 10 = RADIOGROUP - 10 { - legend = Radio Group test - name = radiogroup - - 10 = RADIO - 10 { - label = Option 1 - } - 20 = RADIO - 20 { - label = Option 2 - } - 30 = RADIO - 30 { - label = Option 3 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/reset.txt b/typo3/sysext/form/Documentation/Tests/Attributes/reset.txt deleted file mode 100644 index 29c0fa25e148141a9c77bf1f8763f6717154e737..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/reset.txt +++ /dev/null @@ -1,205 +0,0 @@ -form.attributes.reset = FORM -form.attributes.reset { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = RESET - 10 { - label = label - } - 20 = RESET - 20 { - label.value = label.value - } - 30 = RESET - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = RESET - 10 { - label = label in front of input (default) - } - 20 = RESET - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = RESET - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = RESET - 10 { - label = This reset button has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = RESET - 10 { - label = This reset button has an alt attribute - alt = This is the alt attribute content - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = RESET - 10 { - label = This reset button has a class attribute - class = classAtribute - } - 20 = RESET - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = RESET - 10 { - label = Dir ltr - dir = ltr - } - 20 = RESET - 20 { - label = Dir rtl - dir = rtl - } - 30 = RESET - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = RESET - 10 { - label = disabled=1 - disabled = 1 - } - 20 = RESET - 20 { - label = disabled=0 - disabled = 0 - } - 30 = RESET - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = RESET - 10 { - label = This reset button has an id attribute and the label a for attribute - id = resetId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = RESET - 10 { - label = This reset button has a lang attribute - lang = en-US - } - } - - # Name - 100 = FIELDSET - 100 { - legend = Name test - 10 = RESET - 10 { - label = This reset button has a name attribute - name = resetName - } - } - - # Style - 110 = FIELDSET - 110 { - legend = style test - 10 = RESET - 10 { - label = This reset button has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 120 = FIELDSET - 120 { - legend = Tabindex test - 10 = RESET - 10 { - label = This reset button has a tabindex attribute - tabindex = 1 - } - } - - # Title - 130 = FIELDSET - 130 { - legend = Title test - 10 = RESET - 10 { - label = This reset button has a title attribute - title = This is the title text - } - } - - # Value - 140 = FIELDSET - 140 { - legend = Value test - 10 = RESET - 10 { - label = This reset button has a value attribute - value = Don't you dare to push this reset button - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/select.txt b/typo3/sysext/form/Documentation/Tests/Attributes/select.txt deleted file mode 100644 index 53da9a7d76a269af647838caf8abfd7800bd4bc4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/select.txt +++ /dev/null @@ -1,209 +0,0 @@ -form.tempOption = OPTION -form.tempOption { - data = optionData -} - -form.attributes.select = FORM -form.attributes.select { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = SELECT - 10 { - label = label - 1 < form.tempOption - } - 20 = SELECT - 20 { - label.value = label.value - 1 < form.tempOption - } - 30 = SELECT - 30 { - label = TEXT - label { - value = TEXT cObj - } - 1 < form.tempOption - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = SELECT - 10 { - label = label in front of input (default) - 1 < form.tempOption - } - 20 = SELECT - 20 { - layout ( - <select> - <elements /> - </select> - <label /> - ) - label = label after input - 1 < form.tempOption - } - 30 = SELECT - 30 { - 1 < form.tempOption - } - } - - # Class - 30 = FIELDSET - 30 { - legend = Class test - 10 = SELECT - 10 { - label = This select has a class attribute - class = classAtribute - 1 < form.tempOption - } - 20 = SELECT - 20 { - label = Multiple classes - class = class1 class2 - 1 < form.tempOption - } - } - - # Disabled - 40 = FIELDSET - 40 { - legend = Disabled test - 10 = SELECT - 10 { - label = disabled=1 - disabled = 1 - 1 < form.tempOption - } - 20 = SELECT - 20 { - label = disabled=0 - disabled = 0 - 1 < form.tempOption - } - 30 = SELECT - 30 { - label = disabled=disabled - disabled = disabled - 1 < form.tempOption - } - } - - # Id - 50 = FIELDSET - 50 { - legend = Id test - 10 = SELECT - 10 { - label = This select has an id attribute and the label a for attribute - id = textlineId - 1 < form.tempOption - } - } - - # Lang - 60 = FIELDSET - 60 { - legend = Lang test - 10 = SELECT - 10 { - label = This select has a lang attribute - lang = en-US - 1 < form.tempOption - } - } - - # Multiple - 70 = FIELDSET - 70 { - legend = Multiple test - 10 = SELECT - 10 { - label = multiple=1 - multiple = 1 - 1 < form.tempOption - } - 20 = SELECT - 20 { - label = multiple=0 - multiple = 0 - 1 < form.tempOption - } - 30 = SELECT - 30 { - label = multiple=multiple - multiple = multiple - 1 < form.tempOption - } - } - - # Name - 110 = FIELDSET - 110 { - legend = Name test - 10 = SELECT - 10 { - label = This select has a name attribute - name = selectName - 1 < form.tempOption - } - } - - # Size - 120 = FIELDSET - 120 { - legend = Size test - 10 = SELECT - 10 { - label = This select has a size attribute - size = 10 - 1 < form.tempOption - } - } - - # Style - 130 = FIELDSET - 130 { - legend = style test - 10 = SELECT - 10 { - label = This select has a style attribute - style = border: 1px solid #000000 - 1 < form.tempOption - } - } - - # Tabindex - 140 = FIELDSET - 140 { - legend = Tabindex test - 10 = SELECT - 10 { - label = This select has a tabindex attribute - tabindex = 1 - 1 < form.tempOption - } - } - - # Title - 150 = FIELDSET - 150 { - legend = Title test - 10 = SELECT - 10 { - label = This select has a title attribute - title = This is the title text - 1 < form.tempOption - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/submit.txt b/typo3/sysext/form/Documentation/Tests/Attributes/submit.txt deleted file mode 100644 index 6abb1e2399b59650e015e0a1ecc3e9ac7a05cabf..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/submit.txt +++ /dev/null @@ -1,205 +0,0 @@ -form.attributes.submit = FORM -form.attributes.submit { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = SUBMIT - 10 { - label = label - } - 20 = SUBMIT - 20 { - label.value = label.value - } - 30 = SUBMIT - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = SUBMIT - 10 { - label = label in front of input (default) - } - 20 = SUBMIT - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = SUBMIT - 30 { - layout = <input /> - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = SUBMIT - 10 { - label = This submit button has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = SUBMIT - 10 { - label = This submit button has an alt attribute - alt = This is the alt attribute content - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = SUBMIT - 10 { - label = This submit button has a class attribute - class = classAtribute - } - 20 = SUBMIT - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = SUBMIT - 10 { - label = Dir ltr - dir = ltr - } - 20 = SUBMIT - 20 { - label = Dir rtl - dir = rtl - } - 30 = SUBMIT - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = SUBMIT - 10 { - label = disabled=1 - disabled = 1 - } - 20 = SUBMIT - 20 { - label = disabled=0 - disabled = 0 - } - 30 = SUBMIT - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = SUBMIT - 10 { - label = This submit button has an id attribute and the label a for attribute - id = submitId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = SUBMIT - 10 { - label = This submit button has a lang attribute - lang = en-US - } - } - - # Name - 100 = FIELDSET - 100 { - legend = Name test - 10 = SUBMIT - 10 { - label = This submit button has a name attribute - name = submitName - } - } - - # Style - 110 = FIELDSET - 110 { - legend = style test - 10 = SUBMIT - 10 { - label = This submit button has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 120 = FIELDSET - 120 { - legend = Tabindex test - 10 = SUBMIT - 10 { - label = This submit button has a tabindex attribute - tabindex = 1 - } - } - - # Title - 130 = FIELDSET - 130 { - legend = Title test - 10 = SUBMIT - 10 { - label = This submit button has a title attribute - title = This is the title text - } - } - - # Value - 140 = FIELDSET - 140 { - legend = Value test - 10 = SUBMIT - 10 { - label = This submit button has a value attribute - value = Don't you dare to push this reset button - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/textarea.txt b/typo3/sysext/form/Documentation/Tests/Attributes/textarea.txt deleted file mode 100644 index 92cd34c6388d6a174b8f2d867385f9f92a7846d8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/textarea.txt +++ /dev/null @@ -1,239 +0,0 @@ -form.attributes.textarea = FORM -form.attributes.textarea { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = TEXTAREA - 10 { - label = label - } - 20 = TEXTAREA - 20 { - label.value = label.value - } - 30 = TEXTAREA - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = TEXTAREA - 10 { - label = label in front of input (default) - } - 20 = TEXTAREA - 20 { - layout ( - <textarea /> - <label /> - ) - label = label after input - } - 30 = TEXTAREA - 30 { - value = No label - } - } - - # Data test - 30 = FIELDSET - 30 { - legend = Data test - 10 = TEXTAREA - 10 { - label = There should be data in the textarea - data = There is data in the textarea - } - } - - # Accesskey - 40 = FIELDSET - 40 { - legend = Accesskey test - 10 = TEXTAREA - 10 { - label = This textarea has an accesskey - accesskey = a - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = TEXTAREA - 10 { - label = This textarea has a class attribute - class = classAtribute - } - 20 = TEXTAREA - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Cols - 60 = FIELDSET - 60 { - legend = Cols test - 10 = TEXTAREA - 10 { - label = This textarea has a cols - cols = 100 - } - } - - # Dir - 70 = FIELDSET - 70 { - legend = Dir test - 10 = TEXTAREA - 10 { - label = Dir ltr - dir = ltr - } - 20 = TEXTAREA - 20 { - label = Dir rtl - dir = rtl - } - 30 = TEXTAREA - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 80 = FIELDSET - 80 { - legend = Disabled test - 10 = TEXTAREA - 10 { - label = disabled=1 - disabled = 1 - } - 20 = TEXTAREA - 20 { - label = disabled=0 - disabled = 0 - } - 30 = TEXTAREA - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 90 = FIELDSET - 90 { - legend = Id test - 10 = TEXTAREA - 10 { - label = This textarea has an id attribute and the label a for attribute - id = textareaId - } - } - - # Lang - 100 = FIELDSET - 100 { - legend = Lang test - 10 = TEXTAREA - 10 { - label = This textarea has a lang attribute - lang = en-US - } - } - - # Name - 110 = FIELDSET - 110 { - legend = Name test - 10 = TEXTAREA - 10 { - label = This textarea has a name attribute - name = textareaName - } - } - - # Readonly - 120 = FIELDSET - 120 { - legend = Readonly test - 10 = TEXTAREA - 10 { - label = readonly=1 - readonly = 1 - data = This should be readonly - } - 20 = TEXTAREA - 20 { - label = readonly=0 - readonly = 0 - data = This should NOT be readonly - } - 30 = TEXTAREA - 30 { - label = readonly=readonly - readonly = readonly - data = This should be readonly - } - } - - # Rows - 130 = FIELDSET - 130 { - legend = Rows test - 10 = TEXTAREA - 10 { - label = This textarea has rows - rows = 100 - } - } - - # Style - 140 = FIELDSET - 140 { - legend = style test - 10 = TEXTAREA - 10 { - label = This textarea has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 150 = FIELDSET - 150 { - legend = Tabindex test - 10 = TEXTAREA - 10 { - label = This textarea has a tabindex attribute - tabindex = 1 - } - } - - # Title - 160 = FIELDSET - 160 { - legend = Title test - 10 = TEXTAREA - 10 { - label = This textarea has a title attribute - title = This is the title text - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Attributes/textline.txt b/typo3/sysext/form/Documentation/Tests/Attributes/textline.txt deleted file mode 100644 index 4d7251be836a92c8b9c25ec06023dfed86f50004..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Attributes/textline.txt +++ /dev/null @@ -1,250 +0,0 @@ -form.attributes.textline = FORM -form.attributes.textline { - method = post - - # Label test - 10 = FIELDSET - 10 { - legend = Label test - 10 = TEXTLINE - 10 { - label = label - } - 20 = TEXTLINE - 20 { - label.value = label.value - } - 30 = TEXTLINE - 30 { - label = TEXT - label { - value = TEXT cObj - } - } - } - - # Layout test - 20 = FIELDSET - 20 { - legend = Layout test - 10 = TEXTLINE - 10 { - label = label in front of input (default) - } - 20 = TEXTLINE - 20 { - layout ( - <input /> - <label /> - ) - label = label after input - } - 30 = TEXTLINE - 30 { - value = No label - } - } - - # Accesskey - 30 = FIELDSET - 30 { - legend = Accesskey test - 10 = TEXTLINE - 10 { - label = This textline has an accesskey - accesskey = a - } - } - - # Alt - 40 = FIELDSET - 40 { - legend = Alt test - 10 = TEXTLINE - 10 { - label = This submit button has an alt attribute - alt = This is the alt attribute content - } - } - - # Class - 50 = FIELDSET - 50 { - legend = Class test - 10 = TEXTLINE - 10 { - label = This textline has a class attribute - class = classAtribute - } - 20 = TEXTLINE - 20 { - label = Multiple classes - class = class1 class2 - } - } - - # Dir - 60 = FIELDSET - 60 { - legend = Dir test - 10 = TEXTLINE - 10 { - label = Dir ltr - dir = ltr - } - 20 = TEXTLINE - 20 { - label = Dir rtl - dir = rtl - } - 30 = TEXTLINE - 30 { - label = Wrong input in dir - dir = abc - } - } - - # Disabled - 70 = FIELDSET - 70 { - legend = Disabled test - 10 = TEXTLINE - 10 { - label = disabled=1 - disabled = 1 - } - 20 = TEXTLINE - 20 { - label = disabled=0 - disabled = 0 - } - 30 = TEXTLINE - 30 { - label = disabled=disabled - disabled = disabled - } - } - - # Id - 80 = FIELDSET - 80 { - legend = Id test - 10 = TEXTLINE - 10 { - label = This textline has an id attribute and the label a for attribute - id = textlineId - } - } - - # Lang - 90 = FIELDSET - 90 { - legend = Lang test - 10 = TEXTLINE - 10 { - label = This textline has a lang attribute - lang = en-US - } - } - - # Maxlength - 100 = FIELDSET - 100 { - legend = Maxlength test - 10 = TEXTLINE - 10 { - label = This textline has a maxlength attribute - maxlength = 10 - } - } - - # Name - 110 = FIELDSET - 110 { - legend = Name test - 10 = TEXTLINE - 10 { - label = This textline has a name attribute - name = textlineName - } - } - - # Readonly - 120 = FIELDSET - 120 { - legend = Readonly test - 10 = TEXTLINE - 10 { - label = readonly=1 - readonly = 1 - data = This should be readonly - } - 20 = TEXTLINE - 20 { - label = readonly=0 - readonly = 0 - data = This should NOT be readonly - } - 30 = TEXTLINE - 30 { - label = readonly=readonly - readonly = readonly - data = This should be readonly - } - } - - # Size - 130 = FIELDSET - 130 { - legend = Size test - 10 = TEXTLINE - 10 { - label = This textline has a size attribute - size = 10 - } - } - - # Style - 140 = FIELDSET - 140 { - legend = style test - 10 = TEXTLINE - 10 { - label = This textline has a style attribute - style = border: 1px solid #000000 - } - } - - # Tabindex - 150 = FIELDSET - 150 { - legend = Tabindex test - 10 = TEXTLINE - 10 { - label = This textline has a tabindex attribute - tabindex = 1 - } - } - - # Title - 160 = FIELDSET - 160 { - legend = Title test - 10 = TEXTLINE - 10 { - label = This textline has a title attribute - title = This is the title text - } - } - - # Value - 170 = FIELDSET - 170 { - legend = Value test - 10 = TEXTLINE - 10 { - label = This textline has a value attribute - value = The value attribute - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/alphabetic.txt b/typo3/sysext/form/Documentation/Tests/Filter/alphabetic.txt deleted file mode 100644 index 9df926f7080c3b1e07500f320cfda1512b1dae67..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/alphabetic.txt +++ /dev/null @@ -1,56 +0,0 @@ -form.filter.alphabetic = FORM -form.filter.alphabetic { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Alphabetic - 10 = FIELDSET - 10 { - legend = Alphabetic test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 - filters { - 1 = alphabetic - } - } - 20 = TEXTLINE - 20 { - label = allowWhiteSpace=1 - value = John Doe 3 - filters { - 1 = alphabetic - 1 { - allowWhiteSpace = 1 - } - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/alphanumeric.txt b/typo3/sysext/form/Documentation/Tests/Filter/alphanumeric.txt deleted file mode 100644 index f6c965c704290e3172fc63b7fd91536a5bfcd3df..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/alphanumeric.txt +++ /dev/null @@ -1,56 +0,0 @@ -form.filter.alphanumeric = FORM -form.filter.alphanumeric { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Alphanumeric - 10 = FIELDSET - 10 { - legend = Alphanumeric test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = alphanumeric - } - } - 20 = TEXTLINE - 20 { - label = allowWhiteSpace=1 - value = John Doe 3 #$ - filters { - 1 = alphanumeric - 1 { - allowWhiteSpace = 1 - } - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/currency.txt b/typo3/sysext/form/Documentation/Tests/Filter/currency.txt deleted file mode 100644 index dc5aeb2e331b45b26398fc25b0e978e714638a72..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/currency.txt +++ /dev/null @@ -1,68 +0,0 @@ -form.filter.currency = FORM -form.filter.currency { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Currency - 10 = FIELDSET - 10 { - legend = Currency test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = currency - } - } - 20 = TEXTLINE - 20 { - label = decimalPoint=, - value = John Doe 3 #$ - filters { - 1 = currency - 1 { - decimalPoint = , - } - } - } - 30 = TEXTLINE - 30 { - label = decimalPoint=, / thousandSeparator=space - value = John Doe 3 #$ - filters { - 1 = currency - 1 { - decimalPoint = , - thousandSeparator = space - } - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/digit.txt b/typo3/sysext/form/Documentation/Tests/Filter/digit.txt deleted file mode 100644 index d6fc155be035922da89af0af75fc682239efea21..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/digit.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.filter.digit = FORM -form.filter.digit { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Digit - 10 = FIELDSET - 10 { - legend = Digit test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = digit - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/integer.txt b/typo3/sysext/form/Documentation/Tests/Filter/integer.txt deleted file mode 100644 index e6cc33b24039f0293640286b896b4cbf97a771b3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/integer.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.filter.integer = FORM -form.filter.integer { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Integer - 10 = FIELDSET - 10 { - legend = Integer test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = integer - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/lowercase.txt b/typo3/sysext/form/Documentation/Tests/Filter/lowercase.txt deleted file mode 100644 index 536013a499f1148d23487e0e80bf79d85ddbad26..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/lowercase.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.filter.lowercase = FORM -form.filter.lowercase { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Lower case - 10 = FIELDSET - 10 { - legend = Lower case test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = lowercase - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/regexp.txt b/typo3/sysext/form/Documentation/Tests/Filter/regexp.txt deleted file mode 100644 index 04cf247fe6a4c211f83e4a7104656921d45460fb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/regexp.txt +++ /dev/null @@ -1,48 +0,0 @@ -form.filter.regexp = FORM -form.filter.regexp { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Regular expression - 10 = FIELDSET - 10 { - legend = Regular expression test - 10 = TEXTLINE - 10 { - label = using regexp /[^a-zA-Z]/u - value = John Doe 3 #$ - filters { - 1 = regexp - 1 { - expression = /[^a-zA-Z]/u - } - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/stripnewlines.txt b/typo3/sysext/form/Documentation/Tests/Filter/stripnewlines.txt deleted file mode 100644 index ebc546270a3a4505444c8193059d0a44438e9d51..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/stripnewlines.txt +++ /dev/null @@ -1,49 +0,0 @@ -form.filter.stripnewlines = FORM -form.filter.stripnewlines { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Strip newlines - 10 = FIELDSET - 10 { - legend = Strip newlines test - 10 = TEXTAREA - 10 { - label = No settings - data ( -line 1 -line 2 -line 3 - ) - filters { - 1 = stripnewlines - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/titlecase.txt b/typo3/sysext/form/Documentation/Tests/Filter/titlecase.txt deleted file mode 100644 index cfa4e5840dc52db9a59b51d79979ae747149e396..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/titlecase.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.filter.titlecase = FORM -form.filter.titlecase { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Title case - 10 = FIELDSET - 10 { - legend = Title case test - 10 = TEXTLINE - 10 { - label = No settings - value = kasper skÃ¥rhøj - filters { - 1 = titlecase - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/trim.txt b/typo3/sysext/form/Documentation/Tests/Filter/trim.txt deleted file mode 100644 index 60d87d762f898417b45b2764f3ec4f119bfac256..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/trim.txt +++ /dev/null @@ -1,60 +0,0 @@ -form.filter.trim = FORM -form.filter.trim { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Trim - 10 = FIELDSET - 10 { - legend = Trim test - 10 = TEXTAREA - 10 { - label = No settings - data ( - line 1 - line 2 - line 3 - ) - filters { - 1 = trim - } - } - 20 = TEXTLINE - 20 { - label = characterList=a,b,f,g - value = abcdefg - filters { - 1 = trim - 1 { - characterList = a,b,f,g - } - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Filter/uppercase.txt b/typo3/sysext/form/Documentation/Tests/Filter/uppercase.txt deleted file mode 100644 index b064a86e422325f9ac5df716fb0394f321c059f5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Filter/uppercase.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.filter.uppercase = FORM -form.filter.uppercase { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Upper case - 10 = FIELDSET - 10 { - legend = Upper case test - 10 = TEXTLINE - 10 { - label = no settings - value = John Doe 3 #$ - filters { - 1 = uppercase - } - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Request/checkbox.txt b/typo3/sysext/form/Documentation/Tests/Request/checkbox.txt deleted file mode 100644 index e938f9cbd57738a173a4fdc68809f37f66100210..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Request/checkbox.txt +++ /dev/null @@ -1,70 +0,0 @@ -form.request.checkbox = FORM -form.request.checkbox { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Checked test - 10 = FIELDSET - 10 { - legend = Checked test - 10 = CHECKBOX - 10 { - label = Uncheck me - checked = checked - } - 20 = CHECKBOX - 20 { - label = Check me - } - } - - # Multiple test - 20 = FIELDSET - 20 { - legend = Multiple test - 10 = CHECKBOX - 10 { - label = Check 1 - name = checkmultiple - value = check1 - } - 20 = CHECKBOX - 20 { - label = Check 2 - name = checkmultiple - value = check2 - } - 30 = CHECKBOX - 30 { - label = Check 3 - name = checkmultiple - value = check3 - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Request/option.txt b/typo3/sysext/form/Documentation/Tests/Request/option.txt deleted file mode 100644 index c02c6a440656660246cea6eac43de869d6efacb0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Request/option.txt +++ /dev/null @@ -1,127 +0,0 @@ -form.request.option = FORM -form.request.option { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Selected test - 10 = FIELDSET - 10 { - legend = Selected test - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = Select me - value = option2 - } - 2 = OPTION - 2 { - data = Deselect me - selected = selected - value = option1 - } - } - } - - # Regular test - 20 = FIELDSET - 20 { - legend = Regular test - 10 = SELECT - 10 { - 1 = OPTION - 1 { - data = Option 1 - value = option1 - } - 2 = OPTION - 2 { - data = Option 2 - value = option2 - } - 3 = OPTION - 3 { - data = Option 3 - value = option3 - } - } - } - - # Multiple test - 30 = FIELDSET - 30 { - legend = Regular test - 10 = SELECT - 10 { - multiple = multiple - 1 = OPTION - 1 { - data = Option 1 - value = option1 - } - 2 = OPTION - 2 { - data = Option 2 - value = option2 - } - 3 = OPTION - 3 { - data = Option 3 - value = option3 - } - } - } - - # Multiple selected test - 40 = FIELDSET - 40 { - legend = Regular test - 10 = SELECT - 10 { - multiple = multiple - 1 = OPTION - 1 { - data = Uncheck me 1 - value = option1 - selected = selected - } - 2 = OPTION - 2 { - data = Check me - value = option2 - } - 3 = OPTION - 3 { - data = Uncheck me 2 - value = option3 - selected = selected - } - } - } - - # A textline which must be empty to test the above - 50 = FIELDSET - 50 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 60 = FIELDSET - 60 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Request/radio.txt b/typo3/sysext/form/Documentation/Tests/Request/radio.txt deleted file mode 100644 index 0cb778fdd47c4eac48eee3bb9d2f1e08a0a297a5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Request/radio.txt +++ /dev/null @@ -1,74 +0,0 @@ -form.request.radio = FORM -form.request.radio { - method = post - - rules { - 1 = required - 1 { - element = textlineField - } - } - - # Checked test - 10 = FIELDSET - 10 { - legend = Checked test - 10 = RADIO - 10 { - label = Uncheck me - checked = checked - name = checkmultiple - value = check1 - } - 20 = RADIO - 20 { - label = Check me - name = checkmultiple - value = check2 - } - } - - # Radio group - 20 = FIELDSET - 20 { - legend = Radio group - 10 = RADIO - 10 { - label = Check 1 - name = checkmultiple2 - value = check1 - } - 20 = RADIO - 20 { - label = Check 2 - name = checkmultiple2 - value = check2 - } - 30 = RADIO - 30 { - label = Check 3 - name = checkmultiple2 - value = check3 - } - } - - # A textline which must be empty to test the above - 30 = FIELDSET - 30 { - legend = Leave empty to get the form back after submitting - 10 = TEXTLINE - 10 { - name = textlineField - label = Leave me empty - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/alphabetic.txt b/typo3/sysext/form/Documentation/Tests/Validation/alphabetic.txt deleted file mode 100644 index bfdb5ec6289b66fb9ba9dad64a189cba247f943a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/alphabetic.txt +++ /dev/null @@ -1,43 +0,0 @@ -form.validation.alphabetic = FORM -form.validation.alphabetic { - method = post - - rules { - 1 = alphabetic - 1 { - element = alphabetic1 - } - 2 = alphabetic - 2 { - element = alphabetic2 - allowWhiteSpace = 1 - } - } - - # Alphabetic - 10 = FIELDSET - 10 { - legend = Alphabetic test - 10 = TEXTLINE - 10 { - label = no settings - value = 12345 - name = alphabetic1 - } - 20 = TEXTLINE - 20 { - label = allowWhiteSpace=1 - value = 12345 - name = alphabetic2 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/alphanumeric.txt b/typo3/sysext/form/Documentation/Tests/Validation/alphanumeric.txt deleted file mode 100644 index d25e82610fe87c43396fcea0f42e68ef8f00ae28..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/alphanumeric.txt +++ /dev/null @@ -1,43 +0,0 @@ -form.validation.alphanumeric = FORM -form.validation.alphanumeric { - method = post - - rules { - 1 = alphanumeric - 1 { - element = alphanumeric1 - } - 2 = alphanumeric - 2 { - element = alphanumeric2 - allowWhiteSpace = 1 - } - } - - # Alpahnumeric - 10 = FIELDSET - 10 { - legend = Alphanumeric test - 10 = TEXTLINE - 10 { - label = no settings - value = !@#$%^ - name = alphanumeric1 - } - 20 = TEXTLINE - 20 { - label = allowWhiteSpace=1 - value = !@#$%^ - name = alphanumeric2 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/between.txt b/typo3/sysext/form/Documentation/Tests/Validation/between.txt deleted file mode 100644 index 3a324084d9146e435c69907148d7d4e5ef007072..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/between.txt +++ /dev/null @@ -1,47 +0,0 @@ -form.validation.between = FORM -form.validation.between { - method = post - - rules { - 1 = between - 1 { - element = between1 - minimum = 5 - maximum = 10 - } - 2 = between - 2 { - element = between2 - minimum = 5 - maximum = 10 - inclusive = 1 - } - } - - # Between - 10 = FIELDSET - 10 { - legend = Between test - 10 = TEXTLINE - 10 { - label = Between 5 and 10 - value = abcdef - name = between1 - } - 20 = TEXTLINE - 20 { - label = Between 5 and 10, inclusive - value = abcdef - name = between2 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/combined.txt b/typo3/sysext/form/Documentation/Tests/Validation/combined.txt deleted file mode 100644 index 54095e04e2030d435bca85dee5b6ffef146bcec5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/combined.txt +++ /dev/null @@ -1,36 +0,0 @@ -form.validation.combined = FORM -form.validation.combined { - method = post - - rules { - 1 = required - 1 { - element = email1 - } - 2 = email - 2 { - element = email1 - } - } - - # Email - 10 = FIELDSET - 10 { - legend = Email test - 10 = TEXTLINE - 10 { - label = Email address - value = abc!@# - name = email1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/date.txt b/typo3/sysext/form/Documentation/Tests/Validation/date.txt deleted file mode 100644 index e8612654ced2c4a059daeee7ad38248dad51bee4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/date.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.date = FORM -form.validation.date { - method = post - - rules { - 1 = date - 1 { - element = date1 - } - } - - # Date - 10 = FIELDSET - 10 { - legend = Date test - 10 = TEXTLINE - 10 { - label = Date %e-%m-%Y - value = 34-13-01 - name = date1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/digit.txt b/typo3/sysext/form/Documentation/Tests/Validation/digit.txt deleted file mode 100644 index 45dd766f1774da8939f676c64d5d9185c2747819..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/digit.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.digit = FORM -form.validation.digit { - method = post - - rules { - 1 = digit - 1 { - element = digit1 - } - } - - # Digit - 10 = FIELDSET - 10 { - legend = Digit test - 10 = TEXTLINE - 10 { - label = Digit - value = abc!@# - name = digit1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/email.txt b/typo3/sysext/form/Documentation/Tests/Validation/email.txt deleted file mode 100644 index bd6f487fd30329c6b15b223d7db5e51a00bb213f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/email.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.email = FORM -form.validation.email { - method = post - - rules { - 1 = email - 1 { - element = email1 - } - } - - # Email - 10 = FIELDSET - 10 { - legend = Email test - 10 = TEXTLINE - 10 { - label = Email address - value = abc!@# - name = email1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/equals.txt b/typo3/sysext/form/Documentation/Tests/Validation/equals.txt deleted file mode 100644 index 12e0968ca942c474e70f82ea8e5f5feacf8aa3aa..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/equals.txt +++ /dev/null @@ -1,39 +0,0 @@ -form.validation.equals = FORM -form.validation.equals { - method = post - - rules { - 1 = equals - 1 { - element = equals1 - field = equals2 - } - } - - # Equals - 10 = FIELDSET - 10 { - legend = Equals test - 10 = TEXTLINE - 10 { - label = First field - value = abcde - name = equals1 - } - 20 = TEXTLINE - 20 { - label = Second field - value = abcdef - name = equals2 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/float.txt b/typo3/sysext/form/Documentation/Tests/Validation/float.txt deleted file mode 100644 index e82c3f6b168a9614bf464ae4475d33da47a3c9ae..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/float.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.float = FORM -form.validation.float { - method = post - - rules { - 1 = float - 1 { - element = float1 - } - } - - # Float - 10 = FIELDSET - 10 { - legend = Float test - 10 = TEXTLINE - 10 { - label = Float - value = abcde - name = float1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/greaterthan.txt b/typo3/sysext/form/Documentation/Tests/Validation/greaterthan.txt deleted file mode 100644 index 01385a0dc060717d6ccd1e544043e4ddef3f10dc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/greaterthan.txt +++ /dev/null @@ -1,33 +0,0 @@ -form.validation.greaterthan = FORM -form.validation.greaterthan { - method = post - - rules { - 1 = greaterthan - 1 { - element = greaterthan1 - minimum = 5 - } - } - - # Greater than - 10 = FIELDSET - 10 { - legend = Greater than test - 10 = TEXTLINE - 10 { - label = Greater than - value = abcde - name = greaterthan1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/inarray.txt b/typo3/sysext/form/Documentation/Tests/Validation/inarray.txt deleted file mode 100644 index b21add2530de9c94940698845aa6519035564e85..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/inarray.txt +++ /dev/null @@ -1,38 +0,0 @@ -form.validation.inarray = FORM -form.validation.inarray { - method = post - - rules { - 1 = inarray - 1 { - element = inarray1 - array { - 1 = TYPO3 - 2 = FLOW3 - 3 = CMS - 4 = OPEN SOURCE - } - } - } - - # In Array - 10 = FIELDSET - 10 { - legend = In array test - 10 = TEXTLINE - 10 { - label = Type TYPO3, FLOW3, CMS or OPEN SOURCE here - value = abcde - name = inarray1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/integer.txt b/typo3/sysext/form/Documentation/Tests/Validation/integer.txt deleted file mode 100644 index edb52352c3a116266ff80ff0f2c3a53e6a27adb0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/integer.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.integer = FORM -form.validation.integer { - method = post - - rules { - 1 = integer - 1 { - element = integer1 - } - } - - # Integer - 10 = FIELDSET - 10 { - legend = Integer test - 10 = TEXTLINE - 10 { - label = Type an integer - value = abcde - name = integer1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/ip.txt b/typo3/sysext/form/Documentation/Tests/Validation/ip.txt deleted file mode 100644 index d8005a3fad4ac2aa73bdf956f17e980dc0d0435d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/ip.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.ip = FORM -form.validation.ip { - method = post - - rules { - 1 = ip - 1 { - element = ip1 - } - } - - # IP - 10 = FIELDSET - 10 { - legend = IP test - 10 = TEXTLINE - 10 { - label = Type an IP - value = abcde - name = ip1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/length.txt b/typo3/sysext/form/Documentation/Tests/Validation/length.txt deleted file mode 100644 index fd9cdcdb5e525404ddf065af452b7d8f6e95fc55..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/length.txt +++ /dev/null @@ -1,45 +0,0 @@ -form.validation.length = FORM -form.validation.length { - method = post - - rules { - 1 = length - 1 { - element = length1 - minimum = 6 - } - 2 = length - 2 { - element = length2 - minimum = 2 - maximum = 4 - } - } - - # Length - 10 = FIELDSET - 10 { - legend = Length test - 10 = TEXTLINE - 10 { - label = Only minimum - value = abcde - name = length1 - } - 20 = TEXTLINE - 20 { - label = Minimum and maximum - value = abcde - name = length2 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/lessthan.txt b/typo3/sysext/form/Documentation/Tests/Validation/lessthan.txt deleted file mode 100644 index e2a80edea896a7296c571c6939f3994c8279b58f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/lessthan.txt +++ /dev/null @@ -1,33 +0,0 @@ -form.validation.lessthan = FORM -form.validation.lessthan { - method = post - - rules { - 1 = lessthan - 1 { - element = lessthan1 - maximum = 10 - } - } - - # Less than - 10 = FIELDSET - 10 { - legend = Less than test - 10 = TEXTLINE - 10 { - label = Less than - value = abcde - name = lessthan1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/regexp.txt b/typo3/sysext/form/Documentation/Tests/Validation/regexp.txt deleted file mode 100644 index 21cf11f9d8e5dbae8035b7196d1d4524b1635d6f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/regexp.txt +++ /dev/null @@ -1,33 +0,0 @@ -form.validation.regexp = FORM -form.validation.regexp { - method = post - - rules { - 1 = regexp - 1 { - element = regexp1 - expression = /\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b/ - } - } - - # Regexp - 10 = FIELDSET - 10 { - legend = Regexp test - 10 = TEXTLINE - 10 { - label = IP number - value = abcde - name = regexp1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/required.txt b/typo3/sysext/form/Documentation/Tests/Validation/required.txt deleted file mode 100644 index 8c01e733a989e36f61bcfa1c5e33398ec794636c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/required.txt +++ /dev/null @@ -1,31 +0,0 @@ -form.validation.required = FORM -form.validation.required { - method = post - - rules { - 1 = required - 1 { - element = required1 - } - } - - # Required - 10 = FIELDSET - 10 { - legend = Required test - 10 = TEXTLINE - 10 { - label = Leave empty to trigger error - name = required1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Documentation/Tests/Validation/uri.txt b/typo3/sysext/form/Documentation/Tests/Validation/uri.txt deleted file mode 100644 index 386c975451e084deeebbd48d7fd348a19c67beba..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Documentation/Tests/Validation/uri.txt +++ /dev/null @@ -1,32 +0,0 @@ -form.validation.uri = FORM -form.validation.uri { - method = post - - rules { - 1 = uri - 1 { - element = uri1 - } - } - - # URI - 10 = FIELDSET - 10 { - legend = URI test - 10 = TEXTLINE - 10 { - label = URI - value = abcde - name = uri1 - } - } - - # Submit - 40 = FIELDSET - 40 { - 10 = SUBMIT - 10 { - value = Submit - } - } -} \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Layouts/FormEditor.html b/typo3/sysext/form/Resources/Private/Backend/Layouts/FormEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..9fcdc2812e8e30a8a5153d3640fae16841865312 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Layouts/FormEditor.html @@ -0,0 +1,54 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} +{namespace formvh = TYPO3\CMS\Form\ViewHelpers} + +<formvh:be.pageRenderer + loadExtJsTheme="false" + loadJQuery="true" + includeCssFiles="{stylesheets}" + addInlineSettings="{addInlineSettings}" + includeJsFiles="{0: 'EXT:backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js'}" +/> + +<div data-identifier="moduleLoadingIndicator" class="form-editor-loading-spinner"> + <core:icon identifier="spinner-circle-dark" size="default" /> + <div class="form-editor-loading-spinner-label"><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.loading" /></div> +</div> + +<div data-identifier="moduleWrapper" class="hidden"> + <f:for each="{formEditorTemplates}" key="formEditorTemplateName" as="formEditorTemplate"> + <script type="text/x-formeditor-template" data-template-name="{formEditorTemplateName}"> + <f:format.raw>{formEditorTemplate}</f:format.raw> + </script> + </f:for> + + <section id="t3-form-navigation-component" class="t3-form-x-component" data-identifier="structureSection"> + <div id="t3-form-structure-panel"> + <f:render section="ElementSidebarTree"/> + </div> + </section> + + <section id="t3-form-stage-container" data-identifier="stageContainer"> + <div id="t3-form-stage-inner-container"> + <header id="t3-form-stage-header"> + <f:render section="Header"/> + </header> + <div id="t3-form-stage-content"> + <f:render section="Stage"/> + </div> + </div> + </section> + + <section id="t3-form-inspector-panels-container" class="t3-form-x-component" data-identifier="inspectorSection"> + <f:render section="Inspector"/> + </section> +</div> + +<script type="text/javascript"> + require(['{dynamicRequireJsModules.app}', '{dynamicRequireJsModules.mediator}', '{dynamicRequireJsModules.viewModel}'], function (formEditorApp, mediator, viewModel) { + window.TYPO3.FORMEDITOR_APP = formEditorApp.getInstance( + <f:format.htmlentitiesDecode>{formEditorAppInitialData}</f:format.htmlentitiesDecode>, + mediator, + viewModel + ).run(); + }); +</script> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Layouts/FormManager.html b/typo3/sysext/form/Resources/Private/Backend/Layouts/FormManager.html new file mode 100644 index 0000000000000000000000000000000000000000..3d0054fb9b68b43bfee354796df0a8222a6aef6a --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Layouts/FormManager.html @@ -0,0 +1,7 @@ +<f:be.pageRenderer + loadExtJsTheme="false" + includeCssFiles="{stylesheets}" +/> + +<f:flashMessages class="flashmessages" /> +<f:render section="MainContent" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/FileUploadTemplate.html b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/FileUploadTemplate.html new file mode 100644 index 0000000000000000000000000000000000000000..7ded50d8f187f760a55fcad0a185d286a6d0aa71 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/FileUploadTemplate.html @@ -0,0 +1,33 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + <div class="element-content"> + <div data-template-property="properties.saveToFileMount" /> + <div data-identifier="multiValueContainer" data-template-property="properties.allowedMimeTypes"> + <div data-template-property="_value" /> + </div> + </div> + </div> + + <div class="t3-form-validator-info" data-identifier="validators"> + <span data-identifier="validatorIcon"></span> + <div class="t3-form-validator-list"> + <div data-identifier="validatorsContainer"> + <div class="validator-label" data-template-property="_label"></div> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SelectTemplate.html b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SelectTemplate.html new file mode 100644 index 0000000000000000000000000000000000000000..878e58060910a0dbe29e2d87d69138cd0a5132ff --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SelectTemplate.html @@ -0,0 +1,32 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + <div class="element-content"> + <div data-identifier="multiValueContainer" data-template-property="properties.options"> + <div data-template-property="_label"></div> + </div> + </div> + </div> + + <div class="t3-form-validator-info" data-identifier="validators"> + <span data-identifier="validatorIcon"></span> + <div class="t3-form-validator-list"> + <div data-identifier="validatorsContainer"> + <div class="validator-label" data-template-property="_label"></div> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SimpleTemplate.html b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SimpleTemplate.html new file mode 100644 index 0000000000000000000000000000000000000000..c2a539144515d3eb181a8a67a346bd7a92f01a88 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Partials/FormEditor/Stage/SimpleTemplate.html @@ -0,0 +1,27 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + </div> + + <div class="t3-form-validator-info" data-identifier="validators"> + <span data-identifier="validatorIcon"></span> + <div class="t3-form-validator-list"> + <div data-identifier="validatorsContainer"> + <div class="validator-label" data-template-property="_label"></div> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Index.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Index.html new file mode 100644 index 0000000000000000000000000000000000000000..2dec63446d1a30afa8fb19a224998fb5b5b477db --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Index.html @@ -0,0 +1,64 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<f:layout name="FormEditor" /> + +<f:section name="ElementSidebarTree"> + <div class="t3-form-x-component-inner-wrapper"> + <div id="t3-form-navigation-component-tree-root-container" data-identifier="treeRootContainer"> + <core:icon identifier="content-elements-mailform" /> + <span id="t3-form-navigation-component-tree-root" data-identifier="treeRootElement"></span> + </div> + <div class="tree" data-identifier="structure-element"></div> + <div class="form-group col-sm-12"> + <div class="btn-group btn-group-sm" role="group"> + <a class="btn btn-default t3-form-element-new-page-button" href="#" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.new_page_button')}" data-identifier="treeNewPageBottom"><core:icon identifier="actions-page-new" /> {f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.new_page_button')}</a> + </div> + </div> + </div> +</f:section> + +<f:section name="Header"> + <h1><span id="t3-form-form-definition-label" data-identifier="formDefinitionLabel"></span></h1> +</f:section> + +<f:section name="Stage"> + <div class="panel panel-default" data-identifier="stagePanel"> + <div class="panel-heading" data-identifier="panelHeading"> + <span data-identifier="stageHeaderToolbar"> + <div class="btn-group"> + <button class="btn btn-default" title="" data-identifier="buttonViewModePreview"><core:icon identifier="actions-document-view" alternativeMarkupIdentifier="inline" /></button> + <button class="btn btn-default" title="" data-identifier="buttonViewModeAbstract"><core:icon identifier="actions-document-open" alternativeMarkupIdentifier="inline" /></button> + </div> + <div class="pull-right"> + <span class="paginiation-label" data-identifier="paginationTitle"></span> + <div class="btn-group"> + <button class="btn btn-default" title="" data-identifier="buttonPaginationPrevious"><core:icon identifier="actions-view-paging-previous" alternativeMarkupIdentifier="inline" /></button> + <button class="btn btn-default" title="" data-identifier="buttonPaginationNext"><core:icon identifier="actions-view-paging-next" alternativeMarkupIdentifier="inline" /></button> + </div> + </div> + </span> + </div> + <div class="form-section" data-identifier="stageSection"> + <div class="row"> + <div id="t3-form-stage" class="form-group col-sm-12" data-identifier="stageArea"></div> + </div> + <div class="row" data-identifier="stageNewElementRow"> + <div class="form-group col-sm-12"> + <div class="t3-form-new-element-container"> + <div class="btn-group btn-group-sm" role="group"> + <a class="btn btn-default" href="#" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element')}" data-identifier="stageNewElementBottom"><core:icon identifier="actions-document-new" /> {f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element')}</a> + </div> + </div> + </div> + </div> + </div> + </div> +</f:section> + +<f:section name="Inspector"> + <div id="t3-form-inspector-panels"> + <div class="t3-form-x-component-inner-wrapper"> + <div id="t3-form-inspector" data-identifier="inspector"></div> + </div> + </div> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CheckboxEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CheckboxEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..40f29ea016b11f26fa2fdc36b68419dffe43f057 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CheckboxEditor.html @@ -0,0 +1,10 @@ +<div class="form-editor"> + <div class="t3-form-control-group form-group"> + <label> + <span data-template-property="label" /> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <input type="checkbox" /> + </div> + </label> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CollectionElementHeaderEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CollectionElementHeaderEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..5c2c4649af05c26cc673a76c461b82c1746573dd --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/CollectionElementHeaderEditor.html @@ -0,0 +1,5 @@ +<div class="t3-form-validator-editor"> + <h4 data-template-property="header-label"> + <span data-template-property="label" /> + </h4> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FinishersEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FinishersEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..1c0b4cb724df63c746b24ce674852e03b4a71233 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FinishersEditor.html @@ -0,0 +1,8 @@ +<div class="form-editor"> + <h3><span data-template-property="label" /></h3> + <div id="t3-form-add-finisher" class="t3-form-add-collection-element"> + <select data-template-property="selectOptions" class="form-control" /> + </div> +</div> +<div id="t3-form-inspector-finishers" class="t3-form-collection-container" data-identifier="inspectorFinishers"> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FormElementHeaderEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FormElementHeaderEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..fd3b22694747ead33a75b27d39e04f3f52c71b63 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/FormElementHeaderEditor.html @@ -0,0 +1,3 @@ +<div class="form-editor"> + <h2 class="t3-form-inspector-formelement-header-editor" data-template-property="header-label" data-identifier="inspectorFormElementHeaderEditor"></h2> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/PropertyGridEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/PropertyGridEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..287b32d90f99e543c9ff496025fe5bd8b36d8d02 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/PropertyGridEditor.html @@ -0,0 +1,47 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<div class="form-editor"> + <div class="t3-form-control-group form-group property-grid"> + <label><span data-template-property="label" /></label> + <div data-editor="new-property-grid" data-template-property="newPropertyPath"> + + <table class="table table-hover" data-identifier="propertyGridContainer"> + <thead> + <tr> + <th></th> + <th>Label</th> + <th>Value</th> + <th>Selected</th> + <th></th> + </tr> + </thead> + <tbody> + <tr data-identifier="rowItem"> + <td><span class="sort-row-field" data-identifier="sortRow"><core:icon identifier="actions-move-move" /></span></td> + <td><input type="text" class="form-control" value="" data-identifier="label" /></td> + <td><input type="text" class="form-control" value="" data-identifier="value" /></td> + <td><input type="checkbox" data-identifier="selectValue" /></td> + <td> + <div class="btn-group btn-group-sm" role="group"> + <button class="btn btn-default" title="Remove this row" data-identifier="deleteRow"><core:icon identifier="actions-delete" /></button> + </div> + </td> + </tr> + <tr data-identifier="addRowItem"> + <td> + <div class="btn-group btn-group-sm" role="group"> + <button class="btn btn-default" title="Add a new row" data-identifier="addRow"><core:icon identifier="actions-add" /></button> + </div> + </td> + <td></td> + <td></td> + <td></td> + <td></td> + </tr> + </tbody> + </table> + + </div> + <div data-editor="property-grid" data-template-property="propertyPath" class="t3-form-grid" /> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RemoveElementEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RemoveElementEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..afa20c43f2206876559274e6b77c76e61d7a3422 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RemoveElementEditor.html @@ -0,0 +1,5 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<div class="t3-form-control-group form-group btn-group-sm"> + <button class="btn btn-default" title="Remove this Element"><core:icon identifier="actions-delete" alternativeMarkupIdentifier="inline"/></button> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RequiredValidatorEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RequiredValidatorEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..40f29ea016b11f26fa2fdc36b68419dffe43f057 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/RequiredValidatorEditor.html @@ -0,0 +1,10 @@ +<div class="form-editor"> + <div class="t3-form-control-group form-group"> + <label> + <span data-template-property="label" /> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <input type="checkbox" /> + </div> + </label> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/SingleSelectEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/SingleSelectEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..f1f9653c5692b056bcb8711d024e0848fc0b8488 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/SingleSelectEditor.html @@ -0,0 +1,6 @@ +<div class="t3-form-control-group form-group"> + <label><span data-template-property="label" /></label> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <select data-template-property="selectOptions" class="form-control" /> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..e74c2b2f4845d4cdceacca7071c86fb8cc91861b --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextEditor.html @@ -0,0 +1,10 @@ +<div class="form-editor"> + <div class="t3-form-control-group form-group"> + <label><span data-template-property="label" /></label> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <input type="text" value="" data-template-property="propertyPath" class="form-control"> + <span data-template-property="fieldExplanationText" /> + <span data-template-property="validationErrors" /> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextareaEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextareaEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..31e261e24a78b0a3b4e60d48411a277cefd14e66 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/TextareaEditor.html @@ -0,0 +1,8 @@ +<div class="form-editor"> + <div class="t3-form-control-group form-group"> + <label><span data-template-property="label" /></label> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <textarea data-template-property="propertyPath" class="form-control" /> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/Typo3WinBrowserEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/Typo3WinBrowserEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..66dd258bed107f2cdce40cb034a878024f3d595a --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/Typo3WinBrowserEditor.html @@ -0,0 +1,17 @@ +<div class="form-editor"> + <div class="t3-form-control-group form-group"> + <label><span data-template-property="label" /></label> + <div class="t3-form-controls" data-identifier="inspectorEditorControlsWrapper"> + <input type="text" value="" data-template-property="propertyPath" class="form-control" data-insert-target=""> + <div class="help-block"> + <a href="#" data-template-property="onclick" class="btn btn-default"> + <span class="t3js-icon icon icon-size-small icon-state-default icon-mimetypes-x-content-text" data-identifier="mimetypes-x-content-text"> + <span class="icon-markup" data-template-property="image" /> + </span> <span data-template-property="buttonLabel" /> + </a> + </div> + <span data-template-property="fieldExplanationText" /> + <span data-template-property="validationErrors" /> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/ValidatorsEditor.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/ValidatorsEditor.html new file mode 100644 index 0000000000000000000000000000000000000000..6d61b5b0bf2376eb69a5eb13c60d8618b420bb45 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Inspector/ValidatorsEditor.html @@ -0,0 +1,8 @@ +<div class="form-editor"> + <h3><span data-template-property="label" /></h3> + <div id="t3-form-add-validator" class="t3-form-add-collection-element"> + <select data-template-property="selectOptions" class="form-control" /> + </div> +</div> +<div id="t3-form-inspector-validators" class="t3-form-collection-container" data-identifier="inspectorValidators"> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertElements.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertElements.html new file mode 100644 index 0000000000000000000000000000000000000000..1d3c65f09421f3fd814c20a974a327023cd3ed80 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertElements.html @@ -0,0 +1,30 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<div id="t3-form-insert-elements-panel"> + <div class="t3-form-x-component-inner-wrapper"> + <f:for each="{insertRenderablesPanelConfiguration}" as="insertRenderablePanelConfiguration"> + <f:if condition="{insertRenderablePanelConfiguration.key} != 'page'"> + <div class="row"> + <div class="col-sm-12"> + <h4 class="t3-form-group-{insertRenderablePanelConfiguration.key}"> + <span>{insertRenderablePanelConfiguration.label}</span> + </h4> + </div> + <f:for each="{insertRenderablePanelConfiguration.elements}" as="element"> + <div class="col-sm-4 btn-group"> + <a class="t3-form-group-{insertRenderablePanelConfiguration.key} t3-form-type-{element.cssKey} btn btn-default btn-block" title="{element.key}" data-element-type="{element.key}"> + <span class="pull-left"> + <core:icon identifier="{element.iconIdentifier}" alternativeMarkupIdentifier="inline" /> + <span>{element.label}</span> + </span> + <span class="clearfix"></span> + </a> + <hr /> + </div> + </f:for> + </div> + <hr /> + </f:if> + </f:for> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertPages.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertPages.html new file mode 100644 index 0000000000000000000000000000000000000000..2f4e0b90322a64463ed8087cbc63331a2a8dc7be --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/InsertPages.html @@ -0,0 +1,26 @@ +<div id="t3-form-insert-pages-panel"> + <div class="t3-form-x-component-inner-wrapper"> + <f:for each="{insertRenderablesPanelConfiguration}" as="insertRenderablePanelConfiguration"> + <f:if condition="{insertRenderablePanelConfiguration.key} == 'page'"> + <div class="row"> + <div class="col-sm-12"> + <h3 class="t3-form-group-{insertRenderablePanelConfiguration.key}"> + <span>{insertRenderablePanelConfiguration.label}</span> + </h3> + </div> + <f:for each="{insertRenderablePanelConfiguration.elements}" as="element"> + <div class="col-sm-4 btn-group"> + <a class="t3-form-group-{insertRenderablePanelConfiguration.key} t3-form-type-{element.cssKey} btn btn-default btn-block" title="{element.key}" data-element-type="{element.key}"> + <span class="pull-left"> + <core:icon identifier="{element.iconIdentifier}" alternativeMarkupIdentifier="inline" /> + <span>{element.label}</span> + </span> + <span class="clearfix"></span> + </a> + <hr /> + </div> + </f:for> + </f:if> + </f:for> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/ValidationErrors.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/ValidationErrors.html new file mode 100644 index 0000000000000000000000000000000000000000..24867aa45fe360dcd4ce14ec8bf563ef72537a77 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Modals/ValidationErrors.html @@ -0,0 +1,17 @@ +<div id="t3-form-validation-errors-panel"> + <div class="t3-form-x-component-inner-wrapper"> + <div class="row"> + <div class="col-sm-12"> + <p><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.modals.validationErrors.dialogMessage" /></p> + </div> + + <div class="col-sm-12"> + <dl class="t3-overview-list" data-identifier="rowsContainer"> + <dt data-identifier="rowItem"> + <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> <a data-identifier="rowLink"></a> + </dt> + </dl> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/AdvancedPassword.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/AdvancedPassword.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/AdvancedPassword.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Checkbox.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Checkbox.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Checkbox.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ContentElement.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ContentElement.html new file mode 100644 index 0000000000000000000000000000000000000000..ac4e0dd62f978af5a4ee83b524131b3cbb3cc468 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ContentElement.html @@ -0,0 +1,30 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + <div class="element-content"> + <div data-template-property="properties.contentElementUid" /> + </div> + </div> + + <div class="t3-form-validator-info" data-identifier="validators"> + <span data-identifier="validatorIcon"></span> + <div class="t3-form-validator-list"> + <div data-identifier="validatorsContainer"> + <div class="validator-label" data-template-property="_label"></div> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/DatePicker.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/DatePicker.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/DatePicker.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Fieldset.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Fieldset.html new file mode 100644 index 0000000000000000000000000000000000000000..b4e6dcfeb6807178f5c0052de2bef1223010ca50 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Fieldset.html @@ -0,0 +1,18 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/FileUpload.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/FileUpload.html new file mode 100644 index 0000000000000000000000000000000000000000..e476819a1f04275a6ae4b4dad1a388638e886514 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/FileUpload.html @@ -0,0 +1 @@ +<f:render partial="Stage/FileUploadTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Hidden.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Hidden.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Hidden.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ImageUpload.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ImageUpload.html new file mode 100644 index 0000000000000000000000000000000000000000..e476819a1f04275a6ae4b4dad1a388638e886514 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/ImageUpload.html @@ -0,0 +1 @@ +<f:render partial="Stage/FileUploadTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiCheckbox.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiCheckbox.html new file mode 100644 index 0000000000000000000000000000000000000000..fbdd4da477ba9f597f5224f5c9cccebf141de1bb --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiCheckbox.html @@ -0,0 +1 @@ +<f:render partial="Stage/SelectTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiSelect.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiSelect.html new file mode 100644 index 0000000000000000000000000000000000000000..fbdd4da477ba9f597f5224f5c9cccebf141de1bb --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/MultiSelect.html @@ -0,0 +1 @@ +<f:render partial="Stage/SelectTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Page.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Page.html new file mode 100644 index 0000000000000000000000000000000000000000..aa5e8817b998251bcebb536b7c01551f61f61439 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Page.html @@ -0,0 +1 @@ +<h2 class="t3-form-page-title" data-template-property="label"></h2> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Password.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Password.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Password.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/RadioButton.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/RadioButton.html new file mode 100644 index 0000000000000000000000000000000000000000..fbdd4da477ba9f597f5224f5c9cccebf141de1bb --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/RadioButton.html @@ -0,0 +1 @@ +<f:render partial="Stage/SelectTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SingleSelect.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SingleSelect.html new file mode 100644 index 0000000000000000000000000000000000000000..fbdd4da477ba9f597f5224f5c9cccebf141de1bb --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SingleSelect.html @@ -0,0 +1 @@ +<f:render partial="Stage/SelectTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/StaticText.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/StaticText.html new file mode 100644 index 0000000000000000000000000000000000000000..b9520b171c26bee4f44bef21bbe06d3f4a71b26b --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/StaticText.html @@ -0,0 +1,30 @@ +<div class="meta-label"> + <span data-template-property="_type"></span>: <span data-template-property="_identifier"></span> +</div> + +<div class="t3-form-form-element-body"> + <div class="t3-form-icon-container"> + <span data-identifier="elementIcon"></span> + </div> + + <div class="t3-form-element-info"> + <div class="element-label-container"> + <div class="element-label"> + <span data-template-property="label"></span> + <span data-template-property="_required"></span> + </div> + </div> + <div class="element-content"> + <div data-template-property="properties.text" /> + </div> + </div> + + <div class="t3-form-validator-info" data-identifier="validators"> + <span data-identifier="validatorIcon"></span> + <div class="t3-form-validator-list"> + <div data-identifier="validatorsContainer"> + <div class="validator-label" data-template-property="_label"></div> + </div> + </div> + </div> +</div> diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SummaryPage.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SummaryPage.html new file mode 100644 index 0000000000000000000000000000000000000000..ccd6afd0873039d89ba683c61363fc428cebf7be --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/SummaryPage.html @@ -0,0 +1 @@ +<h2 data-template-property="label"></h2> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Text.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Text.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Text.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Textarea.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Textarea.html new file mode 100644 index 0000000000000000000000000000000000000000..ececec82bde6c1a5aa7ce081876c347518d90406 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/Textarea.html @@ -0,0 +1 @@ +<f:render partial="Stage/SimpleTemplate" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_ElementToolbar.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_ElementToolbar.html new file mode 100644 index 0000000000000000000000000000000000000000..6b6f071ceb11105a7e2cf3167ecf314116af360b --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_ElementToolbar.html @@ -0,0 +1,35 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<div class="btn-toolbar-container" data-identifier="elementToolbar"> + <div class="btn-toolbar" data-identifier="elementToolbarButtons"> + <div class="btn-group btn-group-sm" role="group"> + <a class="btn btn-default" href="#" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element')}" data-identifier="stageElementToolbarNewElement"><core:icon identifier="actions-document-new" alternativeMarkupIdentifier="inline" /></a> + </div> + <div class="btn-group btn-group-sm" role="group"> + <div class="btn-group t3-form-dropdown-buttons" data-identifier="stageElementToolbarNewElementSplitButton"> + <button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element')}"> + <core:icon identifier="actions-document-new" alternativeMarkupIdentifier="inline" /> + <span class="caret"></span> + <span class="sr-only">Toggle Dropdown</span> + </button> + <ul class="dropdown-menu"> + <li data-no-sorting> + <a href="#" data-identifier="stageElementToolbarNewElementSplitButtonInside"> + <core:icon identifier="t3-form-icon-insert-in" alternativeMarkupIdentifier="inline" /> + <f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element.inside" /> + </a> + </li> + <li data-no-sorting> + <a href="#" data-identifier="stageElementToolbarNewElementSplitButtonAfter"> + <core:icon identifier="t3-form-icon-insert-after" alternativeMarkupIdentifier="inline" /> + <f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.new_element.after" /> + </a> + </li> + </ul> + </div> + </div> + <div class="btn-group btn-group-sm" role="group"> + <a class="btn btn-default" href="#" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.stage.toolbar.remove')}" data-identifier="stageElementToolbarRemoveElement"><core:icon identifier="actions-edit-delete" alternativeMarkupIdentifier="inline" /></a> + </div> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_UnknownElement.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_UnknownElement.html new file mode 100644 index 0000000000000000000000000000000000000000..31d9a2e7d15f6dac3d0eb2393d665899effbebdf --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Stage/_UnknownElement.html @@ -0,0 +1 @@ +<span><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.elements.UnknownElement" /></span> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5a1b08a10dccd7a9a199ebbda32550770e0e49a2 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml @@ -0,0 +1,8 @@ +type: 'Form' +identifier: 'blankForm' +label: '[Blank Form]' +renderables: + - + type: 'Page' + identifier: 'page-1' + label: 'Page' \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4e217ea03baca86c6fad60929cf6c47680927bae --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml @@ -0,0 +1,75 @@ +identifier: ext-form-simple-contact-form-example +label: 'Simple Contact Form' +type: Form + +finishers: + - + identifier: EmailToReceiver + options: + subject: 'Your message: {subject}' + recipientAddress: 'your.company@example.com' + recipientName: 'Your Company name' + senderAddress: '{email}' + senderName: '{name}' + replyToAddress: '' + carbonCopyAddress: '' + blindCarbonCopyAddress: '' + format: 'html' + attachUploads: 'true' + translation: + language: '' + +renderables: + - + identifier: page-1 + label: 'Contact Form' + type: Page + + renderables: + - + identifier: name + label: 'Name' + type: Text + properties: + placeholder: 'Name' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: subject + label: 'Subject' + type: Text + properties: + placeholder: 'Subject' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: email + label: 'Email' + type: Text + properties: + placeholder: 'Email address' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: EmailAddress + - + identifier: message + label: 'Message' + type: Textarea + properties: + placeholder: '' + defaultValue: '' + validators: + - + identifier: NotEmpty + + - + identifier: summarypage + label: 'Summary page' + type: SummaryPage diff --git a/typo3/sysext/form/Resources/Private/Backend/Templates/FormManager/Index.html b/typo3/sysext/form/Resources/Private/Backend/Templates/FormManager/Index.html new file mode 100644 index 0000000000000000000000000000000000000000..cacc99f8dcdedec66b0ddaa2a0f27fa3fc2432fa --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Backend/Templates/FormManager/Index.html @@ -0,0 +1,110 @@ +{namespace core = TYPO3\CMS\Core\ViewHelpers} + +<f:layout name="FormManager" /> + +<f:section name="MainContent"> + <script type="text/javascript"> + require(['{dynamicRequireJsModules.app}', '{dynamicRequireJsModules.viewModel}'], function (formManagerApp, viewModel) { + var FORMMANAGER_APP = formManagerApp.getInstance( + <f:format.htmlentitiesDecode>{formManagerAppInitialData}</f:format.htmlentitiesDecode>, + viewModel + ).run(); + }); + </script> + + <h1><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.headline" /></h1> + + <f:if condition="{forms}"> + <f:then> + <div class="panel panel-space panel-default recordlist"> + <div class="panel-heading"> + <span><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.edit_existing_forms" /></span> + </div> + <div class="collapse in"> + <div class="table-fit"> + <table id="forms" class="table table-striped table-hover"> + <thead> + <tr> + <th nowrap="nowrap" class="col-icon"><a class="btn btn-default" data-identifier="newForm" href="#"><core:icon identifier="actions-add" /></a></th> + <th nowrap="nowrap" class="col-title col-responsive"><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.form_name" /></th> + <th nowrap="nowrap" class="col-control"></th> + <th nowrap="nowrap"><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.location" /></th> + <th nowrap="nowrap"><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.references" /></th> + </tr> + </thead> + <tbody> + <f:for each="{forms}" as="form"> + <tr> + <td nowrap="nowrap" class="col-icon"> + <f:if condition="{form.duplicateIdentifier}"> + <f:then> + <span title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.duplicate_identifier')} {form.identifier}" data-toggle="tooltip" data-placement="top"> + <core:icon identifier="overlay-missing" /> + </span> + </f:then> + <f:else> + <span title="id={form.identifier}" data-toggle="tooltip" data-placement="right"> + <core:icon identifier="content-elements-mailform" /> + </span> + </f:else> + </f:if> + </td> + <td nowrap="nowrap" class="col-title col-responsive"> + <f:if condition="{form.readOnly}"> + <f:then> + <div>{form.name}</div> + </f:then> + <f:else> + <f:link.action controller="FormEditor" action="index" arguments="{formPersistenceIdentifier: form.persistenceIdentifier}" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.edit_form')}" data="{toggle: 'tooltip', placement: 'right'}">{form.name}</f:link.action> + </f:else> + </f:if> + + </td> + <td nowrap="nowrap" class="col-control"> + <div class="btn-group" role="group"> + <f:if condition="{form.readOnly}"> + <f:then> + <button class="btn btn-default form-record-readonly" disabled="disabled" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.edit_form_not_allowed')}"><core:icon identifier="actions-open" /></button> + </f:then> + <f:else> + <f:link.action controller="FormEditor" action="index" arguments="{formPersistenceIdentifier: form.persistenceIdentifier}" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.edit_form')}" class="btn btn-default form-record-open"><core:icon identifier="actions-open" /></f:link.action> + </f:else> + </f:if> + <a href="#" data-identifier="duplicateForm" data-form-persistence-identifier="{form.persistenceIdentifier}" data-form-name="{form.name}" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.duplicate_this_form')}" class="btn btn-default form-record-duplicate"><core:icon identifier="t3-form-icon-duplicate" /></a> + <f:if condition="{form.location} === 'storage'"> + <f:then> + <a href="#" data-identifier="removeForm" data-form-persistence-identifier="{form.persistenceIdentifier}" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.delete_form')}" class="btn btn-default form-record-delete"><core:icon identifier="actions-edit-delete" /></a> + </f:then> + <f:else> + <button class="btn btn-default form-record-delete" disabled="disabled" title="{f:translate(key: 'LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.delete_form_not_allowed')}"><core:icon identifier="actions-edit-delete" /></button> + </f:else> + </f:if> + </div> + </td> + <td nowrap="nowrap">{form.persistenceIdentifier}</td> + <td nowrap="nowrap"> + <f:if condition="{form.referenceCount}"> + <f:then> + <a href="#" data-identifier="showReferences" data-form-persistence-identifier="{form.persistenceIdentifier}" data-form-name="{form.name}">{form.referenceCount}</a> + </f:then> + <f:else> + {form.referenceCount} + </f:else> + </f:if> + </td> + </tr> + </f:for> + </tbody> + </table> + </div> + </div> + </div> + </f:then> + <f:else> + <f:be.infobox title="{f:translate(key: 'formManager.no_forms', extensionName:'form')}" state="-1"> + <p><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.no_forms"/></p> + <a class="btn btn-primary" data-identifier="newForm" href="#"><f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.create_new_form"/></a> + </f:be.infobox> + </f:else> + </f:if> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Layouts/FormElements/Field.html b/typo3/sysext/form/Resources/Private/Frontend/Layouts/FormElements/Field.html new file mode 100644 index 0000000000000000000000000000000000000000..0002b904387d387d1e92aedf7ed509c9a0592cc8 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Layouts/FormElements/Field.html @@ -0,0 +1,22 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<div class="form-group"> + <label for="{element.uniqueIdentifier}">{formvh:translateElementProperty(element: element, property: 'label')}<f:if condition="{element.required}"><f:render partial="Field/Required" /></f:if></label> + <div class="{element.properties.containerClassAttribute}"> + <f:render section="field" /> + <f:format.raw> + <f:form.validationResults for="{element.identifier}"> + <f:if condition="{validationResults.flattenedErrors}"> + <span class="form-control-feedback error help-inline"> + <f:for each="{validationResults.errors}" as="error"> + {error -> f:translate(key: '{element.renderingOptions.translation.translationFile}:validation.error.{error.code}', arguments: error.arguments)} + <br /> + </f:for> + </span> + </f:if> + </f:form.validationResults> + </f:format.raw> + <f:if condition="{element.properties.elementDescription}"> + <span class="help-block">{formvh:translateElementProperty(element: element, property: 'elementDescription')}</span> + </f:if> + </div> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Field/Required.html b/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Field/Required.html new file mode 100644 index 0000000000000000000000000000000000000000..b8618a87e9c68bb89d5b9284545437dfa406ce2e --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Field/Required.html @@ -0,0 +1 @@ +<span class="required">*</span> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Form/Navigation.html b/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Form/Navigation.html new file mode 100644 index 0000000000000000000000000000000000000000..154f80c5eed151b7ef0790aa49f9a89b026cdea0 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Partials/FormElements/Form/Navigation.html @@ -0,0 +1,25 @@ +<nav class="form-navigation"> + <div class="btn-toolbar" role="toolbar"> + <div class="btn-group" role="group"> + <f:if condition="{form.previousPage}"> + <span class="previous"> + <f:form.button property="__currentPage" value="{form.previousPage.index}" class="btn btn-cancel">{formvh:translateElementProperty(element: form.currentPage, renderingOptionProperty: 'previousButtonLabel')}</f:form.button> + </span> + </f:if> + <f:if condition="{form.nextPage}"> + <f:then> + <span class="next"> + <f:form.button property="__currentPage" value="{form.nextPage.index}" class="btn btn-primary">{formvh:translateElementProperty(element: form.currentPage, renderingOptionProperty: 'nextButtonLabel')}</f:form.button> + </span> + </f:then> + <f:else> + <span class="next submit"> + <f:form.button property="__currentPage" value="{form.pages -> f:count()}" class="btn btn-primary"> + {formvh:translateElementProperty(element: form, renderingOptionProperty: 'submitButtonLabel')} + </f:form.button> + </span> + </f:else> + </f:if> + </div> + </div> +</nav> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Html.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Html.html new file mode 100644 index 0000000000000000000000000000000000000000..dce25de4ddadeb9d16e9087d570a413baa51157a --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Html.html @@ -0,0 +1,48 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> + +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} + +<html> +<head> + <title></title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="format-detection" content="telephone=no"> +</head> + +<body> + <table width="600" cellpadding="0" cellspacing="0" border="0"> + <formvh:renderAllFormValues renderable="{form.formDefinition}" formRuntime="{form}"> + <tr> + <td width="600" valign="top" align="left">{formvh:translateElementProperty(element: formValue.element, property: 'label', formRuntime: form)}</td> + <td width="600" valign="top" align="left"> + <f:if condition="{formValue.value}"> + <f:then> + <f:if condition="{formValue.isMultiValue}"> + <f:then> + <table cellspacing="0" border="0"> + <f:for each="{formValue.processedValue}" as="value"> + <tr> + <td>{value}</td> + </tr> + </f:for> + </table> + </f:then> + <f:else> + <table cellspacing="0" border="0"> + <tr> + <td>{formValue.processedValue}</td> + </tr> + </table> + </f:else> + </f:if> + </f:then> + <f:else> + - + </f:else> + </f:if> + </td> + </tr> + </formvh:renderAllFormValues> + </table> +</body> +</html> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Plaintext.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Plaintext.html new file mode 100644 index 0000000000000000000000000000000000000000..05cde5a0bf8444411d2f486b97130930d5953d44 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/Finishers/Email/Plaintext.html @@ -0,0 +1,3 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} + +<formvh:renderAllFormValues renderable="{form.formDefinition}" formRuntime="{form}"><formvh:plainTextMail formValue="{formValue}" formRuntime="{form}" /></formvh:renderAllFormValues> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/AdvancedPassword.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/AdvancedPassword.html new file mode 100644 index 0000000000000000000000000000000000000000..05a9f1da31cbd421f6ae6aa92f60e28fc42fd0f9 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/AdvancedPassword.html @@ -0,0 +1,28 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <div class="form-group"> + <f:form.password + property="{element.identifier}.password" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute} form-control" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\', placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}', else: '{placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}')}" + /> + <f:if condition="{formvh:translateElementProperty(element: element, property: 'passwordDescription')}"> + <span class="help-block">{formvh:translateElementProperty(element: element, property: 'passwordDescription')}</span> + </f:if> + </div> + <div class="form-group"> + <f:if condition="{formvh:translateElementProperty(element: element, property: 'confirmationLabel')}"> + <label for="{element.uniqueIdentifier}-confirmation">{formvh:translateElementProperty(element: element, property: 'confirmationLabel')}<f:if condition="{element.required}"><f:render partial="Field/Required" /></f:if></label> + </f:if> + <f:form.password + property="{element.identifier}.confirmation" + id="{element.uniqueIdentifier}-confirmation" + class="{element.properties.confirmationClassAttribute} form-control" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\', placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}', else: '{placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}')}" + /> + </div> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Checkbox.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Checkbox.html new file mode 100644 index 0000000000000000000000000000000000000000..61e96d2271edf5e1b02cc38dfd2bee0ddfaa81c3 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Checkbox.html @@ -0,0 +1,15 @@ +<f:layout name="Field" /> +<f:section name="field"> + <div class="form-check"> + <label class="{element.properties.elementClassAttribute} form-check-label"> + <f:form.checkbox + property="{element.identifier}" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute}" + value="{element.properties.value}" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" + /> + </label> + </div> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ContentElement.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ContentElement.html new file mode 100644 index 0000000000000000000000000000000000000000..9d1b2d4bb23bd2e467ad6dc4bed4a55bb4a98cd9 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ContentElement.html @@ -0,0 +1,22 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:if condition="{element.rootForm.renderingOptions.previewMode}"> + <f:then> + <div class="clearfix"> + <f:if condition="{element.properties.contentElementUid}"> + <f:then> + <formvh:be.renderContentElementPreview contentElementUid="{element.properties.contentElementUid}" /> + </f:then> + <f:else> + <f:translate key="LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.elements.ContentElement.selectContentElement" /> + </f:else> + </f:if> + </div> + </f:then> + <f:else> + <f:if condition="{element.properties.contentElementUid}"> + <div class="clearfix{f:if(condition: element.properties.elementClassAttribute, then: ' {element.properties.elementClassAttribute}')}"> + <f:cObject typoscriptObjectPath="lib.tx_form.contentElementRendering">{element.properties.contentElementUid}</f:cObject> + </div> + </f:if> + </f:else> +</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/DatePicker.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/DatePicker.html new file mode 100644 index 0000000000000000000000000000000000000000..b1a4e4d93c738e9814263cd7c41b9b8bfc2b9ead --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/DatePicker.html @@ -0,0 +1,47 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <formvh:form.datePicker + id="{element.uniqueIdentifier}" + property="{element.identifier}" + placeholder="{formvh:translateElementProperty(element: element, property: 'placeholder')}" + dateFormat="{element.properties.dateFormat}" + initialDate="{element.properties.initialDate}" + enableDatePicker="{element.properties.enableDatePicker}" + class="{element.properties.elementClassAttribute}" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" + > + <f:if condition="{element.rootForm.renderingOptions.previewMode}"> + <f:else> + <f:if condition="{element.properties.enableDatePicker}"> + <script type="text/javascript"> + if ("undefined" !== typeof $) { + $(function() { + $("#<f:format.raw>{element.uniqueIdentifier}</f:format.raw>").datepicker({ + dateFormat: "<f:format.raw>{datePickerDateFormat}</f:format.raw>" + }).on("keydown", function(e) { + // By using "backspace" or "delete", you can clear the datepicker again. + if(e.keyCode == 8 || e.keyCode == 46) { + e.preventDefault(); + $.datepicker._clearDate(this); + } + }); + }); + } + </script> + </f:if> + </f:else> + </f:if> + </formvh:form.datePicker> + + <f:if condition="{element.properties.displayTimeSelector}"> + <formvh:form.timePicker + id="{element.uniqueIdentifier}-time" + property="{element.identifier}" + initialDate="{element.properties.initialDate}" + class="{element.properties.timeSelectorClassAttribute} form-control" + errorClass="{element.properties.elementErrorClassAttribute}" + /> + </f:if> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Fieldset.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Fieldset.html new file mode 100644 index 0000000000000000000000000000000000000000..89c64c46685e54820f1f2321d0154dfb652199a9 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Fieldset.html @@ -0,0 +1,9 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<fieldset id="{section.uniqueIdentifier}" class="form-group{f:if(condition: section.properties.elementClassAttribute, then: ' {section.properties.elementClassAttribute}')}"> + <f:if condition="{section.label}"> + <legend>{formvh:translateElementProperty(element: section, property: 'label')}</legend> + </f:if> + <f:for each="{section.elements}" as="element"> + <formvh:renderRenderable renderable="{element}" /> + </f:for> +</fieldset> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/FileUpload.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/FileUpload.html new file mode 100644 index 0000000000000000000000000000000000000000..d2774bec03705fa23061b1b20d0a8c325f120cd5 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/FileUpload.html @@ -0,0 +1,11 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <formvh:form.uploadedResource property="{element.identifier}" as="resource" additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" accept="{element.properties.allowedMimeTypes}"> + <f:if condition="{resource}"> + <div id="{element.uniqueIdentifier}-preview"> + {resource.originalResource.originalFile.name} + </div> + </f:if> + </formvh:form.uploadedResource> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Form.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Form.html new file mode 100644 index 0000000000000000000000000000000000000000..e4c950a565bec8fc882955b76732df4c042c5b2a --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Form.html @@ -0,0 +1,7 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<formvh:form object="{form}" action="perform" method="post" id="{form.identifier}" section="{form.identifier}" enctype="multipart/form-data"> + <formvh:renderRenderable renderable="{form.currentPage}" /> + <div class="actions"> + <f:render partial="Form/Navigation" arguments="{form: form}" /> + </div> +</formvh:form> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Hidden.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Hidden.html new file mode 100644 index 0000000000000000000000000000000000000000..0d4b716824f788d164a9d639ae5c5b12b7ea4fcb --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Hidden.html @@ -0,0 +1 @@ +<f:form.hidden property="{element.identifier}" id="{element.uniqueIdentifier}" value="{element.properties.value}" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Honeypot.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Honeypot.html new file mode 100644 index 0000000000000000000000000000000000000000..6f26f34f07d38a00221846938f814d8db14cb54e --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Honeypot.html @@ -0,0 +1,8 @@ +<f:if condition="{element.properties.renderAsHiddenField}"> + <f:then> + <f:form.hidden property="{element.identifier}" id="{element.uniqueIdentifier}" additionalAttributes="{autocomplete: 'off'}" /> + </f:then> + <f:else> + <f:form.textfield property="{element.identifier}" id="{element.uniqueIdentifier}" class="{element.properties.elementClassAttribute}" additionalAttributes="{autocomplete: 'off'}" style="{element.properties.styleAttribute}" /> + </f:else> +</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ImageUpload.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ImageUpload.html new file mode 100644 index 0000000000000000000000000000000000000000..3c6798a59d5575695285f3cfab9d69bd6d5c03dc --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/ImageUpload.html @@ -0,0 +1,13 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <formvh:form.uploadedResource property="{element.identifier}" as="image" additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" accept="{element.properties.allowedMimeTypes}"> + <f:if condition="{image}"> + <div id="{element.uniqueIdentifier}-preview"> + <a href="{f:uri.image(image: image, maxWidth: element.properties.imageLinkMaxWidth)}" class="{element.properties.elementClassAttribute}"> + <f:image image="{image}" maxWidth="{element.properties.imageMaxWidth}" maxHeight="{element.properties.imageMaxHeight}" alt="{formvh:translateElementProperty(element: element, property: 'altText')}" /> + </a> + </div> + </f:if> + </formvh:form.uploadedResource> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiCheckbox.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiCheckbox.html new file mode 100644 index 0000000000000000000000000000000000000000..642dcdf1c6bceb3f5782e6c0b220737cc2030b30 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiCheckbox.html @@ -0,0 +1,20 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <div id="{element.uniqueIdentifier}" class="inputs-list"> + <f:for each="{element.properties.options}" as="label" key="value"> + <div class="form-check"> + <label class="form-check-label"> + <formvh:form.checkbox + property="{element.identifier}" + multiple="1" + class="{element.properties.elementClassAttribute}" + value="{value}" + errorClass="{element.properties.elementErrorClassAttribute}" + /> + <span>{formvh:translateElementProperty(element: element, property: 'options.{value}')}</span> + </label> + </div> + </f:for> + </div> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiSelect.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiSelect.html new file mode 100644 index 0000000000000000000000000000000000000000..c8459427292dd471cc741414148bdfe665c7ab0a --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/MultiSelect.html @@ -0,0 +1,12 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <f:form.select + property="{element.identifier}" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute} form-control" + options="{formvh:translateElementProperty(element: element, property: 'options')}" + multiple="multiple" + errorClass="{element.properties.elementErrorClassAttribute}" + /> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Page.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Page.html new file mode 100644 index 0000000000000000000000000000000000000000..cf7462f4bec952a5e439bd404b62adc11e35e996 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Page.html @@ -0,0 +1,9 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<fieldset class="form-group"> + <f:if condition="{page.label}"> + <legend>{formvh:translateElementProperty(element: page, property: 'label')}</legend> + </f:if> + <f:for each="{page.elements}" as="element"> + <formvh:renderRenderable renderable="{element}" /> + </f:for> +</fieldset> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Password.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Password.html new file mode 100644 index 0000000000000000000000000000000000000000..89f7780705b9d475cb11045169ae7d57a5340f39 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Password.html @@ -0,0 +1,11 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <f:form.password + property="{element.identifier}" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute} form-control" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\', placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}', else: '{placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}')}" + errorClass="{element.properties.elementErrorClassAttribute}" + /> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/RadioButton.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/RadioButton.html new file mode 100644 index 0000000000000000000000000000000000000000..7434e45b94200df66e76e1e47245921e72344b02 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/RadioButton.html @@ -0,0 +1,22 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <div id="{element.uniqueIdentifier}" class="inputs-list"> + <div class="form-group"> + <f:for each="{element.properties.options}" as="label" key="value"> + <div class="form-check"> + <label class="form-check-label"> + <f:form.radio + property="{element.identifier}" + class="{element.properties.elementClassAttribute} form-check-input" + value="{value}" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" + /> + <span>{formvh:translateElementProperty(element: element, property: 'options.{value}')}</span> + </label> + </div> + </f:for> + </div> + </div> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SingleSelect.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SingleSelect.html new file mode 100644 index 0000000000000000000000000000000000000000..bb125dc15aed99a1e27c4ea9ef02dac2b6cdcbd6 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SingleSelect.html @@ -0,0 +1,12 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <f:form.select + property="{element.identifier}" + id="{element.uniqueIdentifier}" + options="{formvh:translateElementProperty(element: element, property: 'options')}" + class="{element.properties.elementClassAttribute} form-control" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\'}')}" + /> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/StaticText.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/StaticText.html new file mode 100644 index 0000000000000000000000000000000000000000..9fe0a2a9ef5597bf408ea1e9dc7a9d334beb06c2 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/StaticText.html @@ -0,0 +1,9 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<div class="clearfix"> + <f:if condition="{element.label}"> + <h2>{formvh:translateElementProperty(element: element, property: 'label')}</h2> + </f:if> + <f:if condition="{element.properties.text}"> + <p{f:if(condition: element.properties.elementClassAttribute, then: ' class="{element.properties.elementClassAttribute}"')}>{formvh:translateElementProperty(element: element, property: 'text') -> f:format.nl2br()}</p> + </f:if> +</div> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SummaryPage.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SummaryPage.html new file mode 100644 index 0000000000000000000000000000000000000000..3afa995f48a0e60f613bda6e9933245613b1e4fc --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/SummaryPage.html @@ -0,0 +1,43 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<fieldset class="form-group"> + <f:if condition="{page.label}"> + <legend>{formvh:translateElementProperty(element: page, property: 'label')}</legend> + </f:if> + <div class="table-responsive"> + <table class="table"> + <formvh:renderAllFormValues renderable="{page.rootForm}"> + <tr> + <td class="summary-table-first-col">{formvh:translateElementProperty(element: formValue.element, property: 'label')}</td> + <td> + <f:if condition="{formValue.value}"> + <f:then> + <f:if condition="{0: formValue.element.type} == {0: 'ImageUpload'}"> + <f:then> + <f:image image="{formValue.value}" maxWidth="{formValue.element.properties.imageMaxWidth}" maxHeight="{formValue.element.properties.imageMaxHeight}" alt="{formvh:translateElementProperty(element: formValue.element, property: 'altText')}" /> + </f:then> + <f:else> + <f:if condition="{formValue.isMultiValue}"> + <f:then> + <ul> + <f:for each="{formValue.processedValue}" as="value"> + <li>{value}</li> + </f:for> + </ul> + </f:then> + <f:else> + {formValue.processedValue} + </f:else> + </f:if> + </f:else> + </f:if> + </f:then> + <f:else> + - + </f:else> + </f:if> + </td> + </tr> + </formvh:renderAllFormValues> + </table> + </div> +</fieldset> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Text.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Text.html new file mode 100644 index 0000000000000000000000000000000000000000..0eb10c2c1b8b1964902ed7ebc5c851866b6bf686 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Text.html @@ -0,0 +1,12 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <f:form.textfield + property="{element.identifier}" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute} form-control" + placeholder="{formvh:translateElementProperty(element: element, property: 'placeholder')}" + errorClass="{element.properties.elementErrorClassAttribute}" + required="{element.required}" + /> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Textarea.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Textarea.html new file mode 100644 index 0000000000000000000000000000000000000000..c0baddec26b081a971e5bcf8edc236b775f9e98c --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/FormElements/Textarea.html @@ -0,0 +1,13 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:layout name="Field" /> +<f:section name="field"> + <f:form.textarea + property="{element.identifier}" + id="{element.uniqueIdentifier}" + class="{element.properties.elementClassAttribute} form-control" + rows="{element.properties.rows}" + cols="{element.properties.cols}" + errorClass="{element.properties.elementErrorClassAttribute}" + additionalAttributes="{f:if(condition: '{element.required}', then: '{required: \'required\', placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}', else: '{placeholder: \'{formvh:translateElementProperty(element: element, property: \"placeholder\")}\'}')}" + /> +</f:section> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Frontend/Templates/Render.html b/typo3/sysext/form/Resources/Private/Frontend/Templates/Render.html new file mode 100644 index 0000000000000000000000000000000000000000..a42a55d1682a7bd5352e41605d9658ed12c574c5 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Frontend/Templates/Render.html @@ -0,0 +1,5 @@ +{namespace formvh=TYPO3\CMS\Form\ViewHelpers} +<f:flashMessages class="flashmessages" /> +<f:if condition="{formConfiguration}"> + <formvh:render overrideConfiguration="{formConfiguration}"/> +</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Language/Database.xlf b/typo3/sysext/form/Resources/Private/Language/Database.xlf index 069dedb784318e97a8a851d311e8572bfd1648a4..3f8d42d814994f9ce1e41dbcae87ed6d369fccc9 100644 --- a/typo3/sysext/form/Resources/Private/Language/Database.xlf +++ b/typo3/sysext/form/Resources/Private/Language/Database.xlf @@ -1,14 +1,690 @@ <?xml version="1.0" encoding="UTF-8"?> <xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> - <file t3:id="1450450398" source-language="en" datatype="plaintext" original="messages" date="2015-12-18T15:53:55Z" product-name="form"> - <header/> - <body> - <trans-unit id="tx_form_predefinedform"> - <source>Predefined form</source> - </trans-unit> - <trans-unit id="tx_form_predefinedform.selectPredefinedForm"> - <source>Choose a predefined form</source> - </trans-unit> - </body> - </file> + <file t3:id="1471786343" source-language="en" datatype="plaintext" original="messages" date="2016-08-21T20:15:32Z" product-name="form"> + <header/> + <body> + <trans-unit id="module.shortcut_name" xml:space="preserve"> + <source>Form manager</source> + </trans-unit> + + <trans-unit id="tt_content.pi_flexform.formframework.persistenceIdentifier" xml:space="preserve"> + <source>Form definition</source> + </trans-unit> + <trans-unit id="tt_content.pi_flexform.formframework.sheet_general" xml:space="preserve"> + <source>General</source> + </trans-unit> + <trans-unit id="tt_content.pi_flexform.formframework.selectPersistenceIdentifier" xml:space="preserve"> + <source>Please select a form definition</source> + </trans-unit> + <trans-unit id="tt_content.pi_flexform.formframework.overrideFinishers" xml:space="preserve"> + <source>Override finisher settings</source> + </trans-unit> + + <trans-unit id="tt_content.finishersDefinition.EmailToSender.label" xml:space="preserve"> + <source>Email to sender</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.subject.label" xml:space="preserve"> + <source>Subject of the email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.recipientAddress.label" xml:space="preserve"> + <source>Email address of the recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.recipientName.label" xml:space="preserve"> + <source>Human-readable name of the recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.senderAddress.label" xml:space="preserve"> + <source>Email address of the sender</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.senderName.label" xml:space="preserve"> + <source>Human-readable name of the sender</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.replyToAddress.label" xml:space="preserve"> + <source>Email address of to be used as reply-to email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.carbonCopyAddress.label" xml:space="preserve"> + <source>Email address of the copy recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.blindCarbonCopyAddress.label" xml:space="preserve"> + <source>Email address of the blind copy recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.format.label" xml:space="preserve"> + <source>The format of the email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.format.1" xml:space="preserve"> + <source>HTML</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToSender.format.2" xml:space="preserve"> + <source>Plain text</source> + </trans-unit> + + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.label" xml:space="preserve"> + <source>Email to receiver</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.subject.label" xml:space="preserve"> + <source>Subject of the email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.recipientAddress.label" xml:space="preserve"> + <source>Email address of the recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.recipientName.label" xml:space="preserve"> + <source>Human-readable name of the recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.senderAddress.label" xml:space="preserve"> + <source>Email address of the sender</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.senderName.label" xml:space="preserve"> + <source>Human-readable name of the sender</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.replyToAddress.label" xml:space="preserve"> + <source>Email address of to be used as reply-to email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.carbonCopyAddress.label" xml:space="preserve"> + <source>Email address of the copy recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.blindCarbonCopyAddress.label" xml:space="preserve"> + <source>Email address of the blind copy recipient</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.format.label" xml:space="preserve"> + <source>Format of the email</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.format.1" xml:space="preserve"> + <source>HTML</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.format.2" xml:space="preserve"> + <source>Plain text</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.language.label" xml:space="preserve"> + <source>Translation language</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.EmailToReceiver.language.1" xml:space="preserve"> + <source>Default</source> + </trans-unit> + + <trans-unit id="tt_content.finishersDefinition.Redirect.label" xml:space="preserve"> + <source>Redirect</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.Redirect.pageUid.label" xml:space="preserve"> + <source>Page</source> + </trans-unit> + <trans-unit id="tt_content.finishersDefinition.Redirect.additionalParameters.label" xml:space="preserve"> + <source>Additional link parameter</source> + </trans-unit> + + <trans-unit id="formManagerController.deleteAction.error.title" xml:space="preserve"> + <source>Delete error</source> + </trans-unit> + <trans-unit id="formManagerController.deleteAction.error.body" xml:space="preserve"> + <source>The form "%s" could not be deleted.</source> + </trans-unit> + + <trans-unit id="formManager.headline" xml:space="preserve"> + <source>Manage forms</source> + </trans-unit> + <trans-unit id="formManager.create_new_form" xml:space="preserve"> + <source>Create a new form</source> + </trans-unit> + <trans-unit id="formManager.edit_existing_forms" xml:space="preserve"> + <source>Edit existing forms</source> + </trans-unit> + <trans-unit id="formManager.form_name" xml:space="preserve"> + <source>Form name</source> + </trans-unit> + <trans-unit id="formManager.location" xml:space="preserve"> + <source>Location</source> + </trans-unit> + <trans-unit id="formManager.references" xml:space="preserve"> + <source>References</source> + </trans-unit> + <trans-unit id="formManager.options" xml:space="preserve"> + <source>Options</source> + </trans-unit> + <trans-unit id="formManager.show_references" xml:space="preserve"> + <source>Show references for this form</source> + </trans-unit> + <trans-unit id="formManager.edit_form" xml:space="preserve"> + <source>Edit this form</source> + </trans-unit> + <trans-unit id="formManager.duplicate_this_form" xml:space="preserve"> + <source>Duplicate this form</source> + </trans-unit> + <trans-unit id="formManager.delete_form" xml:space="preserve"> + <source>Remove this form</source> + </trans-unit> + <trans-unit id="formManager.no_forms" xml:space="preserve"> + <source>No form available.</source> + </trans-unit> + <trans-unit id="formManager.edit_form_not_allowed" xml:space="preserve"> + <source>Edit this form is not allowed.</source> + </trans-unit> + <trans-unit id="formManager.delete_form_not_allowed" xml:space="preserve"> + <source>Delete this form is not allowed.</source> + </trans-unit> + <trans-unit id="formManager.duplicate_identifier" xml:space="preserve"> + <source>Duplicate identifier!</source> + </trans-unit> + + <trans-unit id="formManager.selectablePrototypesConfiguration.standard.label" xml:space="preserve"> + <source>Standard</source> + </trans-unit> + <trans-unit id="formManager.selectablePrototypesConfiguration.standard.newFormTemplates.blankForm.label" xml:space="preserve"> + <source>Blank form</source> + </trans-unit> + <trans-unit id="formManager.selectablePrototypesConfiguration.standard.newFormTemplates.simpleContactForm.label" xml:space="preserve"> + <source>Simple contact form (ext:form example)</source> + </trans-unit> + + <trans-unit id="formEditor.header" xml:space="preserve"> + <source>Form Editor</source> + </trans-unit> + <trans-unit id="formEditor.loading" xml:space="preserve"> + <source>Loading...</source> + </trans-unit> + <trans-unit id="formEditor.spinner" xml:space="preserve"> + <source>Loading...</source> + </trans-unit> + <trans-unit id="formEditor.save_button" xml:space="preserve"> + <source>Save</source> + </trans-unit> + <trans-unit id="formEditor.undo_button" xml:space="preserve"> + <source>Undo</source> + </trans-unit> + <trans-unit id="formEditor.redo_button" xml:space="preserve"> + <source>Redo</source> + </trans-unit> + <trans-unit id="formEditor.new_page_button" xml:space="preserve"> + <source>Create new page</source> + </trans-unit> + <trans-unit id="formEditor.structure" xml:space="preserve"> + <source>Structure</source> + </trans-unit> + <trans-unit id="formEditor.insert_elements" xml:space="preserve"> + <source>Insert elements</source> + </trans-unit> + <trans-unit id="formEditor.insert_pages" xml:space="preserve"> + <source>Insert pages</source> + </trans-unit> + + <trans-unit id="formEditor.formElementPropertyValidatorsDefinition.NotEmpty.label" xml:space="preserve"> + <source>Required</source> + </trans-unit> + <trans-unit id="formEditor.formElementPropertyValidatorsDefinition.Integer.label" xml:space="preserve"> + <source>Not a number</source> + </trans-unit> + <trans-unit id="formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label" xml:space="preserve"> + <source>Invalid email address</source> + </trans-unit> + <trans-unit id="formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label" xml:space="preserve"> + <source>Invalid form element</source> + </trans-unit> + + <trans-unit id="formEditor.formElementGroups.input.label" xml:space="preserve"> + <source>Basic elements</source> + </trans-unit> + <trans-unit id="formEditor.formElementGroups.select.label" xml:space="preserve"> + <source>Select elements</source> + </trans-unit> + <trans-unit id="formEditor.formElementGroups.custom.label" xml:space="preserve"> + <source>Advanced elements</source> + </trans-unit> + <trans-unit id="formEditor.formElementGroups.container.label" xml:space="preserve"> + <source>Container elements</source> + </trans-unit> + <trans-unit id="formEditor.formElementGroups.page.label" xml:space="preserve"> + <source>Page types</source> + </trans-unit> + + <trans-unit id="formEditor.elements.BaseFormElementMixin.editor.label.label" xml:space="preserve"> + <source>Form name</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.saveSuccessFlashMessageTitle" xml:space="preserve"> + <source>Save</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.saveSuccessFlashMessageMessage" xml:space="preserve"> + <source>The form has been successfully saved.</source> + </trans-unit> + + <trans-unit id="formEditor.modals.validationErrors.dialogTitle" xml:space="preserve"> + <source>Alert</source> + </trans-unit> + <trans-unit id="formEditor.modals.validationErrors.dialogMessage" xml:space="preserve"> + <source>Some elements are not configured properly. Please check the following elements:</source> + </trans-unit> + <trans-unit id="formEditor.modals.validationErrors.confirmButton" xml:space="preserve"> + <source>OK</source> + </trans-unit> + + <trans-unit id="formEditor.modals.insertElements.dialogTitle" xml:space="preserve"> + <source>New element</source> + </trans-unit> + <trans-unit id="formEditor.modals.newPages.dialogTitle" xml:space="preserve"> + <source>New page</source> + </trans-unit> + + <trans-unit id="formEditor.modals.removeElement.dialogTitle" xml:space="preserve"> + <source>Remove element?</source> + </trans-unit> + <trans-unit id="formEditor.modals.removeElement.dialogMessage" xml:space="preserve"> + <source>Are you sure that you want to remove this element?</source> + </trans-unit> + <trans-unit id="formEditor.modals.removeElement.confirmButton" xml:space="preserve"> + <source>Remove</source> + </trans-unit> + <trans-unit id="formEditor.modals.removeElement.cancleButton" xml:space="preserve"> + <source>Cancel</source> + </trans-unit> + <trans-unit id="formEditor.modals.removeElement.lastAvailablePageFlashMessageTitle" xml:space="preserve"> + <source>Error</source> + </trans-unit> + <trans-unit id="formEditor.modals.removeElement.lastAvailablePageFlashMessageMessage" xml:space="preserve"> + <source>There must be at least one page within your form.</source> + </trans-unit> + + <trans-unit id="formEditor.modals.close.dialogMessage" xml:space="preserve"> + <source>You have currently unsaved changes. Are you sure that you want to discard all changes?</source> + </trans-unit> + <trans-unit id="formEditor.modals.close.dialogTitle" xml:space="preserve"> + <source>Do you want to quit without saving?</source> + </trans-unit> + <trans-unit id="formEditor.modals.close.confirmButton" xml:space="preserve"> + <source>Yes, discard my changes</source> + </trans-unit> + <trans-unit id="formEditor.modals.close.cancleButton" xml:space="preserve"> + <source>No, I will continue editing</source> + </trans-unit> + + <trans-unit id="formEditor.pagination.title" xml:space="preserve"> + <source>Page {0} of {1}</source> + </trans-unit> + + <trans-unit id="formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label" xml:space="preserve"> + <source>Minimum</source> + </trans-unit> + <trans-unit id="formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label" xml:space="preserve"> + <source>Maximum</source> + </trans-unit> + + <trans-unit id="formEditor.elements.TextMixin.editor.placeholder.label" xml:space="preserve"> + <source>Placeholder</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.defaultValue.label" xml:space="preserve"> + <source>Default value</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.label" xml:space="preserve"> + <source>Validators</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.EmptyValue.label" xml:space="preserve"> + <source>Add validator</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.Alphanumeric.label" xml:space="preserve"> + <source>Alphanumeric</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.Text.label" xml:space="preserve"> + <source>Non-XML text</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.StringLength.label" xml:space="preserve"> + <source>String length</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.EmailAddress.label" xml:space="preserve"> + <source>Email</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.Integer.label" xml:space="preserve"> + <source>Integer number</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.Float.label" xml:space="preserve"> + <source>Floating-point number</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.NumberRange.label" xml:space="preserve"> + <source>Number range</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.editor.validators.RegularExpression.label" xml:space="preserve"> + <source>Regular expression</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label" xml:space="preserve"> + <source>Alphanumeric</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.Text.editor.header.label" xml:space="preserve"> + <source>Non-XML text</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.StringLength.editor.header.label" xml:space="preserve"> + <source>String length</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label" xml:space="preserve"> + <source>Email</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.Integer.editor.header.label" xml:space="preserve"> + <source>Integer number</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.Float.editor.header.label" xml:space="preserve"> + <source>Floating-point number</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.NumberRange.editor.header.label" xml:space="preserve"> + <source>Number range</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label" xml:space="preserve"> + <source>Regular expression</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label" xml:space="preserve"> + <source>Regular expression</source> + </trans-unit> + <trans-unit id="formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.fieldExplanationText" xml:space="preserve"> + <source>Enter a valid PHP PCRE regular expression here.</source> + </trans-unit> + + <trans-unit id="formEditor.elements.SelectionMixin.editor.options.label" xml:space="preserve"> + <source>Choices</source> + </trans-unit> + <trans-unit id="formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle" xml:space="preserve"> + <source>Error</source> + </trans-unit> + <trans-unit id="formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage" xml:space="preserve"> + <source>There must be at least one row within your options.</source> + </trans-unit> + + <trans-unit id="formEditor.elements.MultiSelectionMixin.editor.validators.label" xml:space="preserve"> + <source>Validators</source> + </trans-unit> + <trans-unit id="formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label" xml:space="preserve"> + <source>Add validator</source> + </trans-unit> + <trans-unit id="formEditor.elements.MultiSelectionMixin.editor.validators.Count.label" xml:space="preserve"> + <source>Number of submitted values</source> + </trans-unit> + <trans-unit id="formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label" xml:space="preserve"> + <source>Number of submitted values</source> + </trans-unit> + + <trans-unit id="formEditor.elements.FileUploadMixin.editor.saveToFileMount.label" xml:space="preserve"> + <source>Uploads save path</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.editor.submitButtonLabel.label" xml:space="preserve"> + <source>Submit label</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.label" xml:space="preserve"> + <source>Finishers</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.EmptyValue.label" xml:space="preserve"> + <source>Add finisher</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.EmailToSender.label" xml:space="preserve"> + <source>Email to sender</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.EmailToReceiver.label" xml:space="preserve"> + <source>Email to receiver</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.Redirect.label" xml:space="preserve"> + <source>Redirect to a page</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.editor.finishers.DeleteUploads.label" xml:space="preserve"> + <source>Delete uploads</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.header.label" xml:space="preserve"> + <source>Send email (sender)</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.subject.label" xml:space="preserve"> + <source>Subject</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.recipientAddress.label" xml:space="preserve"> + <source>Recipient address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.recipientName.label" xml:space="preserve"> + <source>Recipient name</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label" xml:space="preserve"> + <source>Sender address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label" xml:space="preserve"> + <source>Sender name</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.replyToAddress.label" xml:space="preserve"> + <source>Reply-to address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyAddress.label" xml:space="preserve"> + <source>CC address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyAddress.label" xml:space="preserve"> + <source>BCC address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.format.label" xml:space="preserve"> + <source>Format</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.format.1" xml:space="preserve"> + <source>Plain text</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.format.2" xml:space="preserve"> + <source>HTML</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label" xml:space="preserve"> + <source>Attach uploads</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label" xml:space="preserve"> + <source>Send email (receiver)</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label" xml:space="preserve"> + <source>Subject</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.recipientAddress.label" xml:space="preserve"> + <source>Recipient address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.recipientName.label" xml:space="preserve"> + <source>Recipient name</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label" xml:space="preserve"> + <source>Sender address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label" xml:space="preserve"> + <source>Sender name</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToAddress.label" xml:space="preserve"> + <source>Reply-to address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyAddress.label" xml:space="preserve"> + <source>CC address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyAddress.label" xml:space="preserve"> + <source>BCC address</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.format.label" xml:space="preserve"> + <source>Format</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.format.1" xml:space="preserve"> + <source>Plain text</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.format.2" xml:space="preserve"> + <source>HTML</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label" xml:space="preserve"> + <source>Attach uploads</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label" xml:space="preserve"> + <source>Translation language</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1" xml:space="preserve"> + <source>EN</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.finisher.Redirect.editor.header.label" xml:space="preserve"> + <source>Redirect to a page</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.Redirect.editor.pageUid.label" xml:space="preserve"> + <source>Page</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel" xml:space="preserve"> + <source>Pages</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label" xml:space="preserve"> + <source>Additional parameters</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Form.finisher.DeleteUploads.editor.header.label" xml:space="preserve"> + <source>Delete uploads</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.Confirmation.editor.header.label" xml:space="preserve"> + <source>Confirmation message</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.Closure.editor.header.label" xml:space="preserve"> + <source>Execute a closure</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.FlashMessage.editor.header.label" xml:space="preserve"> + <source>Flash message</source> + </trans-unit> + <trans-unit id="formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label" xml:space="preserve"> + <source>Save the mail to the Database</source> + </trans-unit> + + <trans-unit id="formEditor.elements.ReadOnlyFormElement.editor.label.label" xml:space="preserve"> + <source>Element name</source> + </trans-unit> + + <trans-unit id="formEditor.elements.FormElement.editor.label.label" xml:space="preserve"> + <source>Element name</source> + </trans-unit> + <trans-unit id="formEditor.elements.FormElement.editor.requiredValidator.label" xml:space="preserve"> + <source>Required field</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Page.label" xml:space="preserve"> + <source>Page</source> + </trans-unit> + <trans-unit id="formEditor.elements.Page.editor.label.label" xml:space="preserve"> + <source>Page name</source> + </trans-unit> + <trans-unit id="formEditor.elements.Page.editor.previousButtonLabel.label" xml:space="preserve"> + <source>Previous label</source> + </trans-unit> + <trans-unit id="formEditor.elements.Page.editor.nextButtonLabel.label" xml:space="preserve"> + <source>Next label</source> + </trans-unit> + + <trans-unit id="formEditor.elements.SummaryPage.label" xml:space="preserve"> + <source>Summary page</source> + </trans-unit> + <trans-unit id="formEditor.elements.SummaryPage.editor.label.label" xml:space="preserve"> + <source>Page name</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Fieldset.label" xml:space="preserve"> + <source>Fieldset</source> + </trans-unit> + <trans-unit id="formEditor.elements.Fieldset.editor.label.label" xml:space="preserve"> + <source>Fieldset name</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Text.label" xml:space="preserve"> + <source>Text</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Password.label" xml:space="preserve"> + <source>Password</source> + </trans-unit> + <trans-unit id="formEditor.elements.AdvancedPassword.label" xml:space="preserve"> + <source>Advanced password</source> + </trans-unit> + + <trans-unit id="formEditor.elements.AdvancedPassword.editor.confirmationLabel.label" xml:space="preserve"> + <source>Confirmation label</source> + </trans-unit> + <trans-unit id="formEditor.element.AdvancedPassword.editor.confirmationLabel.predefinedDefaults" xml:space="preserve"> + <source>Confirmation</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Textarea.label" xml:space="preserve"> + <source>Textarea</source> + </trans-unit> + + <trans-unit id="formEditor.elements.Checkbox.label" xml:space="preserve"> + <source>Checkbox</source> + </trans-unit> + + <trans-unit id="formEditor.elements.MultiCheckbox.label" xml:space="preserve"> + <source>Multi checkbox</source> + </trans-unit> + + <trans-unit id="formEditor.elements.MultiSelect.label" xml:space="preserve"> + <source>Multi select</source> + </trans-unit> + + <trans-unit id="formEditor.elements.RadioButton.label" xml:space="preserve"> + <source>Radio button</source> + </trans-unit> + + <trans-unit id="formEditor.elements.SingleSelect.label" xml:space="preserve"> + <source>Single select</source> + </trans-unit> + + <trans-unit id="formEditor.elements.DatePicker.label" xml:space="preserve"> + <source>Date picker</source> + </trans-unit> + <trans-unit id="formEditor.elements.DatePicker.editor.validators.label" xml:space="preserve"> + <source>Validators</source> + </trans-unit> + <trans-unit id="formEditor.elements.DatePicker.editor.validators.EmptyValue.label" xml:space="preserve"> + <source>Add validator</source> + </trans-unit> + <trans-unit id="formEditor.elements.DatePicker.editor.validators.DateTime.label" xml:space="preserve"> + <source>Date/time</source> + </trans-unit> + <trans-unit id="formEditor.elements.DatePicker.validators.DateTime.editor.header.label" xml:space="preserve"> + <source>Date/time</source> + </trans-unit> + + <trans-unit id="formEditor.elements.StaticText.label" xml:space="preserve"> + <source>Static text</source> + </trans-unit> + <trans-unit id="formEditor.elements.StaticText.editor.staticText.label" xml:space="preserve"> + <source>Text</source> + </trans-unit> + + <trans-unit id="formEditor.elements.ContentElement.label" xml:space="preserve"> + <source>Content element</source> + </trans-unit> + <trans-unit id="formEditor.elements.ContentElement.selectContentElement" xml:space="preserve"> + <source>No content element selected</source> + </trans-unit> + + <trans-unit id="formEditor.elements.StaticText.editor.contentElement.label" xml:space="preserve"> + <source>Content element uid</source> + </trans-unit> + <trans-unit id="formEditor.elements.StaticText.editor.contentElement.buttonLabel" xml:space="preserve"> + <source>tt_content</source> + </trans-unit> + + <trans-unit id="formEditor.elements.FileUpload.label" xml:space="preserve"> + <source>File upload</source> + </trans-unit> + <trans-unit id="formEditor.elements.FileUpload.editor.allowedMimeTypes.label" xml:space="preserve"> + <source>Allowed file mime types</source> + </trans-unit> + <trans-unit id="formEditor.elements.FileUpload.editor.allowedMimeTypes.1" xml:space="preserve"> + <source>Documents (doc, docx, odt, pdf)</source> + </trans-unit> + <trans-unit id="formEditor.elements.FileUpload.editor.allowedMimeTypes.2" xml:space="preserve"> + <source>Spreadsheet documents (xls)</source> + </trans-unit> + + <trans-unit id="formEditor.elements.ImageUpload.label" xml:space="preserve"> + <source>Image upload</source> + </trans-unit> + + <trans-unit id="formEditor.elements.UnknownElement" xml:space="preserve"> + <source>Unknown Element</source> + </trans-unit> + + <trans-unit id="formEditor.stage.toolbar.new_element" xml:space="preserve"> + <source>Create new element</source> + </trans-unit> + <trans-unit id="formEditor.stage.toolbar.remove" xml:space="preserve"> + <source>Remove</source> + </trans-unit> + <trans-unit id="formEditor.stage.toolbar.new_element.inside" xml:space="preserve"> + <source>Inside</source> + </trans-unit> + <trans-unit id="formEditor.stage.toolbar.new_element.after" xml:space="preserve"> + <source>After</source> + </trans-unit> + </body> + </file> </xliff> diff --git a/typo3/sysext/form/Resources/Private/Language/locallang.xlf b/typo3/sysext/form/Resources/Private/Language/locallang.xlf index cb38da6f0ce7559c2d83e6ab1c2f86f6ac4373e1..f7fe933149838797d05475f1caff9e6d2c4b5014 100644 --- a/typo3/sysext/form/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/form/Resources/Private/Language/locallang.xlf @@ -1,209 +1,96 @@ <?xml version="1.0" encoding="UTF-8"?> <xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> - <file t3:id="1415814824" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:32Z" product-name="form"> - <header/> - <body> - <trans-unit id="tx_form_domain_model_element_button.value"> - <source>Push this button</source> - </trans-unit> - <trans-unit id="tx_form_domain_model_element_submit.value"> - <source>Submit form</source> - </trans-unit> - <trans-unit id="tx_form_domain_model_element_reset.value"> - <source>Clear form</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphabetic.message"> - <source>Use alphabetic characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphabetic.message2"> - <source>whitespace allowed</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphabetic.error"> - <source>The value contains not only alphabetic characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphanumeric.message"> - <source>Use alphanumeric characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphanumeric.message2"> - <source>whitespace allowed</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_alphanumeric.error"> - <source>The value contains not only alphanumeric characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_between.message"> - <source>The value must be between %minimum and %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_between.message2"> - <source>inclusively</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_between.error"> - <source>The value is not between %minimum and %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_between.error2"> - <source>inclusively</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.message"> - <source>(%format)</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.A"> - <source>dddd</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.a"> - <source>ddd</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.d"> - <source>dd</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.e"> - <source>d</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.B"> - <source>mmmm</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.b"> - <source>mmm</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.m"> - <source>mm</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.Y"> - <source>yyyy</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.y"> - <source>yy</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.H"> - <source>HH</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.I"> - <source>hh</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.M"> - <source>mm</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.strftime.S"> - <source>ss</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_date.error"> - <source>The value does not appear to be a valid date</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_digit.message"> - <source>Use digit characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_digit.error"> - <source>The value contains not only digit characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_email.message"> - <source>(john.doe@domain.com)</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_email.error"> - <source>This is not a valid email address</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_equals.message"> - <source>This field must be equal to '%field'</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_equals.error"> - <source>The value does not equal the value in field '%field'</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_fileallowedtypes.message"> - <source>(%allowedTypes)</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_fileallowedtypes.error"> - <source>The file type is not allowed</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_filemaximumsize.message"> - <source>The filesize must be smaller than %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_filemaximumsize.error"> - <source>The filesize is too big</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_fileminimumsize.message"> - <source>The filesize must be bigger than %minimum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_fileminimumsize.error"> - <source>The filesize is too small</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_float.message"> - <source>Enter a float</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_float.error"> - <source>The value does not appear to be a float</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_greaterthan.message"> - <source>The value must be greater than %minimum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_greaterthan.error"> - <source>The value does not appear to be greater than %minimum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_inarray.message"> - <source>Only a few values are possible</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_inarray.error"> - <source>The value does not appear to be valid</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_integer.message"> - <source>Use an integer</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_integer.error"> - <source>The value does not appear to be an integer</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_ip.message"> - <source>(123.123.123.123)</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_ip.error"> - <source>The value does not appear to be a valid IP address</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_length.message"> - <source>The length of the value must have a minimum of %minimum characters</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_length.message2"> - <source>and a maximum of %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_length.error"> - <source>The value is less than %minimum characters long</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_length.error2"> - <source>or longer than %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_lessthan.message"> - <source>The value must be less than %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_lessthan.error"> - <source>The value does not appear to be less than %maximum</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_regexp.message"> - <source>Use the right pattern</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_regexp.error"> - <source>The value does not match against pattern</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_required.message"> - <source>Required</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_required.error"> - <source>This field is required</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_uri.message"> - <source>The value must be a URI</source> - </trans-unit> - <trans-unit id="tx_form_system_validate_uri.error"> - <source>The value does not appear to be a URI</source> - </trans-unit> - <trans-unit id="tx_form_view_confirmation.message"> - <source>Please check your input and confirm by using the appropriate button</source> - </trans-unit> - <trans-unit id="tx_form_view_confirmation.confirm"> - <source>Confirm</source> - </trans-unit> - <trans-unit id="tx_form_view_confirmation.donotconfirm"> - <source>Go back to the form</source> - </trans-unit> - <trans-unit id="tx_form_view_mail.success"> - <source>The form has been sent successfully by mail</source> - </trans-unit> - <trans-unit id="tx_form_view_mail.error"> - <source>There was an error when sending the form by mail</source> - </trans-unit> - </body> - </file> + <file t3:id="1475977066" source-language="en" datatype="plaintext" original="messages" date="2016-10-09T03:38:32Z" product-name="form"> + <header/> + <body> + <trans-unit id="element.Form.renderingOptions.submitButtonLabel" xml:space="preserve"> + <source>Submit</source> + </trans-unit> + <trans-unit id="element.Page.renderingOptions.previousButtonLabel" xml:space="preserve"> + <source>previous Page</source> + </trans-unit> + <trans-unit id="element.Page.renderingOptions.nextButtonLabel" xml:space="preserve"> + <source>next Page</source> + </trans-unit> + <trans-unit id="element.SummaryPage.renderingOptions.previousButtonLabel" xml:space="preserve"> + <source>previous Page</source> + </trans-unit> + <trans-unit id="element.SummaryPage.renderingOptions.nextButtonLabel" xml:space="preserve"> + <source>next Page</source> + </trans-unit> + <trans-unit id="element.ImageUpload.properties.SummaryPage.altText" xml:space="preserve"> + <source>uploaded image</source> + </trans-unit> + + <trans-unit id="validation.error.1221560910" xml:space="preserve"> + <source>This field is mandatory</source> + </trans-unit> + <trans-unit id="validation.error.1221560718" xml:space="preserve"> + <source>This field is mandatory</source> + </trans-unit> + <trans-unit id="validation.error.1347992400" xml:space="preserve"> + <source>This field is mandatory</source> + </trans-unit> + <trans-unit id="validation.error.1347992453" xml:space="preserve"> + <source>This field is mandatory</source> + </trans-unit> + <trans-unit id="validation.error.1238087674" xml:space="preserve"> + <source>Please enter a valid Date</source> + </trans-unit> + <trans-unit id="validation.error.1221551320" xml:space="preserve"> + <source>Please enter letters or digits</source> + </trans-unit> + <trans-unit id="validation.error.1221565786" xml:space="preserve"> + <source>Please enter a valid text (e.g. without XML tags)</source> + </trans-unit> + <trans-unit id="validation.error.1238110957" xml:space="preserve"> + <source>Please enter a valid text</source> + </trans-unit> + <trans-unit id="validation.error.1269883975" xml:space="preserve"> + <source>Please enter a valid text</source> + </trans-unit> + <trans-unit id="validation.error.1428504122" xml:space="preserve"> + <source>Please enter a text between %s and %s characters</source> + </trans-unit> + <trans-unit id="validation.error.1238108068" xml:space="preserve"> + <source>Please enter a text which is longer than %s characters</source> + </trans-unit> + <trans-unit id="validation.error.1238108069" xml:space="preserve"> + <source>Please enter a text which is not longer than %s characters</source> + </trans-unit> + <trans-unit id="validation.error.1221559976" xml:space="preserve"> + <source>Please enter a valid email address</source> + </trans-unit> + <trans-unit id="validation.error.1221560494" xml:space="preserve"> + <source>Please enter a valid number</source> + </trans-unit> + <trans-unit id="validation.error.1221560288" xml:space="preserve"> + <source>Please enter a valid floating point number</source> + </trans-unit> + <trans-unit id="validation.error.1221563685" xml:space="preserve"> + <source>Please enter a valid number</source> + </trans-unit> + <trans-unit id="validation.error.1221561046" xml:space="preserve"> + <source>Please enter a valid number between %s and %s</source> + </trans-unit> + <trans-unit id="validation.error.1221565130" xml:space="preserve"> + <source>Please enter a valid value</source> + </trans-unit> + <trans-unit id="validation.error.1475002976" xml:space="preserve"> + <source>The given subject is not countable.</source> + </trans-unit> + <trans-unit id="validation.error.1475002994" xml:space="preserve"> + <source>Please enter a valid number between %s and %s</source> + </trans-unit> + <trans-unit id="validation.error.1471708997" xml:space="preserve"> + <source>The given value was not an instance of \TYPO3\CMS\Extbase\Domain\Model\FileReference or \TYPO3\CMS\Core\Resource\File.</source> + </trans-unit> + <trans-unit id="validation.error.1471708998" xml:space="preserve"> + <source>The media type "%s" is not allowed for this file.</source> + </trans-unit> + <trans-unit id="validation.error.1476396435" xml:space="preserve"> + <source>Do not fill this field</source> + </trans-unit> + </body> + </file> </xliff> diff --git a/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf b/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf new file mode 100644 index 0000000000000000000000000000000000000000..1468bc84c8c6680368f2316ad01d9a2b57e11669 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Language/locallang_formManager_javascript.xlf @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> + <file t3:id="1477653834" source-language="en" datatype="plaintext" original="messages" date="2016-10-09T03:38:32Z" product-name="form"> + <header/> + <body> + <trans-unit id="formManager.form_name" xml:space="preserve"> + <source>Form name</source> + </trans-unit> + <trans-unit id="formManager.new_form_name" xml:space="preserve"> + <source>New form name</source> + </trans-unit> + <trans-unit id="formManager.form_save_path" xml:space="preserve"> + <source>Form storage</source> + </trans-unit> + <trans-unit id="formManager.form_prototype" xml:space="preserve"> + <source>Form prototype</source> + </trans-unit> + <trans-unit id="formManager.form_template" xml:space="preserve"> + <source>Start template</source> + </trans-unit> + <trans-unit id="formManager.cancel" xml:space="preserve"> + <source>Cancel</source> + </trans-unit> + <trans-unit id="formManager.remove_form" xml:space="preserve"> + <source>Remove</source> + </trans-unit> + <trans-unit id="formManager.remove_form_title" xml:space="preserve"> + <source>Remove form</source> + </trans-unit> + <trans-unit id="formManager.remove_form_message" xml:space="preserve"> + <source>Are you sure that you want to remove this form?</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step1.title" xml:space="preserve"> + <source>Create new form</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step1.advanced" xml:space="preserve"> + <source>Advanced settings</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step2.title" xml:space="preserve"> + <source>Advanced settings</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step3.title" xml:space="preserve"> + <source>Ready</source> + </trans-unit> + <trans-unit id="formManager.newFormWizard.step3.message" xml:space="preserve"> + <source>Now you are ready to create your new form.</source> + </trans-unit> + <trans-unit id="formManager.duplicateFormWizard.step1.title" xml:space="preserve"> + <source>Duplicate form "{0}"</source> + </trans-unit> + <trans-unit id="formManager.no_references" xml:space="preserve"> + <source>There are no references yet</source> + </trans-unit> + <trans-unit id="formManager.page" xml:space="preserve"> + <source>Page</source> + </trans-unit> + <trans-unit id="formManager.record" xml:space="preserve"> + <source>Record</source> + </trans-unit> + <trans-unit id="formManager.references.title" xml:space="preserve"> + <source>References</source> + </trans-unit> + <trans-unit id="formManager.references.headline" xml:space="preserve"> + <source>References for "{0}"</source> + </trans-unit> + </body> + </file> +</xliff> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Language/locallang_module.xlf b/typo3/sysext/form/Resources/Private/Language/locallang_module.xlf new file mode 100644 index 0000000000000000000000000000000000000000..fd1de2ed0b3c677fb50f8a741f39faa8531ed077 --- /dev/null +++ b/typo3/sysext/form/Resources/Private/Language/locallang_module.xlf @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> + <file t3:id="1465049996" source-language="en" datatype="plaintext" original="messages" date="2016-06-04T20:22:33Z" product-name="form"> + <header/> + <body> + <trans-unit id="mlang_labels_tablabel"> + <source>Build custom forms</source> + </trans-unit> + <trans-unit id="mlang_labels_tabdescr"> + <source>Build custom forms. TODO: Add more description.</source> + </trans-unit> + <trans-unit id="mlang_tabs_tab"> + <source>Forms</source> + </trans-unit> + </body> + </file> +</xliff> diff --git a/typo3/sysext/form/Resources/Private/Language/locallang_wizard.xlf b/typo3/sysext/form/Resources/Private/Language/locallang_wizard.xlf deleted file mode 100644 index 47ec19b828be86c6cc03e1ad1b0c8f80af98e41c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Language/locallang_wizard.xlf +++ /dev/null @@ -1,875 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<xliff version="1.0" xmlns:t3="http://typo3.org/schemas/xliff"> - <file t3:id="1415814825" source-language="en" datatype="plaintext" original="messages" date="2011-10-17T20:22:33Z" product-name="form"> - <header/> - <body> - <trans-unit id="title"> - <source>Form Wizard</source> - </trans-unit> - <trans-unit id="yes"> - <source>Yes</source> - </trans-unit> - <trans-unit id="no"> - <source>No</source> - </trans-unit> - <trans-unit id="refresh"> - <source>Refresh without saving</source> - </trans-unit> - <trans-unit id="errorTitle"> - <source>Wizard error</source> - </trans-unit> - <trans-unit id="errorMessage"> - <source>No reference to record</source> - </trans-unit> - <trans-unit id="save"> - <source>Save form</source> - </trans-unit> - <trans-unit id="saveAndClose"> - <source>Save and close form</source> - </trans-unit> - <trans-unit id="history_undo"> - <source>Undo</source> - </trans-unit> - <trans-unit id="history_redo"> - <source>Redo</source> - </trans-unit> - <trans-unit id="action_save"> - <source>Saving form</source> - </trans-unit> - <trans-unit id="action_save_error"> - <source>Server-side failure with status code</source> - </trans-unit> - <trans-unit id="action_save_message_failed"> - <source>Failed to save the form</source> - </trans-unit> - <trans-unit id="action_save_message_saved"> - <source>Changes saved successfully</source> - </trans-unit> - <trans-unit id="button_remove"> - <source>Remove</source> - </trans-unit> - <trans-unit id="left_elements"> - <source>Elements</source> - </trans-unit> - <trans-unit id="left_elements_intro_title"> - <source>Adding elements to the form</source> - </trans-unit> - <trans-unit id="left_elements_intro_description"> - <source>Drag or double-click elements to add</source> - </trans-unit> - <trans-unit id="left_elements_basic"> - <source>Basic form elements</source> - </trans-unit> - <trans-unit id="basic_button"> - <source>Button</source> - </trans-unit> - <trans-unit id="basic_checkbox"> - <source>Checkbox</source> - </trans-unit> - <trans-unit id="basic_fieldset"> - <source>Fieldset</source> - </trans-unit> - <trans-unit id="basic_fileupload"> - <source>Upload Field</source> - </trans-unit> - <trans-unit id="basic_hidden"> - <source>Hidden Field</source> - </trans-unit> - <trans-unit id="basic_input"> - <source>Input Field</source> - </trans-unit> - <trans-unit id="basic_password"> - <source>Password Field</source> - </trans-unit> - <trans-unit id="basic_radio"> - <source>Radio Button</source> - </trans-unit> - <trans-unit id="basic_reset"> - <source>Reset Button</source> - </trans-unit> - <trans-unit id="basic_select"> - <source>Drop Down</source> - </trans-unit> - <trans-unit id="basic_submit"> - <source>Submit Button</source> - </trans-unit> - <trans-unit id="basic_textarea"> - <source>Text Area</source> - </trans-unit> - <trans-unit id="basic_textline"> - <source>Text Field</source> - </trans-unit> - <trans-unit id="left_elements_content"> - <source>Content elements</source> - </trans-unit> - <trans-unit id="content_header"> - <source>Header</source> - </trans-unit> - <trans-unit id="content_textblock"> - <source>Text block</source> - </trans-unit> - <trans-unit id="left_elements_predefined"> - <source>Predefined form elements</source> - </trans-unit> - <trans-unit id="predefined_email"> - <source>Email</source> - </trans-unit> - <trans-unit id="predefined_radiogroup"> - <source>Radio Button Group</source> - </trans-unit> - <trans-unit id="predefined_checkboxgroup"> - <source>Checkbox Group</source> - </trans-unit> - <trans-unit id="predefined_name"> - <source>Full Name</source> - </trans-unit> - <trans-unit id="left_options"> - <source>Options</source> - </trans-unit> - <trans-unit id="options_error"> - <source>Error</source> - </trans-unit> - <trans-unit id="options_error_message"> - <source>There is an error in the settings of the current element. Please check!</source> - </trans-unit> - <trans-unit id="options_dummy_title"> - <source>Please select an element on the right</source> - </trans-unit> - <trans-unit id="options_dummy_description"> - <source>When an element has been selected, this area will show the options for the selected element</source> - </trans-unit> - <trans-unit id="options_attributes"> - <source>Attributes Properties</source> - </trans-unit> - <trans-unit id="attributes_accept"> - <source>Accept</source> - </trans-unit> - <trans-unit id="attributes_acceptcharset"> - <source>Acceptcharset</source> - </trans-unit> - <trans-unit id="attributes_accesskey"> - <source>Accesskey</source> - </trans-unit> - <trans-unit id="attributes_action"> - <source>Action</source> - </trans-unit> - <trans-unit id="attributes_alt"> - <source>Alt</source> - </trans-unit> - <trans-unit id="attributes_autocomplete"> - <source>Autocomplete</source> - </trans-unit> - <trans-unit id="attributes_autocomplete_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_autocomplete_off"> - <source>Off</source> - </trans-unit> - <trans-unit id="attributes_autocomplete_on"> - <source>On</source> - </trans-unit> - <trans-unit id="attributes_autofocus"> - <source>Autofocus</source> - </trans-unit> - <trans-unit id="attributes_checked"> - <source>Checked</source> - </trans-unit> - <trans-unit id="attributes_class"> - <source>Class</source> - </trans-unit> - <trans-unit id="attributes_cols"> - <source>Cols</source> - </trans-unit> - <trans-unit id="attributes_contenteditable"> - <source>Content editable</source> - </trans-unit> - <trans-unit id="attributes_contenteditable_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_contenteditable_true"> - <source>True</source> - </trans-unit> - <trans-unit id="attributes_contenteditable_false"> - <source>False</source> - </trans-unit> - <trans-unit id="attributes_contextmenu"> - <source>Contextmenu</source> - </trans-unit> - <trans-unit id="attributes_dir"> - <source>Dir</source> - </trans-unit> - <trans-unit id="attributes_dir_ltr"> - <source>Left to right</source> - </trans-unit> - <trans-unit id="attributes_dir_rtl"> - <source>Right to left</source> - </trans-unit> - <trans-unit id="attributes_disabled"> - <source>Disabled</source> - </trans-unit> - <trans-unit id="attributes_draggable"> - <source>Draggable</source> - </trans-unit> - <trans-unit id="attributes_draggable_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_draggable_true"> - <source>True</source> - </trans-unit> - <trans-unit id="attributes_draggable_false"> - <source>False</source> - </trans-unit> - <trans-unit id="attributes_draggable_auto"> - <source>Auto</source> - </trans-unit> - <trans-unit id="attributes_dropzone"> - <source>Dropzone</source> - </trans-unit> - <trans-unit id="attributes_enctype"> - <source>Enctype</source> - </trans-unit> - <trans-unit id="attributes_enctype_1"> - <source>Encoded</source> - </trans-unit> - <trans-unit id="attributes_enctype_2"> - <source>No encoding - File upload</source> - </trans-unit> - <trans-unit id="attributes_enctype_3"> - <source>No encoding - Spaces converted</source> - </trans-unit> - <trans-unit id="attributes_hidden"> - <source>Hidden</source> - </trans-unit> - <trans-unit id="attributes_height"> - <source>Height</source> - </trans-unit> - <trans-unit id="attributes_id"> - <source>Id</source> - </trans-unit> - <trans-unit id="attributes_inputmode"> - <source>Inputmode</source> - </trans-unit> - <trans-unit id="attributes_inputmode_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_inputmode_verbatim"> - <source>Verbatim</source> - </trans-unit> - <trans-unit id="attributes_inputmode_latin"> - <source>Latin</source> - </trans-unit> - <trans-unit id="attributes_inputmode_latin-name"> - <source>Latin-name</source> - </trans-unit> - <trans-unit id="attributes_inputmode_latin-prose"> - <source>Latin-prose</source> - </trans-unit> - <trans-unit id="attributes_inputmode_full-width-latin"> - <source>Full-width-latin</source> - </trans-unit> - <trans-unit id="attributes_inputmode_kana"> - <source>Kana</source> - </trans-unit> - <trans-unit id="attributes_inputmode_kana-name"> - <source>Kana-name</source> - </trans-unit> - <trans-unit id="attributes_inputmode_katakana"> - <source>Katakana</source> - </trans-unit> - <trans-unit id="attributes_inputmode_numeric"> - <source>Numeric</source> - </trans-unit> - <trans-unit id="attributes_inputmode_tel"> - <source>Tel</source> - </trans-unit> - <trans-unit id="attributes_inputmode_email"> - <source>Email</source> - </trans-unit> - <trans-unit id="attributes_inputmode_url"> - <source>Url</source> - </trans-unit> - <trans-unit id="attributes_label"> - <source>Label</source> - </trans-unit> - <trans-unit id="attributes_lang"> - <source>Lang</source> - </trans-unit> - <trans-unit id="attributes_list"> - <source>List</source> - </trans-unit> - <trans-unit id="attributes_max"> - <source>Max</source> - </trans-unit> - <trans-unit id="attributes_maxlength"> - <source>Maxlength</source> - </trans-unit> - <trans-unit id="attributes_method"> - <source>Method</source> - </trans-unit> - <trans-unit id="attributes_min"> - <source>Min</source> - </trans-unit> - <trans-unit id="attributes_minlength"> - <source>Minlength</source> - </trans-unit> - <trans-unit id="attributes_method_get"> - <source>Get</source> - </trans-unit> - <trans-unit id="attributes_pattern"> - <source>Pattern</source> - </trans-unit> - <trans-unit id="attributes_method_post"> - <source>Post</source> - </trans-unit> - <trans-unit id="attributes_multiple"> - <source>Multiple</source> - </trans-unit> - <trans-unit id="attributes_name"> - <source>Name</source> - </trans-unit> - <trans-unit id="attributes_novalidate"> - <source>Novalidate</source> - </trans-unit> - <trans-unit id="attributes_placeholder"> - <source>Placeholder</source> - </trans-unit> - <trans-unit id="attributes_readonly"> - <source>Readonly</source> - </trans-unit> - <trans-unit id="attributes_required"> - <source>Required</source> - </trans-unit> - <trans-unit id="attributes_rows"> - <source>Rows</source> - </trans-unit> - <trans-unit id="attributes_selected"> - <source>Selected</source> - </trans-unit> - <trans-unit id="attributes_selectionDirection"> - <source>Selection direction</source> - </trans-unit> - <trans-unit id="attributes_selectionDirection_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_selectionDirection_forward"> - <source>Forward</source> - </trans-unit> - <trans-unit id="attributes_selectionDirection_backward"> - <source>Backward</source> - </trans-unit> - <trans-unit id="attributes_selectionEnd"> - <source>Selection end</source> - </trans-unit> - <trans-unit id="attributes_selectionStart"> - <source>Selection start</source> - </trans-unit> - <trans-unit id="attributes_size"> - <source>Size</source> - </trans-unit> - <trans-unit id="attributes_spellcheck"> - <source>Spellcheck</source> - </trans-unit> - <trans-unit id="attributes_spellcheck_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_spellcheck_true"> - <source>True</source> - </trans-unit> - <trans-unit id="attributes_spellcheck_false"> - <source>False</source> - </trans-unit> - <trans-unit id="attributes_src"> - <source>Src</source> - </trans-unit> - <trans-unit id="attributes_step"> - <source>Step</source> - </trans-unit> - <trans-unit id="attributes_style"> - <source>Style</source> - </trans-unit> - <trans-unit id="attributes_tabindex"> - <source>Tabindex</source> - </trans-unit> - <trans-unit id="attributes_text"> - <source>Text</source> - </trans-unit> - <trans-unit id="attributes_title"> - <source>Title</source> - </trans-unit> - <trans-unit id="attributes_translate"> - <source>Translate</source> - </trans-unit> - <trans-unit id="attributes_translate_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_translate_yes"> - <source>Yes</source> - </trans-unit> - <trans-unit id="attributes_translate_no"> - <source>No</source> - </trans-unit> - <trans-unit id="attributes_type"> - <source>Type</source> - </trans-unit> - <trans-unit id="attributes_type_button"> - <source>button</source> - </trans-unit> - <trans-unit id="attributes_type_checkbox"> - <source>checkbox</source> - </trans-unit> - <trans-unit id="attributes_type_color"> - <source>color</source> - </trans-unit> - <trans-unit id="attributes_type_date"> - <source>date</source> - </trans-unit> - <trans-unit id="attributes_type_datetime"> - <source>datetime</source> - </trans-unit> - <trans-unit id="attributes_type_datetime-local"> - <source>datetime-local</source> - </trans-unit> - <trans-unit id="attributes_type_email"> - <source>email</source> - </trans-unit> - <trans-unit id="attributes_type_file"> - <source>file</source> - </trans-unit> - <trans-unit id="attributes_type_hidden"> - <source>hidden</source> - </trans-unit> - <trans-unit id="attributes_type_image"> - <source>image</source> - </trans-unit> - <trans-unit id="attributes_type_month"> - <source>month</source> - </trans-unit> - <trans-unit id="attributes_type_number"> - <source>number</source> - </trans-unit> - <trans-unit id="attributes_type_password"> - <source>password</source> - </trans-unit> - <trans-unit id="attributes_type_radio"> - <source>radio</source> - </trans-unit> - <trans-unit id="attributes_type_range"> - <source>range</source> - </trans-unit> - <trans-unit id="attributes_type_reset"> - <source>reset</source> - </trans-unit> - <trans-unit id="attributes_type_search"> - <source>search</source> - </trans-unit> - <trans-unit id="attributes_type_submit"> - <source>submit</source> - </trans-unit> - <trans-unit id="attributes_type_tel"> - <source>tel</source> - </trans-unit> - <trans-unit id="attributes_type_text"> - <source>text</source> - </trans-unit> - <trans-unit id="attributes_type_time"> - <source>time</source> - </trans-unit> - <trans-unit id="attributes_type_url"> - <source>url</source> - </trans-unit> - <trans-unit id="attributes_type_week"> - <source>week</source> - </trans-unit> - <trans-unit id="attributes_value"> - <source>Value</source> - </trans-unit> - <trans-unit id="attributes_width"> - <source>Width</source> - </trans-unit> - <trans-unit id="attributes_wrap"> - <source>Wrap</source> - </trans-unit> - <trans-unit id="attributes_wrap_none"> - <source>Not set</source> - </trans-unit> - <trans-unit id="attributes_wrap_soft"> - <source>Soft</source> - </trans-unit> - <trans-unit id="attributes_wrap_hard"> - <source>Hard</source> - </trans-unit> - <trans-unit id="options_label"> - <source>Label Properties</source> - </trans-unit> - <trans-unit id="label_label"> - <source>Label</source> - </trans-unit> - <trans-unit id="label_layout"> - <source>Label position</source> - </trans-unit> - <trans-unit id="label_layout_front"> - <source>In front</source> - </trans-unit> - <trans-unit id="label_layout_back"> - <source>After</source> - </trans-unit> - <trans-unit id="options_legend"> - <source>Legend Properties</source> - </trans-unit> - <trans-unit id="legend_legend"> - <source>Legend</source> - </trans-unit> - <trans-unit id="options_filters"> - <source>Filters</source> - </trans-unit> - <trans-unit id="filters_emptytext"> - <source>Add a filter</source> - </trans-unit> - <trans-unit id="filters_alert_title"> - <source>Adding a filter</source> - </trans-unit> - <trans-unit id="filters_alert_description"> - <source>The selected filter is already present</source> - </trans-unit> - <trans-unit id="filters_dummy_title"> - <source>No filter selected</source> - </trans-unit> - <trans-unit id="filters_dummy_description"> - <source>To add a filter, select one from the dropdown</source> - </trans-unit> - <trans-unit id="filters_alphabetic"> - <source>Alphabetic</source> - </trans-unit> - <trans-unit id="filters_alphanumeric"> - <source>Alphanumeric</source> - </trans-unit> - <trans-unit id="filters_currency"> - <source>Currency</source> - </trans-unit> - <trans-unit id="filters_digit"> - <source>Digit</source> - </trans-unit> - <trans-unit id="filters_integer"> - <source>Integer</source> - </trans-unit> - <trans-unit id="filters_lowercase"> - <source>Lowercase</source> - </trans-unit> - <trans-unit id="filters_regexp"> - <source>Regular Expression</source> - </trans-unit> - <trans-unit id="filters_stripnewlines"> - <source>Strip New Lines</source> - </trans-unit> - <trans-unit id="filters_titlecase"> - <source>Titlecase</source> - </trans-unit> - <trans-unit id="filters_trim"> - <source>Trim</source> - </trans-unit> - <trans-unit id="filters_uppercase"> - <source>Uppercase</source> - </trans-unit> - <trans-unit id="filters_properties_allowwhitespace"> - <source>Allow whitespace</source> - </trans-unit> - <trans-unit id="filters_properties_decimalpoint"> - <source>Decimal point</source> - </trans-unit> - <trans-unit id="filters_properties_thousandseparator"> - <source>Thousand separator</source> - </trans-unit> - <trans-unit id="filters_properties_expression"> - <source>Expression</source> - </trans-unit> - <trans-unit id="filters_properties_characterlist"> - <source>Character list</source> - </trans-unit> - <trans-unit id="filters_properties_none"> - <source>This filter has no configuration settings</source> - </trans-unit> - <trans-unit id="options_validation"> - <source>Validation</source> - </trans-unit> - <trans-unit id="validation_emptytext"> - <source>Add a validation rule</source> - </trans-unit> - <trans-unit id="validation_alert_title"> - <source>Adding a validation rule</source> - </trans-unit> - <trans-unit id="validation_alert_description"> - <source>The selected validation rule is already present</source> - </trans-unit> - <trans-unit id="validation_dummy_title"> - <source>No validation rule selected</source> - </trans-unit> - <trans-unit id="validation_dummy_description"> - <source>To add a validation rule, select one from the dropdown</source> - </trans-unit> - <trans-unit id="validation_alphabetic"> - <source>Alphabetic</source> - </trans-unit> - <trans-unit id="validation_alphanumeric"> - <source>Alphanumeric</source> - </trans-unit> - <trans-unit id="validation_between"> - <source>Between</source> - </trans-unit> - <trans-unit id="validation_date"> - <source>Date</source> - </trans-unit> - <trans-unit id="validation_digit"> - <source>Digit</source> - </trans-unit> - <trans-unit id="validation_email"> - <source>Email address</source> - </trans-unit> - <trans-unit id="validation_equals"> - <source>Equals</source> - </trans-unit> - <trans-unit id="validation_fileallowedtypes"> - <source>Allowed mimetypes for file</source> - </trans-unit> - <trans-unit id="validation_filemaximumsize"> - <source>Maximum size for file (bytes)</source> - </trans-unit> - <trans-unit id="validation_fileminimumsize"> - <source>Minimum size for file (bytes)</source> - </trans-unit> - <trans-unit id="validation_float"> - <source>Float</source> - </trans-unit> - <trans-unit id="validation_greaterthan"> - <source>Greater than</source> - </trans-unit> - <trans-unit id="validation_inarray"> - <source>In array</source> - </trans-unit> - <trans-unit id="validation_integer"> - <source>Integer</source> - </trans-unit> - <trans-unit id="validation_ip"> - <source>Ip address</source> - </trans-unit> - <trans-unit id="validation_length"> - <source>Length</source> - </trans-unit> - <trans-unit id="validation_lessthan"> - <source>Less than</source> - </trans-unit> - <trans-unit id="validation_regexp"> - <source>Regular Expression</source> - </trans-unit> - <trans-unit id="validation_required"> - <source>Required</source> - </trans-unit> - <trans-unit id="validation_uri"> - <source>Uniform Resource Identifier</source> - </trans-unit> - <trans-unit id="validation_properties_message"> - <source>Message</source> - </trans-unit> - <trans-unit id="validation_properties_error"> - <source>Error</source> - </trans-unit> - <trans-unit id="validation_properties_showmessage"> - <source>Show message in label</source> - </trans-unit> - <trans-unit id="validation_properties_allowwhitespace"> - <source>Allow whitespace</source> - </trans-unit> - <trans-unit id="validation_properties_minimum"> - <source>Minimum</source> - </trans-unit> - <trans-unit id="validation_properties_maximum"> - <source>Maximum</source> - </trans-unit> - <trans-unit id="validation_properties_inclusive"> - <source>Inclusive</source> - </trans-unit> - <trans-unit id="validation_properties_format"> - <source>Format</source> - </trans-unit> - <trans-unit id="validation_properties_field"> - <source>Field</source> - </trans-unit> - <trans-unit id="validation_properties_array"> - <source>Array (Comma separated)</source> - </trans-unit> - <trans-unit id="validation_properties_expression"> - <source>Expression</source> - </trans-unit> - <trans-unit id="validation_properties_types"> - <source>Mime types</source> - </trans-unit> - <trans-unit id="options_fieldoptions"> - <source>Field options</source> - </trans-unit> - <trans-unit id="fieldoptions_emptytext"> - <source>No options to display</source> - </trans-unit> - <trans-unit id="fieldoptions_text"> - <source>Text</source> - </trans-unit> - <trans-unit id="fieldoptions_value"> - <source>Value</source> - </trans-unit> - <trans-unit id="fieldoptions_delete"> - <source>Delete</source> - </trans-unit> - <trans-unit id="fieldoptions_selected"> - <source>Selected</source> - </trans-unit> - <trans-unit id="fieldoptions_button_add"> - <source>Add option</source> - </trans-unit> - <trans-unit id="fieldoptions_new"> - <source>New option</source> - </trans-unit> - <trans-unit id="options_various"> - <source>Various Properties</source> - </trans-unit> - <trans-unit id="various_properties_name"> - <source>Name</source> - </trans-unit> - <trans-unit id="various_properties_content"> - <source>Content</source> - </trans-unit> - <trans-unit id="various_properties_headingsize"> - <source>Heading size</source> - </trans-unit> - <trans-unit id="various_properties_prefix"> - <source>Show prefix</source> - </trans-unit> - <trans-unit id="various_properties_suffix"> - <source>Show suffix</source> - </trans-unit> - <trans-unit id="various_properties_text"> - <source>Text</source> - </trans-unit> - <trans-unit id="various_properties_middlename"> - <source>Show middle name</source> - </trans-unit> - <trans-unit id="left_form"> - <source>Form</source> - </trans-unit> - <trans-unit id="form_prefix"> - <source>Prefix</source> - </trans-unit> - <trans-unit id="form_behaviour"> - <source>Behaviour</source> - </trans-unit> - <trans-unit id="behaviour_confirmation_page"> - <source>Confirmation page</source> - </trans-unit> - <trans-unit id="form_postprocessor"> - <source>Post Processors</source> - </trans-unit> - <trans-unit id="postprocessor_emptytext"> - <source>Add a Post Processor</source> - </trans-unit> - <trans-unit id="postprocessor_alert_title"> - <source>Adding a Post Processor</source> - </trans-unit> - <trans-unit id="postprocessor_alert_description"> - <source>The selected post processor is already present</source> - </trans-unit> - <trans-unit id="postprocessor_mail"> - <source>Send email</source> - </trans-unit> - <trans-unit id="postprocessor_redirect"> - <source>Redirect</source> - </trans-unit> - <trans-unit id="postprocessor_dummy_title"> - <source>No post processor selected</source> - </trans-unit> - <trans-unit id="postprocessor_dummy_description"> - <source>To add a post processor, select one from the dropdown</source> - </trans-unit> - <trans-unit id="postprocessor_properties_recipientemail"> - <source>Email address of the recipient</source> - </trans-unit> - <trans-unit id="postprocessor_properties_senderemail"> - <source>Email address of the sender</source> - </trans-unit> - <trans-unit id="postprocessor_properties_subject"> - <source>Subject</source> - </trans-unit> - <trans-unit id="postprocessor_properties_destination"> - <source>Destination to redirect to</source> - </trans-unit> - <trans-unit id="prefix_prefix"> - <source>Prefix</source> - </trans-unit> - <trans-unit id="elements_dummy_title"> - <source>You haven't added any elements yet!</source> - </trans-unit> - <trans-unit id="elements_dummy_description"> - <source>To get started, drag an element from the left panel onto this area</source> - </trans-unit> - <trans-unit id="elements_button_delete"> - <source>Delete this element</source> - </trans-unit> - <trans-unit id="elements_button_edit"> - <source>Edit this element</source> - </trans-unit> - <trans-unit id="elements_confirm_delete_title"> - <source>Delete element</source> - </trans-unit> - <trans-unit id="elements_confirm_delete_description"> - <source>Are you sure you want to delete the selected element?</source> - </trans-unit> - <trans-unit id="elements_label"> - <source>Edit this label</source> - </trans-unit> - <trans-unit id="elements_label_email"> - <source>Email</source> - </trans-unit> - <trans-unit id="elements_label_prefix"> - <source>Prefix</source> - </trans-unit> - <trans-unit id="elements_label_firstname"> - <source>First name</source> - </trans-unit> - <trans-unit id="elements_label_middlename"> - <source>Middle name</source> - </trans-unit> - <trans-unit id="elements_label_lastname"> - <source>Last name</source> - </trans-unit> - <trans-unit id="elements_label_suffix"> - <source>Suffix</source> - </trans-unit> - <trans-unit id="elements_legend"> - <source>Edit this legend</source> - </trans-unit> - <trans-unit id="elements_legend_name"> - <source>Full name</source> - </trans-unit> - <trans-unit id="elements_header_content"> - <source>Edit this header</source> - </trans-unit> - <trans-unit id="elements_textblock_content"> - <source>Edit this textblock</source> - </trans-unit> - <trans-unit id="elements_option_1"> - <source>Option 1</source> - </trans-unit> - <trans-unit id="elements_option_2"> - <source>Option 2</source> - </trans-unit> - <trans-unit id="elements_option_3"> - <source>Option 3</source> - </trans-unit> - <trans-unit id="elements_value_1"> - <source>Value 1</source> - </trans-unit> - <trans-unit id="elements_value_2"> - <source>Value 2</source> - </trans-unit> - <trans-unit id="elements_value_3"> - <source>Value 3</source> - </trans-unit> - </body> - </file> -</xliff> diff --git a/typo3/sysext/form/Resources/Private/Layouts/Default.html b/typo3/sysext/form/Resources/Private/Layouts/Default.html deleted file mode 100644 index 54d9aa0bb6bc6344e981179f79d369c297f47bec..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Layouts/Default.html +++ /dev/null @@ -1 +0,0 @@ -<f:render section="main" /> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Label.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Label.html deleted file mode 100644 index e39cf1f7bad6ff59e99e08c7cfa14ed0b12edba6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Label.html +++ /dev/null @@ -1 +0,0 @@ -<label>{model.additionalArguments.label}</label> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Legend.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Legend.html deleted file mode 100644 index 5a70ce3ee2eec493348c27a75afffb1c6453d58a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/AdditionalElements/Legend.html +++ /dev/null @@ -1,3 +0,0 @@ -<f:if condition="{model.additionalArguments.legend}"> - <legend>{model.additionalArguments.legend}</legend> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Checkboxgroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Checkboxgroup.html deleted file mode 100644 index 1018baa6079a270a85ebba3e51dce7fb0f3a5f23..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Checkboxgroup.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"> - <f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Legend', arguments: {model: model, themeName: themeName})} - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Fieldset.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Fieldset.html deleted file mode 100644 index 945aa07a55961d86c27520c1de7f5271a630bb6d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Fieldset.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.childElements.0}"> - <f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Legend', arguments: {model: model, themeName: themeName})} - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Form.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Form.html deleted file mode 100644 index b3fb2131f44d7fddbfdc7ff4da6fca1e620f979e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Form.html +++ /dev/null @@ -1,53 +0,0 @@ -<f:form - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - enctype="{model.additionalArguments.enctype}" - method="{model.additionalArguments.method}" - name="{model.additionalArguments.name}" - onreset="{model.additionalArguments.onreset}" - onsubmit="{model.additionalArguments.onsubmit}" - - absolute="{model.additionalArguments.absolute}" - action="dispatchConfirmationButtonClick" - actionUri="{model.additionalArguments.actionUri}" - addQueryString="{model.additionalArguments.addQueryString}" - additionalAttributes="{model.htmlAttributes}" - additionalParams="{model.additionalArguments.additionalParams}" - arguments="{model.additionalArguments.arguments}" - argumentsToBeExcludedFromQueryString="{model.additionalArguments.argumentsToBeExcludedFromQueryString}" - controller="Frontend" - extensionName="Form" - - format="{f:if(condition:'{model.additionalArguments.format}',then:'{model.additionalArguments.format}')}" - hiddenFieldClassName="{model.additionalArguments.hiddenFieldClassName}" - - object="{model}" - - pageType="{model.additionalArguments.pageType}" - pageUid="{model.additionalArguments.pageUid}" - pluginName="Form" - section="{model.additionalArguments.section}"> - - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - - <ol> - <li class="csc-form-confirmation-false"> - <f:form.submit name="confirmation-false" value="<f:translate key='tx_form_view_confirmation.donotconfirm'/>"><f:translate key='tx_form_view_confirmation.donotconfirm'/></f:form.submit> - </li> - <li class="csc-form-confirmation-true"> - <f:form.submit name="confirmation-true" value="<f:translate key='tx_form_view_confirmation.confirm'/>"><f:translate key='tx_form_view_confirmation.confirm'/></f:form.submit> - </li> - </ol> -</f:form> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Radiogroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Radiogroup.html deleted file mode 100644 index 1018baa6079a270a85ebba3e51dce7fb0f3a5f23..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/ContainerElements/Radiogroup.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"> - <f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Legend', arguments: {model: model, themeName: themeName})} - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Confirmation/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Checkbox.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Checkbox.html deleted file mode 100644 index 734eb4403aa336c7fbc356e78247a4ad1650979f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Checkbox.html +++ /dev/null @@ -1,49 +0,0 @@ -<f:if condition="{model.showElement}"> - <f:if condition="{model.additionalArguments.checked} == 'checked'"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - <f:if condition="{model.additionalArguments.value}">{model.additionalArguments.value}</f:if> - </li> - </f:if> -</f:if> - -<f:if condition="{model.additionalArguments.checked} == 'checked'"> - <f:if condition="{model.additionalArguments.multiple}"> - <f:then> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}][{model.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:then> - <f:else> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Hidden.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Hidden.html deleted file mode 100644 index 6f3c765a6eb97a9a4fbbcc9229800899a208fdec..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Hidden.html +++ /dev/null @@ -1,18 +0,0 @@ -<li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - additionalAttributes="{model.htmlAttributes}" - /> -</li> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Imagebutton.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Imagebutton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Input.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Input.html deleted file mode 100644 index e9c809fd24280319419570cfda2378acdc90901b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Input.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - {model.additionalArguments.value} - </li> -</f:if> - -<f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - additionalAttributes="{model.htmlAttributes}" -/> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/InputTypeButton.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/InputTypeButton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Password.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Password.html deleted file mode 100644 index f7e3d8cdb3b5e2a289c330831f5d26ee4e942995..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Password.html +++ /dev/null @@ -1,16 +0,0 @@ -<f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - additionalAttributes="{model.htmlAttributes}" -/> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Radio.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Radio.html deleted file mode 100644 index 0667ba983c66001c3c5b8eab1c671ab42b871b55..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Radio.html +++ /dev/null @@ -1,27 +0,0 @@ -<f:if condition="{model.showElement}"> - <f:if condition="{model.additionalArguments.checked} == 'checked'"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - <f:if condition="{model.additionalArguments.value}">{model.additionalArguments.value}</f:if> - </li> - </f:if> -</f:if> - -<f:if condition="{model.additionalArguments.checked} == 'checked'"> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - additionalAttributes="{model.htmlAttributes}" - /> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Reset.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Reset.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Select.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Select.html deleted file mode 100644 index 2baa6bdbca2a968ddd9f7e3354fff93e2df0d58d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Select.html +++ /dev/null @@ -1,111 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers} - -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - <ol> -</f:if> -<f:for each="{form:aggregateSelectOptions(model:model)}" as="option"> - <f:if condition="{option.options}"> - <f:then> - <f:for each="{option.options}" as="optgroupOption"> - <f:if condition="{optgroupOption.selected}"> - <f:if condition="{model.showElement}"> - <li class="csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {optgroupOption.label} - </li> - </f:if> - <f:if condition="{model.additionalArguments.multiple}"> - <f:then> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}][]" - value="{optgroupOption.value}" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:then> - <f:else> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{optgroupOption.value}" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:else> - </f:if> - </f:if> - </f:for> - </f:then> - <f:else> - <f:if condition="{option.selected}"> - <f:if condition="{model.showElement}"> - <li class="csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {option.label} - </li> - </f:if> - <f:if condition="{model.additionalArguments.multiple}"> - <f:then> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}][]" - value="{option.value}" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:then> - <f:else> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{option.value}" - - additionalAttributes="{model.htmlAttributes}" - /> - </f:else> - </f:if> - </f:if> - </f:else> - </f:if> -</f:for> -<f:if condition="{model.showElement}"> - </ol> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Submit.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Submit.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textarea.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textarea.html deleted file mode 100644 index eaedfd0856f90d46192acd7fe8cbcb8d069a1d82..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textarea.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - {model.additionalArguments.text} - </li> -</f:if> - -<f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.text}" - - additionalAttributes="{model.htmlAttributes}" -/> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textblock.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textblock.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textfield.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textfield.html deleted file mode 100644 index 4145a534afe10d0d1f639d662a1d91eb6783276a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Textfield.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - {model.additionalArguments.value} - </li> -</f:if> - -<f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - additionalAttributes="{model.htmlAttributes}" -/> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Upload.html b/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Upload.html deleted file mode 100644 index fae3e351b939ab0e2045d8782d31154fc6bb07bd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Upload.html +++ /dev/null @@ -1,8 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Confirmation/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - <f:for each="{model.additionalArguments.uploadedFiles}" as="uploadedFile"> - {uploadedFile.name}<br /> - </f:for> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Label.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Label.html deleted file mode 100644 index 9dc9dfbeddbfa1b3d0678a3121c35fffc6246524..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Label.html +++ /dev/null @@ -1 +0,0 @@ -<em>{model.additionalArguments.label}</em> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Legend.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Legend.html deleted file mode 100644 index e6420befc51c2c7cb5b493d2f0c45ac15a2e0372..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/AdditionalElements/Legend.html +++ /dev/null @@ -1 +0,0 @@ -{model.additionalArguments.legend} \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Checkboxgroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Checkboxgroup.html deleted file mode 100644 index 4fa40c7046a27a7dde1056b30dfb59fb2bd167a0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Checkboxgroup.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"> - <f:if condition="{model.showElement}"> - <f:then> - <tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <f:if condition="{model.additionalArguments.legend}"> - <thead> - <tr> - <th colspan="2" align="left"> - {f:render(partial: 'AdditionalElements/Legend', arguments: {model: model})} - </th> - </tr> - </thead> - </f:if> - <tbody> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </tbody> - </table> - </td> - </tr> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Fieldset.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Fieldset.html deleted file mode 100644 index 8b4a9e74a669d38a3659e82d531d83f82271609c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Fieldset.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.childElements.0}"> - <f:if condition="{model.showElement}"> - <f:then> - <tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <f:if condition="{model.additionalArguments.legend}"> - <thead> - <tr> - <th colspan="2" align="left"> - {f:render(partial: 'AdditionalElements/Legend', arguments: {model: model})} - </th> - </tr> - </thead> - </f:if> - <tbody> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </tbody> - </table> - </td> - </tr> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Form.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Form.html deleted file mode 100644 index dc4d724a604f254f94443ded4d12ffac324155a4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Form.html +++ /dev/null @@ -1,14 +0,0 @@ -<html> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - </head> - <body> - <table cellspacing="0"> - <tbody> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </tbody> - </table> - </body> -</html> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Radiogroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Radiogroup.html deleted file mode 100644 index 4fa40c7046a27a7dde1056b30dfb59fb2bd167a0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/ContainerElements/Radiogroup.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"> - <f:if condition="{model.showElement}"> - <f:then> - <tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td colspan="2"> - <table cellspacing="0" style="padding-left: 20px; margin-bottom: 20px;"> - <f:if condition="{model.additionalArguments.legend}"> - <thead> - <tr> - <th colspan="2" align="left"> - {f:render(partial: 'AdditionalElements/Legend', arguments: {model: model})} - </th> - </tr> - </thead> - </f:if> - <tbody> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </tbody> - </table> - </td> - </tr> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{element.partialPath}" arguments="{model: element}" /> - </f:for> - </f:else> - </f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Button.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Button.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/ButtonTag.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/ButtonTag.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Checkbox.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Checkbox.html deleted file mode 100644 index a5d44397423efbd650badf82912dcd8665b76c33..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Checkbox.html +++ /dev/null @@ -1,10 +0,0 @@ -<f:if condition="{model.showElement}"> -<f:if condition="{model.additionalArguments.checked} == 'checked'"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td>{model.additionalArguments.value}</td> -</tr> -</f:if> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/ContentElement.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/ContentElement.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Header.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Header.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Hidden.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Hidden.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Imagebutton.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Imagebutton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Input.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Input.html deleted file mode 100644 index 3a539949329eaa4fba65a9eb7df6771d689ec010..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Input.html +++ /dev/null @@ -1,8 +0,0 @@ -<f:if condition="{model.showElement}"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td>{model.additionalArguments.value}</td> -</tr> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/InputTypeButton.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/InputTypeButton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Password.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Password.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Radio.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Radio.html deleted file mode 100644 index 73e16d87c7b196f266ac420d99db139d59250006..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Radio.html +++ /dev/null @@ -1,10 +0,0 @@ -<f:if condition="{model.showElement}"> -<f:if condition="{model.additionalArguments.checked} == 'checked'"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td>{model.additionalArguments.value}</td> -</tr> -</f:if> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Reset.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Reset.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Select.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Select.html deleted file mode 100644 index e071ed69d0c42e3e97a5f0c5cb0083fa88902fb2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Select.html +++ /dev/null @@ -1,26 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers} -<f:if condition="{model.showElement}"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td> -<f:for each="{form:aggregateSelectOptions(model:model)}" as="option"> -<f:if condition="{option.options}"> -<f:then> -<f:for each="{option.options}" as="optgroupOption"> -<f:if condition="{optgroupOption.selected}"> - <div class="csc-form-element csc-form-element-{model.elementTypeLowerCase}">{optgroupOption.label}</div> -</f:if> -</f:for> -</f:then> -<f:else> -<f:if condition="{option.selected}"> - <div class="csc-form-element csc-form-element-{model.elementTypeLowerCase}">{option.label}</div> -</f:if> -</f:else> -</f:if> -</f:for> - </td> -</tr> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Submit.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Submit.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textarea.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textarea.html deleted file mode 100644 index 367fe2a72231783f14f8e2d83891cb145605af7c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textarea.html +++ /dev/null @@ -1,8 +0,0 @@ -<f:if condition="{model.showElement}"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;" valign="top"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td>{model.additionalArguments.text}</td> -</tr> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textblock.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textblock.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textfield.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textfield.html deleted file mode 100644 index 3a539949329eaa4fba65a9eb7df6771d689ec010..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Textfield.html +++ /dev/null @@ -1,8 +0,0 @@ -<f:if condition="{model.showElement}"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td>{model.additionalArguments.value}</td> -</tr> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Upload.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Upload.html deleted file mode 100644 index 9459c26689f66d33428c7f55c42582a128129b17..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Html/FlatElements/Upload.html +++ /dev/null @@ -1,10 +0,0 @@ -<f:if condition="{model.showElement}"> -<tr class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <td style="width: 200px;"> - {f:render(partial: 'AdditionalElements/Label', arguments: {model: model})} - </td> - <td> -<f:for each="{model.additionalArguments.uploadedFiles}" as="uploadedFile">{uploadedFile.name}<br /></f:for> - </td> -</tr> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Checkboxgroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Checkboxgroup.html deleted file mode 100644 index 2a2a5e64fb17797eee1e359f449e3670ac9e26f1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Checkboxgroup.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"><f:if condition="{model.showElement}"><f:then><form:plainMail labelContent="{model}" newLineAfterLabel="1" indent="4" /><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for><form:plainMail indent="-4"/></f:then><f:else><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for></f:else></f:if></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Fieldset.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Fieldset.html deleted file mode 100644 index 7bfa2832b075d4dd7698cf6106795b656afa3622..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Fieldset.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.childElements.0}"><f:if condition="{model.showElement}"><f:then><form:plainMail labelContent="{model}" newLineAfterLabel="1" indent="4" /><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for><form:plainMail indent="-4"/></f:then><f:else><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for></f:else></f:if></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Form.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Form.html deleted file mode 100644 index 4a71b60e7da3d570e2eb8a9fb064f1f9ea5580b8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Form.html +++ /dev/null @@ -1,2 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers} -<form:plainMail content="{model}" /><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Radiogroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Radiogroup.html deleted file mode 100644 index 2a2a5e64fb17797eee1e359f449e3670ac9e26f1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/ContainerElements/Radiogroup.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.additionalArguments.atLeastOneCheckedChildElement}"><f:if condition="{model.showElement}"><f:then><form:plainMail labelContent="{model}" newLineAfterLabel="1" indent="4" /><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for><form:plainMail indent="-4"/></f:then><f:else><f:for each="{model.childElements}" as="element"><f:render partial="{element.partialPath}" arguments="{model: element}" /></f:for></f:else></f:if></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Button.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Button.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/ButtonTag.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/ButtonTag.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Checkbox.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Checkbox.html deleted file mode 100644 index 29119c77277c64a618eddbfcc49bed4b0b8233f6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Checkbox.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><f:if condition="{model.additionalArguments.checked} == 'checked'"><form:plainMail labelContent="{model}" content="{model.additionalArguments.value}" /></f:if></f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/ContentElement.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/ContentElement.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Header.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Header.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Hidden.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Hidden.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Imagebutton.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Imagebutton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Input.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Input.html deleted file mode 100644 index 76676300102b1071cea96043bf5c6d03bb04203e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Input.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" content="{model}" /></f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/InputTypeButton.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/InputTypeButton.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Password.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Password.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Radio.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Radio.html deleted file mode 100644 index 73e09419f92288838cb3ba3663ed9c67b0feafe8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Radio.html +++ /dev/null @@ -1,2 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><f:if condition="{model.additionalArguments.checked} == 'checked'"><form:plainMail labelContent="{model}" content="{model.additionalArguments.value}" /> -</f:if></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Reset.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Reset.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Select.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Select.html deleted file mode 100644 index 122c8666ff2045bd88639451c9e6d38dd00433ab..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Select.html +++ /dev/null @@ -1,3 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" newLineAfterLabel="1" indent="4" /><f:for each="{form:aggregateSelectOptions(model:model)}" as="option"><f:if condition="{option.options}"><f:then><f:for each="{option.options}" as="optgroupOption"><f:if condition="{optgroupOption.selected}"><form:plainMail content="{optgroupOption.label}" /> -</f:if></f:for></f:then><f:else><f:if condition="{option.selected}"><form:plainMail content="{option.label}" /> -</f:if></f:else></f:if></f:for><form:plainMail indent="-4"/></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Submit.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Submit.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textarea.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textarea.html deleted file mode 100644 index 5c6ea67aaed547d94866503eaf67023e5ab42dd5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textarea.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" content="{model.additionalArguments.text}" newLineAfterLabel="1" indent="4" /><form:plainMail indent="-4" /></f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textblock.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textblock.html deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textfield.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textfield.html deleted file mode 100644 index 76676300102b1071cea96043bf5c6d03bb04203e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Textfield.html +++ /dev/null @@ -1 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" content="{model}" /></f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Upload.html b/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Upload.html deleted file mode 100644 index bb9573121a7a5b43ff3185906705a72d9c146cbb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/PostProcessor/Mail/Plain/FlatElements/Upload.html +++ /dev/null @@ -1,2 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers}<f:if condition="{model.showElement}"><form:plainMail labelContent="{model}" newLineAfterLabel="1" indent="4" /><f:for each="{model.additionalArguments.uploadedFiles}" as="uploadedFile"><form:plainMail content="{uploadedFile.name}" /> -</f:for><form:plainMail indent="-4"/></f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/ErrorValidationMessage.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/ErrorValidationMessage.html deleted file mode 100644 index 891c7c7d1e200f9e621f6b8d2c392e3fdbaaf203..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/ErrorValidationMessage.html +++ /dev/null @@ -1,3 +0,0 @@ -<f:if condition="{model.validationErrorMessages}"> - <strong><f:for each="{model.validationErrorMessages}" as="errorValidationMessage" iteration="iterator">{errorValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></strong> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Label.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Label.html deleted file mode 100644 index b4840a4b4892a6fc9f1a260365d280bf93d973d4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Label.html +++ /dev/null @@ -1,5 +0,0 @@ -<label for="{model.additionalArguments.id}"> - {model.additionalArguments.label} - {f:render(partial: '{themeName}/Show/AdditionalElements/MandatoryValidationMessage', arguments: {model: model, themeName: themeName})} - {f:render(partial: '{themeName}/Show/AdditionalElements/ErrorValidationMessage', arguments: {model: model, themeName: themeName})} -</label> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Legend.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Legend.html deleted file mode 100644 index 7ec127594293f642f804ba39e242301985977148..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/Legend.html +++ /dev/null @@ -1,7 +0,0 @@ -<f:if condition="{model.additionalArguments.legend}"> - <legend> - {model.additionalArguments.legend} - {f:render(partial: '{themeName}/Show/AdditionalElements/MandatoryValidationMessage', arguments: {model: model, themeName: themeName})} - {f:render(partial: '{themeName}/Show/AdditionalElements/ErrorValidationMessage', arguments: {model: model, themeName: themeName})} - </legend> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/MandatoryValidationMessage.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/MandatoryValidationMessage.html deleted file mode 100644 index 4b38cea54a68b36b53465f9e65afc1fae0326d99..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/AdditionalElements/MandatoryValidationMessage.html +++ /dev/null @@ -1,3 +0,0 @@ -<f:if condition="{model.mandatoryValidationMessages}"> - <em><f:for each="{model.mandatoryValidationMessages}" as="mandatoryValidationMessage" iteration="iterator">{mandatoryValidationMessage}<f:if condition="{iterator.isLast}"><f:else> - </f:else></f:if></f:for></em> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Checkboxgroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Checkboxgroup.html deleted file mode 100644 index fea70dee3ae712f1493245f9c955c51c3611d433..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Checkboxgroup.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - {f:render(partial: '{themeName}/Show/AdditionalElements/Legend', arguments: {model: model, themeName: themeName})} - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Fieldset.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Fieldset.html deleted file mode 100644 index 8921d4f5cf80a407ba7a6130456bbf0d8d9e0072..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Fieldset.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - <f:if condition="{model.additionalArguments.legend}"> - <legend>{model.additionalArguments.legend}</legend> - </f:if> - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Form.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Form.html deleted file mode 100644 index fff6fb537549b427336b8d456fba0ea5df11ec3a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Form.html +++ /dev/null @@ -1,44 +0,0 @@ -<f:form - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - enctype="{model.additionalArguments.enctype}" - method="{model.additionalArguments.method}" - name="{model.additionalArguments.name}" - onreset="{model.additionalArguments.onreset}" - onsubmit="{model.additionalArguments.onsubmit}" - - absolute="{model.additionalArguments.absolute}" - action="{model.additionalArguments.action}" - actionUri="{model.additionalArguments.actionUri}" - addQueryString="{model.additionalArguments.addQueryString}" - additionalAttributes="{model.htmlAttributes}" - additionalParams="{model.additionalArguments.additionalParams}" - arguments="{model.additionalArguments.arguments}" - argumentsToBeExcludedFromQueryString="{model.additionalArguments.argumentsToBeExcludedFromQueryString}" - controller="{model.additionalArguments.controller}" - extensionName="{model.additionalArguments.extensionName}" - - format="{f:if(condition:'{model.additionalArguments.format}',then:'{model.additionalArguments.format}')}" - hiddenFieldClassName="{model.additionalArguments.hiddenFieldClassName}" - - object="{model}" - - pageType="{model.additionalArguments.pageType}" - pageUid="{model.additionalArguments.pageUid}" - pluginName="{model.additionalArguments.pluginName}" - section="{model.additionalArguments.section}"> - - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> -</f:form> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Radiogroup.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Radiogroup.html deleted file mode 100644 index 562311e5c2e97c7c6302b047cb5dda827d147586..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/ContainerElements/Radiogroup.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <f:then> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <fieldset - <f:for each="{model.htmlAttributes}" as="htmAttributeValue" key="htmAttributeKey"> - {htmAttributeKey}="{htmAttributeValue}" - </f:for> - > - {f:render(partial: '{themeName}/Show/AdditionalElements/Legend', arguments: {model: model, themeName: themeName})} - <ol> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </ol> - </fieldset> - </li> - </f:then> - <f:else> - <f:for each="{model.childElements}" as="element"> - <f:render partial="{themeName}/Show/{element.partialPath}" arguments="{model: element, themeName: themeName}" /> - </f:for> - </f:else> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Button.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Button.html deleted file mode 100644 index c70ea7104167a9ba22619368e9460b9e7ef8283a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Button.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.button - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - type="{model.additionalArguments.type}" - - additionalAttributes="{model.htmlAttributes}" - >{model.additionalArguments.value}</f:form.button> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ButtonTag.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ButtonTag.html deleted file mode 100644 index 7d3735a748c76f25691d27dfce63f361ba1445eb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ButtonTag.html +++ /dev/null @@ -1,23 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.button - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - type="{model.additionalArguments.type}" - >{model.attributes.value.value}</f:form.button> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Checkbox.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Checkbox.html deleted file mode 100644 index 2782e80dff48760b8333cbf67a073db3ef2a7d97..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Checkbox.html +++ /dev/null @@ -1,50 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:if condition="{model.additionalArguments.multiple}"> - <f:then> - <f:form.checkbox - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}][{model.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - checked="{model.additionalArguments.checked}" - - errorClass="{model.additionalAttributes.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </f:then> - <f:else> - <f:form.checkbox - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - checked="{model.additionalArguments.checked}" - - errorClass="{model.additionalAttributes.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </f:else> - </f:if> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ContentElement.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ContentElement.html deleted file mode 100644 index 16f128849bec594524eca4d44cbe9a8a1ad4fe75..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/ContentElement.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <f:format.raw>{model.additionalArguments.content}</f:format.raw> - </li> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Header.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Header.html deleted file mode 100644 index 477d4985334be87e8e64668dfbe28520a0c9582b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Header.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <f:format.raw><{model.additionalArguments.headingSize}>{model.additionalArguments.content}</{model.additionalArguments.headingSize}></f:format.raw> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Hidden.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Hidden.html deleted file mode 100644 index 6f3c765a6eb97a9a4fbbcc9229800899a208fdec..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Hidden.html +++ /dev/null @@ -1,18 +0,0 @@ -<li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <f:form.hidden - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - additionalAttributes="{model.htmlAttributes}" - /> -</li> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Imagebutton.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Imagebutton.html deleted file mode 100644 index c60c4646aff2e223e1c96501fee6673604e65c4d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Imagebutton.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textfield - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - placeholder="{model.additionalArguments.placeholder}" - pattern="{model.additionalArguments.pattern}" - required="{model.additionalArguments.required}" - type="{model.additionalArguments.type}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Input.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Input.html deleted file mode 100644 index c60c4646aff2e223e1c96501fee6673604e65c4d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Input.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textfield - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - placeholder="{model.additionalArguments.placeholder}" - pattern="{model.additionalArguments.pattern}" - required="{model.additionalArguments.required}" - type="{model.additionalArguments.type}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/InputTypeButton.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/InputTypeButton.html deleted file mode 100644 index ec954789f047a9d47f9104e749cbd4632065d0c1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/InputTypeButton.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textfield - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - placeholder="{model.additionalArguments.placeholder}" - pattern="{model.additionalArguments.pattern}" - required="{model.additionalArguments.required}" - type="{model.additionalArguments.type}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Password.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Password.html deleted file mode 100644 index f384b7acae12ee304f8628f1ac7be83262056922..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Password.html +++ /dev/null @@ -1,26 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.password - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Radio.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Radio.html deleted file mode 100644 index 1b1e5167ac9bfe17673402257315023328e52b35..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Radio.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.radio - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="<f:if condition='{model.additionalArguments.value}'><f:then>{model.additionalArguments.value}</f:then><f:else>{model.additionalArguments.name}-{model.elementCounter}</f:else></f:if>" - - checked="{model.additionalArguments.checked}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Reset.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Reset.html deleted file mode 100644 index ec954789f047a9d47f9104e749cbd4632065d0c1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Reset.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textfield - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - autofocus="{model.additionalArguments.autofocus}" - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - placeholder="{model.additionalArguments.placeholder}" - pattern="{model.additionalArguments.pattern}" - required="{model.additionalArguments.required}" - type="{model.additionalArguments.type}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Select.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Select.html deleted file mode 100644 index 7270eb7eb0f27f19f736116437ae44c66630b3d5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Select.html +++ /dev/null @@ -1,36 +0,0 @@ -{namespace form=TYPO3\CMS\Form\ViewHelpers} - -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <form:select - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{form:aggregateSelectOptions(model:model, returnSelectedValues: 1)}" - - multiple="{model.additionalArguments.multiple}" - size="{model.additionalArguments.size}" - - optionLabelField="label" - optionValueField="value" - options="{form:aggregateSelectOptions(model:model)}" - prependOptionLabel="{model.additionalArguments.prependOptionLabel}" - prependOptionValue="{model.additionalArguments.prependOptionValue}" - selectAllByDefault="{model.additionalArguments.selectAllByDefault}" - sortByOptionLabel="{model.additionalArguments.sortByOptionLabel}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Submit.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Submit.html deleted file mode 100644 index cf6c9d20d21c008d919dc47cd319dd8962eea548..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Submit.html +++ /dev/null @@ -1,20 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.submit - additionalAttributes="{model.htmlAttributes}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textarea.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textarea.html deleted file mode 100644 index 61ff619ca6a15f263d43c4ef957743a13a7b562d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textarea.html +++ /dev/null @@ -1,28 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textarea - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.text}" - - autofocus="{model.additionalArguments.autofocus}" - rows="{model.additionalArguments.rows}" - cols="{model.additionalArguments.cols}" - placeholder="{model.additionalArguments.placeholder}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textblock.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textblock.html deleted file mode 100644 index 625809e71b66c6ed010cf4d5bfc90e5da1c3e60c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textblock.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - <f:format.raw>{model.additionalArguments.text}</f:format.raw> - </li> -</f:if> \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textfield.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textfield.html deleted file mode 100644 index 14c1d62aefb93c46fe50d2c5273447f1bb4bc904..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Textfield.html +++ /dev/null @@ -1,31 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.textfield - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - value="{model.additionalArguments.value}" - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - - autofocus="{model.additionalArguments.autofocus}" - maxlength="{model.additionalArguments.maxlength}" - size="{model.additionalArguments.size}" - placeholder="{model.additionalArguments.placeholder}" - pattern="{model.additionalArguments.pattern}" - required="{model.additionalArguments.required}" - type="{model.additionalArguments.type}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Upload.html b/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Upload.html deleted file mode 100644 index 9f858309738265c1ea0e4fc3d9d8b436289daa90..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Partials/Default/Show/FlatElements/Upload.html +++ /dev/null @@ -1,25 +0,0 @@ -<f:if condition="{model.showElement}"> - <li class="csc-form-{model.elementCounter} csc-form-element csc-form-element-{model.elementTypeLowerCase}"> - {f:render(partial: '{themeName}/Show/AdditionalElements/Label', arguments: {model: model, themeName: themeName})} - - <f:form.upload - class="{model.additionalArguments.class}" - dir="{model.additionalArguments.dir}" - id="{model.additionalArguments.id}" - lang="{model.additionalArguments.lang}" - style="{model.additionalArguments.style}" - title="{model.additionalArguments.title}" - accesskey="{model.additionalArguments.accesskey}" - tabindex="{model.additionalArguments.tabindex}" - onclick="{model.additionalArguments.onclick}" - - name="{model.additionalArguments.prefix}[{model.additionalArguments.name}]" - value="{model.additionalArguments.value}" - - multiple="{model.additionalArguments.multiple}" - - errorClass="{model.additionalArguments.errorClass}" - additionalAttributes="{model.htmlAttributes}" - /> - </li> -</f:if> diff --git a/typo3/sysext/form/Resources/Private/Templates/Frontend/AfterProcess.html b/typo3/sysext/form/Resources/Private/Templates/Frontend/AfterProcess.html deleted file mode 100644 index 0592e2b79c6e40045f38abb7c5d1b15812987be0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/Frontend/AfterProcess.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:layout name="Default" /> - -<f:section name="main"> - <f:format.raw>{postProcessorContent}</f:format.raw> -</f:section> diff --git a/typo3/sysext/form/Resources/Private/Templates/Frontend/Confirmation.html b/typo3/sysext/form/Resources/Private/Templates/Frontend/Confirmation.html deleted file mode 100644 index 0fbefd5917f87596224c3fd4c8b49cb8963d6efa..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/Frontend/Confirmation.html +++ /dev/null @@ -1,6 +0,0 @@ -<f:layout name="Default" /> - -<f:section name="main"> - <f:format.raw>{message}</f:format.raw> - <f:render partial="{model.themeName}/Confirmation/ContainerElements/Form" arguments="{model: model, themeName: model.themeName}" /> -</f:section> diff --git a/typo3/sysext/form/Resources/Private/Templates/Frontend/Show.html b/typo3/sysext/form/Resources/Private/Templates/Frontend/Show.html deleted file mode 100644 index 31ed85e898be64301bc36a00b8f713bb4ca37adc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/Frontend/Show.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:layout name="Default" /> - -<f:section name="main"> - <f:render partial="{model.themeName}/Show/ContainerElements/Form" arguments="{model: model, themeName: model.themeName}" /> -</f:section> diff --git a/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Html.html b/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Html.html deleted file mode 100644 index e50cfa8afb0f8c409ba09d8ea59c11c89caab44d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Html.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:layout name="Default" /> - -<f:section name="main"> - <f:render partial="ContainerElements/Form" arguments="{model: model}" /> -</f:section> diff --git a/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Plain.html b/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Plain.html deleted file mode 100644 index 66119ca554d0d34e7ac78348ac38560a38c967a2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/PostProcessor/Mail/Default/Plain.html +++ /dev/null @@ -1,5 +0,0 @@ -<f:layout name="Default" /> - -<f:section name="main"> - <f:render partial="ContainerElements/Form" arguments="{model: model, themeName: model.themeName}" /> -</f:section> diff --git a/typo3/sysext/form/Resources/Private/Templates/Wizard.html b/typo3/sysext/form/Resources/Private/Templates/Wizard.html deleted file mode 100644 index f498835def3a6a079b037d0bbac70f1a15a9e51f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Private/Templates/Wizard.html +++ /dev/null @@ -1,71 +0,0 @@ -<!-- ###FULLDOC### begin --> -<div class="typo3-fullDoc"> - <div id="typo3-docheader"> - <div class="typo3-docheader-functions"> - <div class="left">###CSH###</div> - <div class="right"></div> - </div> - <div class="typo3-docheader-buttons"> - <div class="left">###BUTTONLIST_LEFT###</div> - <div class="right">###BUTTONLIST_RIGHT###</div> - </div> - </div> - - <div id="typo3-docbody"> - <div id="typo3-inner-docbody"> - ###CONTENT### - </div> - </div> -</div> -<!-- ###FULLDOC### end --> - -<!-- Grouping the icons on top --> - -<!-- ###BUTTON_GROUP_WRAP### --> - <div class="buttongroup">###BUTTONS###</div> -<!-- ###BUTTON_GROUP_WRAP### --> - -<!-- ###BUTTON_GROUPS_LEFT### --> -<!-- ###BUTTON_GROUP1### -->###CLOSE###<!-- ###BUTTON_GROUP1### --> -<!-- ###BUTTON_GROUP2### -->###SAVE######SAVE_CLOSE###<!-- ###BUTTON_GROUP2### --> -<!-- ###BUTTON_GROUPS_LEFT### --> - -<!-- ###BUTTON_GROUPS_RIGHT### --> -<!-- ###BUTTON_GROUP1### -->###RELOAD###<!-- ###BUTTON_GROUP1### --> -<!-- ###BUTTON_GROUPS_RIGHT### --> -<!-- ###FULLDOC### begin --> -<div class="typo3-fullDoc"> - <!-- Page header with buttons, path details and csh --> - <div id="typo3-docheader"> - <div class="typo3-docheader-functions"> - <div class="left">###CSH###</div> - <div class="right"></div> - </div> - <div class="typo3-docheader-buttons"> - <div class="left">###BUTTONLIST_LEFT###</div> - <div class="right">###BUTTONLIST_RIGHT###</div> - </div> - </div> - <!-- Content of module, for instance listing, info or editing --> - <div id="typo3-docbody"> - <div id="typo3-inner-docbody"> - ###CONTENT### - </div> - </div> -</div> -<!-- ###FULLDOC### end --> - -<!-- Grouping the icons on top --> - -<!-- ###BUTTON_GROUP_WRAP### --> - <div class="buttongroup">###BUTTONS###</div> -<!-- ###BUTTON_GROUP_WRAP### --> - -<!-- ###BUTTON_GROUPS_LEFT### --> -<!-- ###BUTTON_GROUP1### -->###CLOSE###<!-- ###BUTTON_GROUP1### --> -<!-- ###BUTTON_GROUP2### -->###SAVE######SAVE_CLOSE###<!-- ###BUTTON_GROUP2### --> -<!-- ###BUTTON_GROUPS_LEFT### --> - -<!-- ###BUTTON_GROUPS_RIGHT### --> -<!-- ###BUTTON_GROUP1### -->###RELOAD###<!-- ###BUTTON_GROUP1### --> -<!-- ###BUTTON_GROUPS_RIGHT### --> diff --git a/typo3/sysext/form/Resources/Public/Css/form.css b/typo3/sysext/form/Resources/Public/Css/form.css index b0f77e2c846261c17fe025326d4b1fb96587ae2e..07ec5253b563a6d2c9a115e97c6f6021feda83b6 100644 --- a/typo3/sysext/form/Resources/Public/Css/form.css +++ b/typo3/sysext/form/Resources/Public/Css/form.css @@ -11,576 +11,823 @@ * * The TYPO3 project - inspiring people to share! */ -.std-em-selector { - font-size: 90%; - font-style: normal; +.t3-form-x-component { + position: absolute; + top: 0; + height: 100%; + line-height: normal; + background: #f5f5f5; } -.std-strong-selector { - display: block; - font-size: 90%; - font-weight: normal; - color: #C00; -} -.std-li-selector { - float: none; - width: auto; - margin-right: 0; - margin-left: 1em; +.t3-form-x-component a { + text-decoration: none; +} +.t3-form-x-component ol, +.t3-form-x-component ul { + list-style: none; + padding: 0; } -#fake-form { - /* style for each form element */ - /* labels as block, labels displayed above or below the input fields */ +.t3-form-x-component .ui-sortable-placeholder { + outline-offset: -1px !important; } -#fake-form ol { - padding-left: 0 !important; - list-style: none !important; +.t3-form-x-component-inner-wrapper { + padding: 1.5em; } -#fake-form li { +#t3-form-navigation-component { overflow: hidden; - padding: 0.5em; - margin-bottom: 0.5em; + left: 0; } -#fake-form li#element-placeholder { - padding: 0; - margin: 0; +#t3-form-structure-panel { + overflow: auto; + padding-top: 65px; + height: 100%; } -#fake-form li input + label, -#fake-form li textarea + label, -#fake-form li select + label { - float: none; - width: auto; - margin-right: 0; - margin-left: 1em; +#t3-form-structure-panel .icon { + z-index: 1; } -#fake-form li textarea + label { - vertical-align: top; +#t3-form-structure-panel #t3-form-navigation-component-tree-root-container, +#t3-form-structure-panel .tree li > div { + border: 1px solid transparent; + cursor: pointer; } -#fake-form textarea, -#fake-form input[type=text] { - border: 1px solid #c0c0c0; +#t3-form-structure-panel .tree .svg-wrapper svg { + overflow: visible; + position: relative; + top: -0.8em; + left: 0.6em; } -#fake-form input[type=text] { - width: 300px; - padding: 3px; +#t3-form-structure-panel .tree .svg-wrapper path { + fill: none; + shape-rendering: crispEdges; + stroke: #dddddd; + stroke-width: 1; } -#fake-form label { - display: block; - margin-right: 1em; - vertical-align: baseline; +#t3-form-structure-panel .tree li { + white-space: nowrap; } -#fake-form label em { - font-size: 90%; - font-style: normal; +#t3-form-structure-panel .tree li .icon-actions-pagetree-collapse { + margin-right: 0.3em; } -#fake-form label strong { - display: block; - font-size: 90%; - font-weight: normal; - color: #C00; +#t3-form-structure-panel .tree li .icon-actions-pagetree-collapse img { + transform: rotate(90deg); + transition: transform 0.2s; } -#fake-form .x-checkbox label, -#fake-form .x-radio label { - display: inline-block; +#t3-form-structure-panel .tree li.mjs-nestedSortable-collapsed > ol { + display: none; } -#fake-form legend { - border-bottom: 0; +#t3-form-structure-panel .tree li.mjs-nestedSortable-collapsed .icon-actions-pagetree-collapse img { + transform: rotate(0deg); + transition: transform 0.2s; +} +#t3-form-structure-panel .tree li small { + padding-left: 0.5em; + font-size: 80%; +} +#t3-form-structure-panel .tree .t3-form-icon { + margin-right: 0.5em; + margin-left: 0.5em; +} +#t3-form-structure-panel .tree .t3-form-element-has-children > div .t3-form-icon { + margin-left: 0.1em; +} +#t3-form-structure-panel .tree .sortable-hover { + outline: 1px solid #aaaaaa; +} +#t3-form-structure-panel .tree li > div:hover, +#t3-form-structure-panel .t3-form-form-element-selected, +#t3-form-structure-panel #t3-form-navigation-component-tree-root-container:hover, +#t3-form-structure-panel .t3-form-root-element-selected { + background-color: #f2f2f2; + border-color: #dcdcdc; + border-radius: 2px; + margin-left: -2em; + padding-left: 2em; + margin-right: -1.3em; +} +#t3-form-structure-panel .tree li > .t3-form-form-element-selected, +#t3-form-structure-panel .tree li > .t3-form-form-element-selected:hover, +#t3-form-structure-panel #t3-form-navigation-component-tree-root-container.t3-form-root-element-selected, +#t3-form-structure-panel #t3-form-navigation-component-tree-root-container.t3-form-root-element-selected:hover { + background-color: #fff; + border-color: #dcdcdc; } -#fake-form legend em { - font-size: 90%; - font-style: normal; +#t3-form-structure-panel .t3-form-x-component-inner-wrapper { + padding-top: 2.5em; } -#fake-form legend strong { - display: block; - font-size: 90%; - font-weight: normal; - color: #C00; +.form-group.t3-form-collection-element-remove-button, +.t3-form-inspector-finishers-editor-removeButton, +.form-group.t3-form-inspector-validators-editor-removeButton { + margin: 0 !important; + font-size: 0; } -#fake-form fieldset { - position: relative; +#t3-form-inspector-panels-container { + overflow: hidden; + right: 0; + padding-top: 65px; +} +#t3-form-inspector-panels { + overflow: auto; + height: 100%; +} +#t3-form-inspector { + padding: 1em 0.5em; +} +#t3-form-inspector h2, +#t3-form-inspector h3, +#t3-form-inspector h4 { margin: 0; - padding: 0; + padding: 0.1em 0.2em 0.2em 0.5em; + border-top: 1px solid #c3c3c3; + clear: both; + font: inherit; + font-weight: bold; } -#fake-form fieldset.submit { - border-style: none; +#t3-form-inspector h2 { + padding-bottom: 1em; + border: none; + border-bottom: 1px solid #c3c3c3; } -#fake-form fieldset.fieldset-horizontal { - border-width: 0; +#t3-form-inspector > h2:first-child { + border-top: none; } -#fake-form fieldset.fieldset-horizontal.label-below label { - display: block; - margin-left: 0; - margin-top: 0.2em; - font-size: 90%; - text-align: left; - color: #999999; +#t3-form-inspector h3 { + color: #000; + padding-top: 0.3em; + border: none; } -#fake-form fieldset.fieldset-horizontal label em { - display: inline; +#t3-form-inspector h4 { + padding: 0.8em 3em 0.8em 2.5em; + font-weight: 500; + background-color: #ddd; } -#fake-form fieldset.fieldset-horizontal ol { - padding: 0; +#t3-form-inspector h4 span[data-template-property="label"] { + vertical-align: top; } -#fake-form fieldset.fieldset-horizontal li { - float: left; - margin-right: 1em; - padding: 0; +#t3-form-inspector .t3-form-remove-element-button { + position: absolute; + top: 90px; + right: 2.5em; } -#fake-form fieldset.fieldset-subgroup { - margin-bottom: -2em; - border-style: none; +#t3-form-inspector .t3-form-control-group, +#t3-form-inspector .t3-form-add-collection-element { + margin: 1.5em 0.5em; + clear: both; } -#fake-form fieldset.fieldset-subgroup ol { - position: relative; - top: -1.4em; - padding: 0; +#t3-form-inspector .t3-form-inspector-editor-requiredValidator label { + cursor: pointer; } -#fake-form fieldset.fieldset-subgroup li { - padding: 0; +.t3-form-add-collection-element { + padding-bottom: 1em; } -#fake-form fieldset.fieldset-subgroup legend { - margin-left: 0; - padding: 0; +.t3-form-collection-container { + margin-top: -1em; + padding: 0.6em; } -#fake-form fieldset.fieldset-subgroup input + label { - float: none; - width: auto; - display: inline; - margin: 0 0 0 1em; +.t3-form-collection-container .ui-sortable-handle { + cursor: auto; } -#fake-form legend { - font-size: 12px; - font-weight: bold; - color: #000000; +.t3-form-collection-container h4 { + cursor: move; } -#fake-form legend em { +.t3-form-collection-container .icon-actions-view-table-expand { position: absolute; + left: 0.5em; +} +.t3-form-collection-container a.collapsed .icon-actions-view-table-expand svg { + transform: rotate(0deg); + transition: transform 0.2s; +} +.t3-form-collection-container a:not(.collapsed) .icon-actions-view-table-expand svg { + transform: rotate(90deg); + transition: transform 0.2s; +} +.t3-form-collection-element { + position: relative; + margin-bottom: 0.5em; + border: 1px solid #c3c3c3; + border-top: none; + background: #f5f5f5; } -#fake-form legend strong { +.t3-form-collection-element .t3-form-collection-element-remove-button { position: absolute; - top: 1.4em; + right: 0.5em; + top: 0.6em; } -#fake-form .labels-block label { - display: block; - float: none; - margin: 0 0 0.5em; - width: auto; +.property-grid .form-control { + min-width: initial; + min-width: auto; + font-size: 0.9em; } -#fake-form .labels-block input + label, -#fake-form .labels-block textarea + label { - margin: 0.5em 0 0; +.property-grid .table th { + font-size: 0.9em; } -/* labels alignment right */ -#fake-form .labels-alignment-right label, -#fake-form .labels-alignment-right .fieldset-subgroup legend, -#fake-form .labels-alignment-right.fieldset-subgroup legend { - text-align: right; +.property-grid .table > tbody > tr { + cursor: pointer; + background-color: #fafafa; } -#fake-form .labels-block fieldset.fieldset-subgroup, -#fake-form fieldset.labels-block.fieldset-subgroup { - margin-bottom: 0; +.property-grid .table > tbody > tr:last-child { + cursor: auto; } -#fake-form .labels-block .fieldset-subgroup legend, -#fake-form .labels-block.fieldset-subgroup legend { - width: auto; +.property-grid .table > tbody > tr > td { + padding: 0.6em 0.3em; + text-align: center; } -#fake-form .labels-block .fieldset-subgroup legend em, -#fake-form .labels-block.fieldset-subgroup legend em { - position: relative; +.property-grid .table > tbody > tr > td:first-child { + width: 35px; } -#fake-form .labels-block .fieldset-subgroup legend strong, -#fake-form .labels-block.fieldset-subgroup legend strong { - position: relative; - top: 0; +.property-grid .table > tbody > tr > td:nth-child(2), +.property-grid .table > tbody > tr > td:nth-child(3) { + width: 75px; } -#fake-form .labels-block .fieldset-subgroup ol, -#fake-form .labels-block.fieldset-subgroup ol { - top: 0; - margin: 0; - padding: 0.5em 0 0; +.property-grid .table > tbody > tr > td:nth-child(4) { + width: 65px; } -/* element HIDDEN */ -#fake-form .formwizard-element.hidden-element { - cursor: default; +.property-grid .table > tbody > tr > td:nth-child(5) { + width: 35px; } -#fake-form .formwizard-element .hidden-dummy-element { - margin: 0; - padding: 5px; - border: 1px dotted #A9A9A9; +.property-grid .table .btn { + background-color: #eee; + border-color: #bbb; } -/* styles for drag and drop content */ -.x-dd-drag-ghost .formwizard-element { - list-style: none; +.property-grid .sort-row-field { + cursor: move; } -.x-dd-drop-icon { - top: 7px; +.property-grid .ui-sortable-helper td { + border: none; } -.x-dd-drag-ghost ol { - margin: 5px 0; - padding: 0; - list-style: none; +.property-grid .ui-sortable-placeholder { + height: 45px; + border-left: 1px solid #c3c3c3 !important; + border-right: 1px solid #c3c3c3 !important; + outline-offset: -5px !important; } -.x-dd-drag-ghost .buttongroup, -.x-dd-drag-ghost label em, -.x-dd-drag-ghost label strong { - display: none; +#t3-form-stage-inner-container { + display: inline-block; + width: 90%; + text-align: left; } -.x-dd-drag-ghost label { - margin: 0 10px 0 5px; +@media (min-width: 1300px) { + #t3-form-stage-inner-container { + width: 600px; + } } -.x-dd-drag-ghost legend { - margin: 0 5px; - font-size: 14px; - font-weight: bold; - color: #000; +#t3-form-stage-container { + overflow: auto; + position: relative; + height: 100%; + text-align: left; +} +@media (min-width: 1300px) { + #t3-form-stage-container { + text-align: center; + } +} +#t3-form-stage-container ol, +#t3-form-stage-container ul { + list-style: none; +} +#t3-form-stage-container .form-section { border: none; } -.x-grid-panel .remove { - background-image: url("../Images/remove.gif"); - width: 15px; - height: 16px; +#t3-form-stage-container .panel-heading button { + outline: none; } -.x-dd-drag-proxy, -.x-dd-drop-nodrop { - background-color: #fff; - border-color: #c0c0c0; +#t3-form-stage-container .panel-heading .paginiation-label { + margin-right: 1em; } -.tab-content fieldset #formwizard { - display: inherit; +#t3-form-stage-container .t3-form-new-element-container { + height: 62px; + border: 1px dashed #ddd; + text-align: center; + padding-top: 31px; } -.tab-content fieldset.form-section { - float: left; - min-width: 380px; - width: 100%; - padding-bottom: 15px; +#t3-form-stage-container .t3-form-new-element-container .btn { + transform: translateY(-50%); +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract ol, +#t3-form-stage-container.t3-form-stage-viewmode-abstract ul { + padding-left: 40px; + padding-right: 1em; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-page-title { + margin: 0 0 0.5em; } -.tab-content fieldset.form-section:last-child { +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage-inner-container { + overflow: hidden; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit:not(.t3-form-element-toplevel) { margin-bottom: 1em; + padding-bottom: 1px; + outline: 1px solid #dddddd; + outline-offset: -1px; } -.tab-content fieldset.form-section ol#formwizard-right { - width: 100vw !important; - overflow: visible !important; - position: relative; - float: none; - left: 5px !important; - padding-top: 0; - padding-left: 0; - margin-right: 10px; - top: 30px !important; - display: table-cell; - height: auto !important; - list-style: none; - border-top-style: none; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit .sortable-hover { + outline-color: #777777; } -.tab-content fieldset.form-section ol#formwizard-right.hover { - left: 0; - width: auto; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit .t3-form-form-composit-element-selected { + outline-color: #0078e6; } -/* outer wrapper of whole wizard */ -#form-wizard-element { - z-index: 1; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit.sortable-hover > .ui-sortable-handle, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover { + border-color: #777777; } -#form-wizard-element #formwizard-left { - display: table-cell; - float: left !important; - margin-right: -1px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit.sortable-hover > .ui-sortable-handle .t3-form-icon-container, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-icon-container { + background-color: #777777; } -#form-wizard-element #formwizard-left .x-tab-panel-body { - height: 100% !important; - overflow: visible !important; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-composit.sortable-hover > .ui-sortable-handle .t3-form-icon-container path, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-icon-container path { + fill: #fff; } -/* inner wrapper of whole wizard */ -#formwizard { - background-color: #F8F8F8; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable fieldset { + position: relative; + min-height: 130px; + padding-top: 5em; } -/* applied when a element is moved */ -#formwizard.hover-move { - cursor: move; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable fieldset legend { + position: absolute; + top: 1em; + display: inline-block; + width: 95%; } -/* left panel */ -#formwizard-left.x-border-panel { +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle { + overflow: hidden; position: relative; - left: auto; - top: auto; + height: 62px; + margin-bottom: 1em; + border: 1px solid #ddd; + background-color: #fff; } -/* tabs */ -#formwizard-left .x-tab-panel-header { - background-color: transparent; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-validator-list { + right: 0; + transition: right 0.2s; } -/* tabs inner */ -#formwizard-left .x-tab-strip { - margin-bottom: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-element-info .element-content span, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-element-info .element-content div { + color: #5a5a5a; } -#formwizard-left .x-tab-strip-top .x-tab-left { - padding-right: 20px; -} -#formwizard-left .x-tab-strip-top .x-tab-right { - padding: 5px 10px 2px; - background-color: #EDEDED; - border-radius: 0; -} -#formwizard-left .x-tab-strip-top .x-tab-strip-active .x-tab-right, -#formwizard-left .x-tab-strip-top .x-tab-strip-active.x-tab-strip-over .x-tab-right { - background-color: transparent; - border-bottom-color: #F8F8F8; -} -#formwizard-left .x-tab-strip-top .x-tab-strip-over .x-tab-right { - background-color: #E1E1E1; -} -#formwizard-left li.validation-error .x-tab-left, -#formwizard-left div.validation-error .x-accordion-hd { - margin-right: 14px; - background-image: url("../../../../../t3skin/extjs/images/form/exclamation.gif"); - background-position: right 1px; - background-repeat: no-repeat; -} -/* content below tabs */ -#formwizard-left .x-tab-panel-body-content { - min-height: 330px; - padding: 10px; - background: transparent; - border: 1px solid #C0C0C0; - border-top-width: 0; -} -/* info messages (also for drag and drop) */ -#formwizard-left .message-information, -#fake-form .message-information, -.x-dd-drag-ghost .message-information { - margin: 10px 0 15px 16px; - padding: 12px 10px; - background-image: none; - border-radius: 0; - box-shadow: none; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:hover .t3-form-validator-info .t3-form-icon { + margin-right: 75px; + transition: margin 0.2s; } -#formwizard-left .message-information p, -#fake-form .message-information p, -.x-dd-drag-ghost .message-information { - margin: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle:has (.ui-sortable-handle:hover) { + border-color: transparent; } -/* intro info messages */ -#formwizard-left #formwizard-left-elements-intro, -#formwizard-left #formwizard-left-options-dummy, -#fake-form .message-information { - margin: 0 0 10px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-handle span { + color: #5a5a5a; } -#formwizard-left .x-tab-panel-body, -#formwizard-left .x-accordion-hd { - background: transparent none; - border-width: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-state-disabled { + cursor: auto; } -/* accordion */ -#formwizard-left .x-panel-accordion { - border-bottom: 1px solid #C7C7C7; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-state-disabled:hover { + background: none; } -#formwizard-left .x-panel-accordion:last-child { - border-bottom: medium none; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .ui-sortable-placeholder { + margin-bottom: 1em; } -/* headline of accordion */ -#formwizard-left .x-accordion-hd { - padding-left: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-icon-container { + float: left; + width: 40px; + height: 100%; + padding: 1em; + cursor: move; + background-color: #ddd; } -/* toggle icon of accordion */ -#formwizard-left .x-accordion-hd .x-tool-toggle { - margin: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-icon-container .t3-form-icon { + height: 100%; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-form-element-body { + height: 100%; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info { + position: relative; float: left; - background-image: url("../Images/module-menu-down.png"); - background-position: 0 4px; + width: 55%; + height: 100%; + padding-left: 1em; } -#formwizard-left .x-panel-collapsed .x-accordion-hd .x-tool-toggle { - background-image: url("../Images/module-menu-right.png"); - background-position: 1px 3px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info:before, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info:after { + display: block; + content: ''; + position: absolute; + bottom: 0; + right: 0; + left: 0; } -#formwizard-left .x-accordion-hd .x-panel-header-text { - font-weight: bold; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info:before { + height: 0.8em; + background: #fff; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info:after { + bottom: 0.8em; + height: 1em; + background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, #fff 100%); } -#formwizard-left .x-accordion-hd .x-panel-body { - padding-left: 15px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info .element-label-container { + float: left; + position: relative; + width: 45%; + height: 100%; } -/* element inside accordion */ -#formwizard-left .x-form { - margin-left: 15px; - margin-top: 10px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info .element-label-container .element-label { + overflow: hidden; + position: absolute; + top: 50%; + width: 100%; + text-overflow: ellipsis; + transform: translateY(-50%); } -#formwizard-left .x-form fieldset { - padding: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info .element-content { + padding-top: 1em; + white-space: nowrap; + font-size: 0.8em; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info .element-content span, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-element-info .element-content div { + color: #ddd; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info { + position: relative; + overflow: hidden; + float: right; + height: 100%; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-icon { + height: 100%; + z-index: 1; + margin-left: 1em; + transition: margin 0.3s; + filter: grayscale(100%); +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-validator-list { + position: absolute; + top: 0; + right: -100px; + width: 100px; + height: 100%; + padding: 1em 1em 1em 35px; + font-size: 0.8em; + transition: right 0.3s; + background-color: #ddd; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-validator-list:before, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-validator-list:after { + display: block; + content: ''; + position: absolute; + bottom: 0; + right: 0; + left: 0; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-validator-list:before { + height: 1em; + background: #ddd; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .t3-form-validator-list:after { + bottom: 1em; + height: 1em; + background: linear-gradient(to bottom, rgba(221, 221, 221, 0) 0%, #ddd 100%); +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract .t3-form-validator-info .validator-label { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #5a5a5a; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected { + position: relative; + padding-top: 35px; + height: 97px; border: none; } -#formwizard-left .x-form fieldset legend { - padding: 0; - font-size: 12px; - color: #222222; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-form-element-body { + border: 1px solid #0078e6; } -#formwizard-left .x-panel-tbar { - margin-top: 10px; - padding-left: 15px; - padding-bottom: 0; - border-width: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-icon-container { + background-color: #0078e6; } -#formwizard-left .x-panel-tbar .x-toolbar { - padding: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-element-info .element-content span, +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-element-info .element-content div { + color: #5a5a5a; } -#formwizard-left .x-table-layout { - margin-bottom: 10px; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-validator-list { + right: 0; + transition: right 0.2s; + background-color: #ebf3fb; } -/* generic element like textfield */ -#formwizard-left .formwizard-element { - margin-left: 12px; - background-color: transparent; - background-image: none; - border-color: transparent; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-validator-list:before { + background-color: #ebf3fb; } -#formwizard-left .formwizard-element.x-btn-over { - background-color: #D5D5D5; - background-image: -moz-linear-gradient(center top, #F6F6F6 10%, #D5D5D5 90%); - border-color: #C0C0C0; - border-radius: 0; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-validator-list:after { + background: linear-gradient(to bottom, rgba(235, 243, 251, 0) 0%, #ebf3fb 100%); } -#formwizard-left .formwizard-element .x-btn-mc { - text-align: left; +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .t3-form-validator-info .t3-form-icon { + margin-right: 75px; + filter: none; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 35px; + border: 1px solid #0078e6; + background-color: #0078e6; + padding-right: 0.7em; + padding-top: 0.4em; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container:before, +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container:after { + position: absolute; + top: 0; + display: block; + width: 1px; + height: 100%; + content: ' '; + background-color: #0078e6; +} +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container:before { + left: -1px; } -/* form elements in left panel */ -.formwizard-left-elements-basic-button { - background-image: url("../Images/ui-button.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container:after { + right: -1px; } -.formwizard-left-elements-basic-checkbox { - background-image: url("../Images/ui-check-box.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .dropdown-menu { + left: auto; + left: initial; + min-width: initial; + right: 0; + padding-left: 0; + padding-right: 0; + background-color: #005db3; } -.formwizard-left-elements-basic-fieldset { - background-image: url("../Images/ui-group-box.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .dropdown-menu > li a:hover { + background-color: #006bcd; } -.formwizard-left-elements-basic-fileupload { - background-image: url("../Images/drive-upload.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .caret { + color: #0078e6; } -.formwizard-left-elements-basic-hidden { - background-image: url("../Images/ui-text-field-hidden.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .t3-form-dropdown-buttons .icon { + margin-right: 0.5em; } -.formwizard-left-elements-basic-password { - background-image: url("../Images/ui-text-field-password.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .btn-toolbar { + float: right; } -.formwizard-left-elements-basic-radio { - background-image: url("../Images/ui-radio-button.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .btn-toolbar .btn { + background-color: #fff; + border-color: #fff; } -.formwizard-left-elements-basic-reset { - background-image: url("../Images/broom.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .btn-toolbar .btn:hover, +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .btn-toolbar .btn.active { + background-color: #ebf3fb; } -.formwizard-left-elements-basic-select { - background-image: url("../Images/ui-combo-box.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .btn-toolbar-container .btn-toolbar .icon svg path { + fill: #0078e6; } -.formwizard-left-elements-basic-submit { - background-image: url("../Images/ui-button-default.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .meta-label { + display: inline-block; + top: 1em; + left: 5em; + bottom: auto; + font-size: 0.9em; + color: #fff; } -.formwizard-left-elements-basic-textarea { - background-image: url("../Images/ui-scroll-pane-text.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract #t3-form-stage .t3-form-form-element-selected .meta-label span { + color: #fff; } -.formwizard-left-elements-basic-textline { - background-image: url("../Images/ui-text-field.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected { + border-color: #0078e6; } -.formwizard-left-elements-predefined-checkboxgroup { - background-image: url("../Images/ui-check-boxes.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected > .panel-heading { + background-color: #0078e6; + border-color: #0078e6; + color: #fff; } -.formwizard-left-elements-predefined-email { - background-image: url("../Images/mail.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected > .panel-heading .btn { + background-color: #fff; + border-color: #fff; } -.formwizard-left-elements-predefined-name { - background-image: url("../Images/user-silhouette.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected > .panel-heading .btn:hover, +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected > .panel-heading .btn.active { + background-color: #ebf3fb; } -.formwizard-left-elements-predefined-radiogroup { - background-image: url("../Images/ui-radio-buttons.png"); +#t3-form-stage-container.t3-form-stage-viewmode-abstract .panel.t3-form-form-stage-selected > .panel-heading .icon svg path { + fill: #0078e6; } -.formwizard-left-elements-content-header { - background-image: url("../Images/edit-heading.png"); +#t3-form-stage-container.t3-form-stage-viewmode-preview input[type="text"], +#t3-form-stage-container.t3-form-stage-viewmode-preview input[type="date"], +#t3-form-stage-container.t3-form-stage-viewmode-preview input[type="password"], +#t3-form-stage-container.t3-form-stage-viewmode-preview textarea, +#t3-form-stage-container.t3-form-stage-viewmode-preview select { + color: #000; + background-color: #e5e5e5; } -.formwizard-left-elements-content-textblock { - background-image: url("../Images/edit-textblock.png"); +#t3-form-stage-container.t3-form-stage-viewmode-preview ::-webkit-input-placeholder { + color: #737373; + font-style: italic; } -#formwizard-left .x-form-text { - height: 17px; +#t3-form-stage-container.t3-form-stage-viewmode-preview ::-moz-placeholder { + color: #737373; + font-style: italic; } -#formwizard-left .x-btn-text-icon .x-btn-icon-small-left .x-btn-text { - color: black; +#t3-form-stage-container.t3-form-stage-viewmode-preview :-ms-input-placeholder { + color: #737373; + font-style: italic; } -#formwizard-left .x-small-editor .x-form-text { - height: 13px !important; +#t3-form-stage-container.t3-form-stage-viewmode-preview ::placeholder { + color: #737373; + font-style: italic; } -/* icon in element field for applying entered text */ -#formwizard-left .x-form-field-wrap .x-form-submit-trigger { - background-image: url("../Images/submit-trigger.gif"); +#t3-form-stage-container.t3-form-stage-viewmode-preview input[type="date"] { + display: block; + width: 100%; + height: 32px; + padding: 0.6em; + font-size: 12px; + line-height: 1.5; + background-image: none; + border: 1px solid #c3c3c3; + border-radius: 2px; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; } -/* right panel */ -#formwizard-right { - min-height: 350px; - padding: 30px 0 10px 2px; - overflow: visible; +#t3-form-stage-container.t3-form-stage-viewmode-preview select[multiple="multiple"] { + height: auto; + min-height: 32px; } -#fake-form { - padding: 10px; - background-color: tansparent; - border: 1px solid #C0C0C0; +#t3-form-stage-container.t3-form-stage-viewmode-preview textarea { + min-height: 100px; } -#fake-form li { - overflow: visible; +#t3-form-stage-container.t3-form-stage-viewmode-preview legend.t3-form-form-element-selected { + border-color: #c3c3c3; } -/* visible area of element on right panel */ -#fake-form div.overflow-hidden { - overflow: hidden; +#t3-form-stage-container.t3-form-stage-viewmode-preview .form-navigation .btn-group span, +#t3-form-stage-container.t3-form-stage-viewmode-preview .form-navigation .btn-group button { + display: inline-block; + margin-right: 1em; } -#fake-form div.overflow-hidden input { - margin-left: 1px; +#t3-form-stage-container.t3-form-stage-viewmode-preview .preview-table-first-col { + width: 30%; } -/* wrap around all elements on right panel */ -#fake-form .formwizard-element { - border: 1px solid transparent; +#t3-form-stage-container.t3-form-stage-viewmode-preview .t3-form-element-preview { position: relative; + display: inline-block; + width: 100%; +} +#t3-form-stage-container.t3-form-stage-viewmode-preview .t3-form-new-element-container { + display: none; } -#fake-form .formwizard-element.hover, -#fake-form .formwizard-element.hidden.hover { - background-color: #F9FCFF; - border: 1px solid #C5DBE6; +#t3-form-stage-container.t3-form-stage-viewmode-preview .t3-form-element-toplevel > form > .tooltip { + top: 100px !important; } -#fake-form .formwizard-element.active, -#fake-form .formwizard-element.hidden.active { - background-color: #EAF7FF; - border: 1px solid #C5DBE6; +#t3-form-stage-container #t3-form-stage { + margin-bottom: 0; + padding-top: 0.5em; +} +#t3-form-stage-container #t3-form-stage > ol, +#t3-form-stage-container #t3-form-stage > ol > li > ol { + padding-left: 0; + padding-right: 0; } -#fake-form .formwizard-element.hidden { - min-height: 1em; - background-color: transparent; - border: 1px dotted #C5DBE6; +#t3-form-stage-container #t3-form-stage .t3-form-element-toplevel > .t3-form-form-element-selected { + height: auto; + padding-top: 0; } -/* toolbar on each element */ -#fake-form .formwizard-element div.buttongroup { +#t3-form-stage-container #t3-form-stage .t3-form-element-toplevel > .t3-form-form-element-selected .btn-toolbar-container { + display: none; +} +.meta-label { + z-index: 1; position: absolute; - right: 0; - top: -35px; + bottom: 1em; + left: 5.5em; display: none; + color: #0078e6; + line-height: 1.6; + font-size: 0.8em; +} +.ui-sortable-handle:hover > .meta-label { + display: inline-block; +} +.ui-sortable-placeholder, +.t3-form-element-composit.ui-sortable-placeholder { + background-color: #fff !important; + border: none !important; + outline: 1px dashed #c4dbab !important; + outline-offset: -2px !important; + visibility: visible !important; +} +.t3-form-icon { + margin-right: 1em; +} +.t3-form-validation-child-has-error { + color: #c83c3c; +} +#t3-form-navigation-component .t3-form-validation-errors, +#t3-form-stage-container .t3-form-validation-errors { + position: relative; + color: #c83c3c; +} +#t3-form-navigation-component .t3-form-validation-errors:before, +#t3-form-stage-container .t3-form-validation-errors:before { z-index: 1; - padding: 4px 3px 12px; - background-image: url("../Images/tooltip.png"); + position: absolute; + display: inline-block; + width: 15px; + height: 15px; + font-family: FontAwesome; + vertical-align: middle; + border-radius: 50%; + font-size: 1em; + line-height: 1.4; + text-align: center; + background: none; +} +#t3-form-navigation-component .t3-form-validation-errors:hover:before, +#t3-form-navigation-component .t3-form-validation-errors.t3-form-form-element-selected:before { + left: 2.4em; +} +#t3-form-navigation-component .t3-form-validation-errors:before { + margin-top: 0.2em; + color: #fff; + font-size: 10px; + font-weight: 800; + content: "\f12a"; + background-color: #c83c3c; } -#fake-form .formwizard-element.hover > div.buttongroup, -#fake-form .formwizard-element.active > div.buttongroup { - display: block; +.t3-form-validation-errors#t3-form-navigation-component-tree-root:before { + left: -2em !important; + margin-top: 0.1em; } -#fake-form .formwizard-element div.buttongroup button { - width: 16px; - height: 16px; - background-color: transparent; - border: 0 solid transparent; +#t3-form-stage-container .t3-form-validation-errors.ui-sortable-handle { + border-color: #c83c3c; } -#fake-form .formwizard-element div.buttongroup span { - margin: 0 3px; +#t3-form-stage-container .t3-form-validation-errors.ui-sortable-handle:before { + left: 4.5em; + margin-top: 1.9em; + content: "\f071"; } -#fake-form .formwizard-element div.buttongroup span.x-btn-over { - background-color: transparent; - background-image: none; +#t3-form-stage-container .t3-form-validation-errors.ui-sortable-handle .element-label { + padding-left: 1.5em; } -#fake-form .formwizard-element button.t3-icon-edit-delete { - background-image: url('../../../../core/Resources/Public/Icons/T3Icons/actions/actions-delete.svg'); +#t3-form-inspector-panels .t3-form-collection-element .t3-form-validation-errors { + display: inline-block; + color: #fff; + font-size: 0.8em; + font-weight: 700; + background-color: #c83c3c; + margin-top: 0.5em; + padding: 0.1em 0.5em; + border-radius: 2px; +} +#t3-form-inspector-panels .t3-form-validation-errors.t3-form-collection-element { + border-color: #c83c3c; +} +#t3-form-inspector-panels .t3-form-validation-errors.t3-form-collection-element h4 { + border-color: #c83c3c; + background-color: #c83c3c; + color: #fff; +} +#t3-form-inspector-panels .t3-form-validation-errors.t3-form-collection-element h4 path { + fill: #fff; +} +#t3-form-inspector-panels .t3-form-validation-errors.t3-form-collection-element .t3-form-collection-element-remove-button { + background: #fff; + border-color: transparent; } -#fake-form .formwizard-element button.t3-icon-document-open { - background-image: url('../../../../core/Resources/Public/Icons/T3Icons/actions/actions-open.svg'); +#t3-form-inspector-panels .t3-form-validation-errors.t3-form-collection-element .t3-form-collection-element-remove-button path { + fill: #c83c3c; } -@media only screen and (max-width: 615px) { - .tab-content fieldset.form-section ol#formwizard-right { - left: 0 !important; - } +.form-editor-loading-spinner { + width: 150px; + margin: 5em auto 0; + text-align: center; +} +.ui-sortable-handle { + cursor: pointer; +} +.module[data-module-name="web_FormFormbuilder_FormEditor"] { + overflow: hidden; +} +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-body, +.module[data-module-name="web_FormFormbuilder_FormEditor"] div[data-identifier="moduleWrapper"] { + height: 100%; +} +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-body { + padding-bottom: 0.5em; +} +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-docheader-bar-column-left button, +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-docheader-bar-column-left button:focus, +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-docheader-bar-column-left button:active { + outline: 0; + outline-color: initial; + outline-style: initial; + outline-width: 0px; +} +.module[data-module-name="web_FormFormbuilder_FormEditor"] .module-docheader-bar-column-left .btn-group { + margin-left: 25px; +} +.t3-form-element-new-page-button { + position: absolute; + left: 0.5em; } diff --git a/typo3/sysext/form/Resources/Public/Images/advanced-password.svg b/typo3/sysext/form/Resources/Public/Images/advanced-password.svg new file mode 100644 index 0000000000000000000000000000000000000000..14626a4e4b8ad0452fcbfee6191f5f6f45a08d97 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/advanced-password.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#676767;" d="M2,5.3h1.6V3.7H2V5.3z M4.5,5.3h1.6V3.7H4.5V5.3z M7,3.7v1.6h1.6V3.7H7z M2,12.3h1.6v-1.6H2V12.3z + M4.5,12.3h1.6v-1.6H4.5V12.3z M7,12.3h1.6v-1.6H7V12.3z"/> +<path style="fill:#9A9999;" d="M0,2v5h16V2H0z M15,6H1V3h14V6z M0,14h16V9H0V14z M1,10h14v3H1V10z"/> +<path style="fill:#FFFFFF;" d="M1,3v3h14V3H1z M3.6,5.3H2V3.7h1.6V5.3z M6.1,5.3H4.5V3.7h1.6V5.3z M8.6,5.3H7V3.7h1.6V5.3z M1,13h14 + v-3H1V13z M7,10.7h1.6v1.6H7V10.7z M4.5,10.7h1.6v1.6H4.5V10.7z M2,10.7h1.6v1.6H2V10.7z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/broom.png b/typo3/sysext/form/Resources/Public/Images/broom.png deleted file mode 100644 index 5aa25bd5380ddc618de9f4e839efb82a81a78f34..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/broom.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/captcha.jpg b/typo3/sysext/form/Resources/Public/Images/captcha.jpg deleted file mode 100644 index 6bf02825b6c29a47659ba88845d1c42b670f572d..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/captcha.jpg and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/checkbox.svg b/typo3/sysext/form/Resources/Public/Images/checkbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..2dcb3d81cf8f95a5eac4c6cb16f0db3fdd1421e2 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/checkbox.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M15,15V1H1v14H15z M4.1,8l2.1,2.1l5.7-5.6l0.7,0.7l-5.7,5.6l-0.7,0.7l-0.7-0.7L3.4,8.7L4.1,8z"/> +<path style="fill:#9A9999;" d="M15,0H1H0v1v14v1h1h14h1v-1V1V0H15z M15,15H1V1h14V15z"/> +<polygon style="fill:#676767;" points="11.9,4.5 6.2,10.1 4.1,8 3.4,8.7 6.2,11.5 6.9,10.8 12.6,5.2 "/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/content-element.svg b/typo3/sysext/form/Resources/Public/Images/content-element.svg new file mode 100644 index 0000000000000000000000000000000000000000..8b61701617cded0874bca33388419ce9f352db19 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/content-element.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M15,15V1H1v14H15z M9,2h5v2H9V2z M9,5h5v1H9V5z M9,7h5v1H9V7z M2,2h6v6H2V2z M2,9h12v1H2V9z M2,11h12 + v1H2V11z M2,13h12v1H2V13z"/> +<path style="fill:#9A9999;" d="M15,0H1H0v1v14v1h1h14h1v-1V1V0H15z M15,15H1V1h14V15z"/> +<path style="fill:#676767;" d="M8,2H2v6h6V2z M9,6h5V5H9V6z M9,8h5V7H9V8z M2,10h12V9H2V10z M2,12h12v-1H2V12z M2,14h12v-1H2V14z + M9,2v2h5V2H9z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/cursor-move.png b/typo3/sysext/form/Resources/Public/Images/cursor-move.png deleted file mode 100644 index de8bca52035bd0d4918c5ff98e68b963c936fe2e..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/cursor-move.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/date-picker.svg b/typo3/sysext/form/Resources/Public/Images/date-picker.svg new file mode 100644 index 0000000000000000000000000000000000000000..c785eb2bc94f2484af59e20d1a5f6baf5d40f688 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/date-picker.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M4.8,8h2.9V5H4.8H4.7v3H4.8z M1,5h3v3H1V5z M4.7,8.5v3h0.1h2.9v-3H4.8H4.7z M1,8.5h3v3H1V8.5z + M4.8,12H4.7v3h0.1h2.9v-3H4.8z M1,12h3v3H1V12z M12,5h3v3h-3V5z M11.2,8h0.1V5h-0.1H8.3v3H11.2z M8.3,8.5v3h2.9h0.1v-3h-0.1H8.3z + M12,8.5h3v3h-3V8.5z M12,12h3v3h-3V12z M11.2,12H8.3v3h2.9h0.1v-3H11.2z M4.8,2V1H3v1v2h1.8V2z M13,2V1h-1.8v1v2H13V2z"/> +<path style="fill:#8C8C8C;" d="M12,5h-0.7v3h-0.1H8.3V5H7.7v3H4.8H4.7V5H4v3H1v0.5h3v3H1V12h3v3h0.7v-3h0.1h2.9v3h0.6v-3h2.9h0.1v3 + H12v-3h3v-0.5h-3v-3h3V8h-3V5z M7.7,11.5H4.8H4.7v-3h0.1h2.9V11.5z M11.3,11.5L11.3,11.5h-3v-3h2.9h0.1 + C11.3,8.5,11.3,11.5,11.3,11.5z"/> +<path style="fill:#676767;" d="M15,2h-1V1V0h-1h-1.8h-1v1v1H5.7V1V0h-1H3H2v1v1H1H0v2v1v6.5V12v3v1h1h3.2h0.5h3h0.5h3h0.5H15h1v-1 + v-3v-0.5v-3V8V5V4V2H15z M11.2,2V1H13v1v2h-1.8V2z M3,2V1h1.8v1v2H3V2z M15,8v0.5v3V12v3h-3h-0.7h-0.1H8.3H7.7H4.8H4.7H4H1v-3v-0.5 + v-3V8V5h3h0.7h0.1h2.9h0.6h2.9h0.1H12h3V8z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/drive-upload.png b/typo3/sysext/form/Resources/Public/Images/drive-upload.png deleted file mode 100644 index f25934d2aa9e9836dff357459ffcb63eef2e07fd..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/drive-upload.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/duplicate.svg b/typo3/sysext/form/Resources/Public/Images/duplicate.svg new file mode 100644 index 0000000000000000000000000000000000000000..c785b6d552c0ebfa42254ac6468f7feea778b0f4 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/duplicate.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path d="M14,4h-2V2V1h-1H2H1v1v9v1h1h2v2v1h1h9h1v-1V5V4H14z M4,4v1v6H2V2h9v2H5H4z M14,14H5V5h9V14z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/edit-heading.png b/typo3/sysext/form/Resources/Public/Images/edit-heading.png deleted file mode 100644 index 0817b4930a2e7d7b0fc97107cc2d0f4a984baf11..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/edit-heading.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/edit-textblock.png b/typo3/sysext/form/Resources/Public/Images/edit-textblock.png deleted file mode 100644 index a27655f38a72eb74a1aa6470700a8a6c0667e407..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/edit-textblock.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/fieldset.svg b/typo3/sysext/form/Resources/Public/Images/fieldset.svg new file mode 100644 index 0000000000000000000000000000000000000000..915bea8c10c25318fde4535b45bc3ea8c9243717 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/fieldset.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#9A9999;" d="M10,0v1h5v14H1V1h1V0H0v16h16V0H10z M2,14h12v-3.5H2V14z M3,11.5h10V13H3V11.5z M14,6.2H2v3.6h12V6.2 + z M13,8.8H3V7.2h10V8.8z M14,2H2v3.5h12V2z M13,4.5H3V3h10V4.5z"/> +<rect x="3" style="fill:#676767;" width="6" height="1"/> +<path style="fill:#FFFFFF;" d="M13,7.2H3v1.6h10V7.2z M13,11.5H3V13h10V11.5z M10,1V0H9v1H3V0H2v1H1v14h14V1H10z M14,14H2v-3.5h12 + V14z M14,9.8H2V6.2h12V9.8z M14,5.5H2V2h12V5.5z M13,3H3v1.5h10V3z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/file-upload.svg b/typo3/sysext/form/Resources/Public/Images/file-upload.svg new file mode 100644 index 0000000000000000000000000000000000000000..ae73a246e294ceb79580f77ba8c192dcf7543c63 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/file-upload.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#9A9999;" d="M2,0v16h12V4l-4-4H2z M3,1h6v4h4v10H3V1z M10,1.4L12.6,4H10V1.4z"/> +<path style="fill:#676767;" d="M8,4L5,8h2v4h2V8h2L8,4z"/> +<path style="fill:#FFFFFF;" d="M10,4V1.4L12.6,4H10z M9,1H3v14h10v-5L9,5V1z M11,8H9v4H7V8H5l3-4L11,8z"/> +<path style="fill:#CBCBCB;" d="M13,5v5L9,5H13z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/finisher.svg b/typo3/sysext/form/Resources/Public/Images/finisher.svg new file mode 100644 index 0000000000000000000000000000000000000000..3d8c355369b31fd0dc2220c6e7bd6ddfc2fd064a --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/finisher.svg @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#676767;" d="M12.9,3.8l-1.4-0.4c0-0.1-0.1-0.2-0.1-0.3l0.7-1.2c0-0.1,0-0.1,0-0.2L11.4,1c-0.1-0.1-0.1-0.1-0.2,0 + L9.9,1.6c-0.1,0-0.2-0.1-0.3-0.1L9.2,0.1C9.2,0,9.1,0,9,0H8C7.9,0,7.8,0,7.8,0.1L7.4,1.5c-0.1,0-0.2,0.1-0.3,0.1L5.9,0.9 + c-0.1,0-0.1,0-0.2,0L4.9,1.7c-0.1,0.1-0.1,0.1,0,0.2l0.7,1.2c0,0.1-0.1,0.2-0.1,0.3L4.1,3.8C4,3.8,4,3.9,4,4v1c0,0.1,0,0.1,0.1,0.2 + l1.4,0.4c0,0.1,0.1,0.2,0.1,0.3L4.9,7.1c0,0.1,0,0.1,0,0.2L5.6,8c0.1,0.1,0.1,0.1,0.2,0L7,7.3c0.1,0,0.2,0.1,0.3,0.1l0.4,1.4 + C7.8,9,7.9,9,8,9h1c0.1,0,0.1,0,0.2-0.1l0.4-1.4c0.1,0,0.2-0.1,0.3-0.1l1.2,0.7c0.1,0,0.1,0,0.2,0L12,7.4c0.1-0.1,0.1-0.1,0-0.2 + L11.3,6c0-0.1,0.1-0.2,0.1-0.3l1.4-0.4C13,5.2,13,5.1,13,5V4C13,3.9,13,3.8,12.9,3.8L12.9,3.8z M8.5,6.4c-1.1,0-1.9-0.9-1.9-1.9 + s0.9-1.9,1.9-1.9c1.1,0,1.9,0.9,1.9,1.9S9.6,6.4,8.5,6.4z M5.9,10.6L5.1,10c0-0.1,0-0.2,0-0.2l0.7-0.6V9.1L5.6,8.5L5.5,8.4L4.6,8.5 + c-0.1,0-0.1-0.1-0.2-0.1l0.1-0.9c0,0,0-0.1-0.1-0.1L3.8,7.1H3.7L3.1,7.9c-0.1,0-0.2,0-0.2,0L2.2,7.1H2.1L1.5,7.4L1.4,7.5l0.1,0.9 + c0,0.1-0.1,0.1-0.1,0.2l-1-0.1c0,0-0.1,0-0.1,0.1L0.1,9.2v0.1l0.8,0.6c0,0.1,0,0.2,0,0.2l-0.7,0.6v0.1l0.3,0.6l0.1,0.1l0.9-0.1 + c0.1,0.1,0.1,0.1,0.2,0.2l-0.1,0.9c0,0,0,0.1,0.1,0.1l0.6,0.3h0.1L3,12.1c0.1,0,0.2,0,0.2,0l0.6,0.7h0.1l0.6-0.3l0.1-0.1l-0.1-0.9 + c0.1-0.1,0.1-0.1,0.2-0.2l0.9,0.1c0,0,0.1,0,0.1-0.1L5.9,10.6C5.9,10.7,5.9,10.7,5.9,10.6L5.9,10.6z M2.5,11.2c-0.7-0.3-1-1-0.7-1.7 + s1-1,1.7-0.7s1,1,0.7,1.7S3.2,11.5,2.5,11.2z"/> +<path style="fill:#79A548;" d="M15.9,12.6l-4.4-3.3v2.2H7.1v2.2h4.4v2.1L15.9,12.6z"/> +<path style="fill:#FFFFFF;" d="M8.5,2.6c-1,0-1.9,0.9-1.9,1.9s0.8,1.9,1.9,1.9s1.9-0.9,1.9-1.9S9.6,2.6,8.5,2.6z M3.5,8.8 + c-0.7-0.3-1.4,0-1.7,0.7s0,1.4,0.7,1.7s1.4,0,1.7-0.7S4.2,9.1,3.5,8.8z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/image-upload.svg b/typo3/sysext/form/Resources/Public/Images/image-upload.svg new file mode 100644 index 0000000000000000000000000000000000000000..0b35d9c06bf8cd92d2af58c53f96e7276a7fddbb --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/image-upload.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M15,13V1H1v12H15z M8,4l3,4H9v4H7V8H5L8,4z"/> +<path style="fill:#9A9999;" d="M1,0H0v1v14v1h1h14h1V0H1z M15,13H1V1h14V13z"/> +<path style="fill:#676767;" d="M8,4L5,8h2v4h2V8h2L8,4z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/insert-after.svg b/typo3/sysext/form/Resources/Public/Images/insert-after.svg new file mode 100644 index 0000000000000000000000000000000000000000..7289fa5687885834ce2668b8c84479d2a89cb60d --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/insert-after.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M3,3h10v2H3V3z"/> +<path style="fill:#FFFFFF;" d="M15,0h-5v1h5v6H1V1h1V0H1H0v1v6v1h1h14h1V7V1V0H15z M13,2H3H2v1v2v1h1h10h1V5V3V2H13z M13,5H3V3h10V5 + z"/> +<path style="fill:#FFFFFF;" d="M3,0h6v1H3V0z M10.5,11.5h-2v-2h-1v2h-2v1h2v2h1v-2h2V11.5z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/insert-in.svg b/typo3/sysext/form/Resources/Public/Images/insert-in.svg new file mode 100644 index 0000000000000000000000000000000000000000..95e00bee41f4fcb71ca1bf19dfbb21e0a9610b50 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/insert-in.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M3,3h10v2H3V3z"/> +<path style="fill:#FFFFFF;" d="M15,0h-5v1h5v14H1V1h1V0H1H0v1v14v1h1h14h1v-1V1V0H15z M13,2H3H2v1v2v1h1h10h1V5V3V2H13z M13,5H3V3 + h10V5z"/> +<path style="fill:#FFFFFF;" d="M3,0h6v1H3V0z M10.5,9.8h-2v-2h-1v2h-2v1h2v2h1v-2h2V9.8z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/mail.png b/typo3/sysext/form/Resources/Public/Images/mail.png deleted file mode 100644 index a5fdc0c2b2f204c3659adb15c00de5c2f70631bf..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/mail.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/module-menu-down.png b/typo3/sysext/form/Resources/Public/Images/module-menu-down.png deleted file mode 100644 index 6829ed2920b732c50567cffe0b5b267ec15af5cd..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/module-menu-down.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/module-menu-right.png b/typo3/sysext/form/Resources/Public/Images/module-menu-right.png deleted file mode 100644 index 7b87ed4cb8c03959295736f6704716eee8dd97a2..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/module-menu-right.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/multi-checkbox.svg b/typo3/sysext/form/Resources/Public/Images/multi-checkbox.svg new file mode 100644 index 0000000000000000000000000000000000000000..b8ff71da1b125b3f785a9b703cc74ffece1b3db4 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/multi-checkbox.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#9A9999;" d="M4.3,16h7.5V8.5H4.3V16z M5.3,9.6h5.4v5.4H5.3V9.6z M4.3,0v7.5h7.5V0H4.3z M10.7,6.4H5.3V1.1h5.4V6.4 + z"/> +<path style="fill:#676767;" d="M7.3,12.9L6.4,12l-0.5,0.5l1.4,1.4l0.5-0.5l2.3-2.3l-0.5-0.5L7.3,12.9z M7.8,4.9l2.3-2.3L9.6,2.1 + L7.3,4.4L6.4,3.5L5.9,4l1.4,1.4L7.8,4.9z"/> +<path style="fill:#FFFFFF;" d="M5.3,14.9h5.4V9.6H5.3V14.9z M6.4,12l0.9,0.9l2.3-2.3l0.5,0.5l-2.3,2.3l-0.5,0.5l-1.4-1.4L6.4,12z + M5.3,1.1v5.4h5.4V1.1H5.3z M7.8,4.9L7.3,5.4L5.9,4l0.5-0.5l0.9,0.9l2.3-2.3l0.5,0.5L7.8,4.9z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/multi-select.svg b/typo3/sysext/form/Resources/Public/Images/multi-select.svg new file mode 100644 index 0000000000000000000000000000000000000000..2621d8de455f2c8ad8fc3dfc698b54c63dd173b0 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/multi-select.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#9A9999;" d="M4.3,16h7.5V8.5H4.3V16z M5.3,9.6h5.4v5.4H5.3V9.6z M4.3,0v7.5h7.5V0H4.3z M10.7,6.4H5.3V1.1h5.4V6.4 + z"/> +<path style="fill:#676767;" d="M8,13.4l-0.9-0.9L6.6,13L8,14.4L9.4,13l-0.5-0.5L8,13.4z M6.6,11.5L7.1,12L8,11.1L8.9,12l0.5-0.5 + L8,10.1L6.6,11.5z M8,4.9L7.1,4L6.6,4.5L8,5.9l1.4-1.4L8.9,4L8,4.9z M8,2.6l0.9,0.9L9.4,3L8,1.6L6.6,3l0.5,0.5L8,2.6z"/> +<g> + <path style="fill:#FFFFFF;" d="M5.3,1.1v5.4h5.4V1.1H5.3z M8,5.9L6.6,4.5L7.1,4L8,4.9L8.9,4l0.5,0.5L8,5.9z M8.9,3.5L8,2.6L7.1,3.5 + L6.6,3L8,1.6L9.4,3L8.9,3.5z"/> + <path style="fill:#FFFFFF;" d="M5.3,14.9h5.4V9.6H5.3V14.9z M8,10.1l1.4,1.4L8.9,12L8,11.1L7.1,12l-0.5-0.5L8,10.1z M7.1,12.5 + L8,13.4l0.9-0.9L9.4,13L8,14.4L6.6,13L7.1,12.5z"/> +</g> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/page.svg b/typo3/sysext/form/Resources/Public/Images/page.svg new file mode 100644 index 0000000000000000000000000000000000000000..26fbff4224810c34441e8634e6a4fb725a95021d --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/page.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#999999;" d="M3,15V1h6v4h4v1.6h1V4l-4-4H2v16h3v-1H3z M10,1.4L12.6,4H10V1.4z"/> +<path style="fill:#CBCBCB;" d="M9.5,5.7l1-0.7H9L9.5,5.7z M10.5,5l2.2,1.6H13V5H10.5z"/> +<path style="fill:#FFE6BB;" d="M5.8,9.5l0.8,0.6V8.7L5.8,9.3V9.5z M9.6,6.6h1.7L10.5,6L9.6,6.6z M14.4,8.9v1.3l0.8-0.6V9.5L14.4,8.9 + z"/> +<path style="fill:#FFFFFF;" d="M9.5,5.7L9,5V1H3v14h2V8.9l1.6-1.1V6.6h1.6L9.5,5.7z M10,1.4V4h2.6L10,1.4z M7.4,7.4v3.3l3.1,2.3 + l3.1-2.2V7.4H7.4z"/> +<polygon style="fill:#666666;" points="6.6,6.6 6.6,10.1 7.4,10.7 7.4,7.4 13.6,7.4 13.6,10.8 14.4,10.2 14.4,6.6 "/> +<path style="fill:#B9B9B9;" d="M9.3,12.1h2.5l1.1-0.8H8.2L9.3,12.1z M8.2,10.5h4.7V9.7H8.2V10.5z M8.2,8.2V9h4.7V8.2H8.2z"/> +<path style="fill:#FFC857;" d="M5.8,10.4v4.8l2.7-2.8L5.8,10.4z M12.5,12.5l2.7,2.8v-4.8L12.5,12.5z M10.5,13.8l-1.3-0.9l-2.3,2.3 + h7.2l-2.3-2.3L10.5,13.8z"/> +<path style="fill:#E8A33D;" d="M10.5,6l0.8,0.6h1.4L10.5,5L8.2,6.6h1.4L10.5,6z M14.4,7.8v1.1l0.8,0.6v0.1L10.5,13L5.8,9.5V9.3 + l0.8-0.6v-1L5,8.9V16h11V8.9L14.4,7.8z M5.8,10.4l2.7,2l-2.7,2.8V10.4z M6.9,15.2l2.3-2.3l1.3,0.9l1.3-0.9l2.3,2.3H6.9z M15.2,15.3 + l-2.7-2.8l2.7-2V15.3z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/password.svg b/typo3/sysext/form/Resources/Public/Images/password.svg new file mode 100644 index 0000000000000000000000000000000000000000..2dc97b8d452a3fa323d4eed7d5905ac940091995 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/password.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<rect x="2" y="7.2" style="fill:#676767;" width="1.6" height="1.6"/> +<rect x="4.5" y="7.2" style="fill:#676767;" width="1.6" height="1.6"/> +<rect x="7" y="7.2" style="fill:#676767;" width="1.6" height="1.6"/> +<path style="fill:#9A9999;" d="M0,5.5L0,5.5v2v3h1h14h1v-3v-2l0,0h-1 M15,9.5H1v-3h14V9.5z"/> +<path style="fill:#FFFFFF;" d="M1,6.5v3h14v-3H1z M3.6,8.8H2V7.2h1.6V8.8z M6.1,8.8H4.5V7.2h1.6V8.8z M8.6,8.8H7V7.2h1.6V8.8z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/radio-button.svg b/typo3/sysext/form/Resources/Public/Images/radio-button.svg new file mode 100644 index 0000000000000000000000000000000000000000..76634c4abfc10dd25267827f279ea89c147ddd79 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/radio-button.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#9A9999;" d="M8,0C3.6,0,0,3.6,0,8s3.6,8,8,8s8-3.6,8-8S12.4,0,8,0z M8,15c-3.9,0-7-3.1-7-7s3.1-7,7-7s7,3.1,7,7 + S11.9,15,8,15z"/> +<path style="fill:#FFFFFF;" d="M8,1C4.1,1,1,4.1,1,8s3.1,7,7,7s7-3.1,7-7S11.9,1,8,1z M8,12c-2.2,0-4-1.8-4-4s1.8-4,4-4s4,1.8,4,4 + S10.2,12,8,12z"/> +<path style="fill:#676767;" d="M8,4c2.2,0,4,1.8,4,4s-1.8,4-4,4s-4-1.8-4-4S5.8,4,8,4z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/remove.gif b/typo3/sysext/form/Resources/Public/Images/remove.gif deleted file mode 100644 index 04999ad062c2e9cd077e8f9b5d4b3453fcb6615a..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/remove.gif and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/single-select.svg b/typo3/sysext/form/Resources/Public/Images/single-select.svg new file mode 100644 index 0000000000000000000000000000000000000000..961bfe934a36292711a15d5153debd940fbb4852 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/single-select.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M1,1v14h14V1H1z M8,12.9L4.5,9.4l0.7-0.7L8,11.5l2.8-2.8l0.7,0.7L8,12.9z M10.8,7.3L8,4.4L5.2,7.3 + L4.5,6.6l2.8-2.9L8,3l0.7,0.7l2.8,2.9L10.8,7.3z"/> +<path style="fill:#9A9999;" d="M15,0H1H0v1v14v1h1h14h1v-1V1V0H15z M15,15H1V1h14V15z"/> +<path style="fill:#676767;" d="M8,4.4l2.8,2.9l0.7-0.7L8.7,3.7L8,3L7.3,3.7L4.5,6.6l0.7,0.7L8,4.4z M8,11.5L5.2,8.7L4.5,9.4L8,12.9 + l3.5-3.5l-0.7-0.7L8,11.5z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/static-text.svg b/typo3/sysext/form/Resources/Public/Images/static-text.svg new file mode 100644 index 0000000000000000000000000000000000000000..13cc3f62aafa606602cc2c779cdcb03aa0959311 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/static-text.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M1,1v14h14V1H1z M14,14H2v-1h12V14z M14,12H2v-1h12V12z M14,10H2V9h12V10z M14,8H2V7h12V8z M14,6H2V5 + h12V6z M14,4H2V2h12V4z"/> +<path style="fill:#9A9999;" d="M15,0H1H0v1v14v1h1h14h1v-1V1V0H15z M15,15H1V1h14V15z"/> +<path style="fill:#676767;" d="M2,2v2h12V2H2z M2,6h12V5H2V6z M2,8h12V7H2V8z M2,10h12V9H2V10z M2,12h12v-1H2V12z M2,14h12v-1H2V14z + "/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/submit-trigger.gif b/typo3/sysext/form/Resources/Public/Images/submit-trigger.gif deleted file mode 100644 index fa0230f86d5a4b76689349300a6883d8619afebf..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/submit-trigger.gif and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/summary-page.svg b/typo3/sysext/form/Resources/Public/Images/summary-page.svg new file mode 100644 index 0000000000000000000000000000000000000000..51ca03e70e7d1c37da6236f36c3829d972157081 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/summary-page.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#79A548;" d="M8.8,6.8L7.6,8L7.1,7.5L6.8,7.8l0.8,0.8l0,0l0.3-0.3l1.2-1.2L8.8,6.8z M8.8,9.2l-1.2,1.3L7.1,10 + l-0.3,0.3l0.8,0.8l0,0l0.3-0.3l1.2-1.2L8.8,9.2z M8.8,11.8L7.6,13l-0.5-0.5l-0.3,0.3l0.8,0.8l0,0l0.3-0.3l1.2-1.2L8.8,11.8z"/> +<path style="fill:#FFFFFF;" d="M3,1v14h2V5h4V1H3z M10,4V1.4L12.6,4H10z M6,15h9V6H6V15z M9.2,7.4h5v1.2h-5V7.4z M9.2,9.9h5v1.2h-5 + V9.9z M9.2,12.4h5v1.2h-5V12.4z M7.1,7.5L7.6,8l1.2-1.2l0.3,0.3L7.9,8.3L7.6,8.6L6.8,7.8L7.1,7.5z M7.1,10l0.5,0.5l1.2-1.3l0.3,0.4 + l-1.2,1.2l-0.3,0.3l-0.8-0.8L7.1,10z M7.1,12.5L7.6,13l1.2-1.2l0.3,0.3l-1.2,1.2l-0.3,0.3l-0.8-0.8L7.1,12.5z"/> +<path style="fill:#676767;" d="M9.2,7.4h5v1.2h-5V7.4z M9.2,9.9h5v1.2h-5V9.9z M9.2,12.4h5v1.2h-5V12.4z M15,6v9H6V6H15 M16,5H5v11 + h11V5z"/> +<path style="fill:#999999;" d="M3,15V1h6v4h4h1V4l-4-4H2v16h3v-1H3z M10,1.4L12.6,4H10V1.4z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/text.svg b/typo3/sysext/form/Resources/Public/Images/text.svg new file mode 100644 index 0000000000000000000000000000000000000000..db92ec02974d967f251d18762d80619e111c9fb7 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/text.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M1,9.5h3v-3H1V9.5z M5,6.5v3h10v-3H5z"/> +<path style="fill:#9A9999;" d="M0,10.5h4v-1H1v-3h3v-1H0V10.5z M5,5.5v1h10v3H5v1h11v-5H5z"/> +<polygon style="fill:#676767;" points="6.5,4.5 6.5,3.5 5,3.5 4,3.5 2.5,3.5 2.5,4.5 4,4.5 4,11.5 2.5,11.5 2.5,12.5 4,12.5 5,12.5 + 6.5,12.5 6.5,11.5 5,11.5 5,4.5 "/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/textarea.svg b/typo3/sysext/form/Resources/Public/Images/textarea.svg new file mode 100644 index 0000000000000000000000000000000000000000..4efeb102c7f17c54f1b338546a97b7f9f55454d6 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/textarea.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#FFFFFF;" d="M1,1v14h14V1H1z M10,13H2v-1h8V13z M14,11H2v-1h12V11z M14,9H2V8h12V9z M14,7H2V6h12V7z M14,5H2V4h12 + V5z M14,3H2V2h12V3z"/> +<path style="fill:#9A9999;" d="M15,0H1H0v1v14v1h1h14h1v-1V1V0H15z M15,15H1V1h14V15z"/> +<path style="fill:#676767;" d="M2,2v1h12V2H2z M2,5h12V4H2V5z M2,7h12V6H2V7z M2,9h12V8H2V9z M2,11h12v-1H2V11z M2,13h8v-1H2V13z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/Images/tooltip.png b/typo3/sysext/form/Resources/Public/Images/tooltip.png deleted file mode 100644 index 2dcfe228d861ba9ff9b5df20a85f9c59d0ce1c1e..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/tooltip.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-button-default.png b/typo3/sysext/form/Resources/Public/Images/ui-button-default.png deleted file mode 100644 index 0c78dc6ae4fcb2d51a59243eecc9e1bf8892a055..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-button-default.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-button.png b/typo3/sysext/form/Resources/Public/Images/ui-button.png deleted file mode 100644 index d13064cc74d7d1ceb080435719f78c55c40aa876..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-button.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-check-box.png b/typo3/sysext/form/Resources/Public/Images/ui-check-box.png deleted file mode 100644 index 45a96e975fd5b5270ae80f94b13670217eb88742..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-check-box.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-check-boxes.png b/typo3/sysext/form/Resources/Public/Images/ui-check-boxes.png deleted file mode 100644 index 7ed6644b6af67d114574a195802fe7f05a1392da..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-check-boxes.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-combo-box.png b/typo3/sysext/form/Resources/Public/Images/ui-combo-box.png deleted file mode 100644 index f4c3e2e1c4b30d3cc136d60d778eada7249381ed..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-combo-box.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-group-box.png b/typo3/sysext/form/Resources/Public/Images/ui-group-box.png deleted file mode 100644 index 3f9e7eb1aacb916344a3d552c42d878ffde9001a..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-group-box.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-labels.png b/typo3/sysext/form/Resources/Public/Images/ui-labels.png deleted file mode 100644 index f4b0c418d07125d0d10c74ed1d5f64a753914531..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-labels.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-radio-button.png b/typo3/sysext/form/Resources/Public/Images/ui-radio-button.png deleted file mode 100644 index cbdb9223daeca3226b7aad1f835d34e280363726..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-radio-button.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-radio-buttons.png b/typo3/sysext/form/Resources/Public/Images/ui-radio-buttons.png deleted file mode 100644 index 4face34b24a76003aab6cf739e1d9c5c36514d08..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-radio-buttons.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-scroll-pane-text.png b/typo3/sysext/form/Resources/Public/Images/ui-scroll-pane-text.png deleted file mode 100644 index 85400c6120782dce91b6b472146bd451ddc8f188..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-scroll-pane-text.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-text-field-hidden.png b/typo3/sysext/form/Resources/Public/Images/ui-text-field-hidden.png deleted file mode 100644 index 715e18d06c97240bd13dd813246348f8e66f5eaa..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-text-field-hidden.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-text-field-password.png b/typo3/sysext/form/Resources/Public/Images/ui-text-field-password.png deleted file mode 100644 index fd0fa5a65549a2d27d28d7c372ae87224fc5422b..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-text-field-password.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/ui-text-field.png b/typo3/sysext/form/Resources/Public/Images/ui-text-field.png deleted file mode 100644 index bd818025869b33833d0178331322f1c19263d422..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/ui-text-field.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/user-silhouette.png b/typo3/sysext/form/Resources/Public/Images/user-silhouette.png deleted file mode 100644 index 6205ff18ad0d23bf2c0a310c28473c22881a190e..0000000000000000000000000000000000000000 Binary files a/typo3/sysext/form/Resources/Public/Images/user-silhouette.png and /dev/null differ diff --git a/typo3/sysext/form/Resources/Public/Images/validator.svg b/typo3/sysext/form/Resources/Public/Images/validator.svg new file mode 100644 index 0000000000000000000000000000000000000000..5b1ed6a243b6dbb24df68cd3b56102bb57cf7674 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/Images/validator.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve"> +<path style="fill:#0078e6;" d="M14,0H2H1v1v7c0,4.5,6.5,7.7,6.8,7.8L8,15.9l0.2-0.1C8.5,15.7,15,12.4,15,8V1V0H14z M8,14.8 + C6.9,14.2,2,11.5,2,8V1h12v7C14,11.4,9.1,14.2,8,14.8z"/> +<path style="fill:#FFFFFF;" d="M14,8V1H8v13.8C9.1,14.2,14,11.4,14,8z"/> +<path style="fill:#0078e6;" d="M2,1v7c0,3.5,4.9,6.2,6,6.8V1H2z"/> +</svg> diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js new file mode 100644 index 0000000000000000000000000000000000000000..adecd027bd496d27c12949dddd37cd4160894463 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js @@ -0,0 +1,1114 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Core', + ], function($, core) { + 'use strict'; + + /** + * Return a static method named "getInstance". + * Use this method to create the formeditor app. + */ + return (function(_core) { + + /** + * @private + * + * Hold the instance (Singleton Pattern) + */ + var _formEditorInstance = null; + + /** + * @public + * + * @param object _configuration + * @param object _mediator + * @param object _viewModel + * @return object + */ + function FormEditor(_configuration, _mediator, _viewModel) { + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @private + * + * @var bool + */ + var _unsavedContent = false; + + /** + * @private + * + * @var bool + */ + var _previewMode = false; + + /** + * @public + * + * @return object + */ + function getPublisherSubscriber() { + return _core.getPublisherSubscriber(); + }; + + /** + * @public + * + * @return void + */ + function _saveApplicationState() { + + _getApplicationStateStack().addAndReset({ + formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(), + currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'), + currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath') + }); + }; + + /** + * @public + * + * @return void + */ + function undoApplicationState() { + _getApplicationStateStack().incrementCurrentStackPointer(); + }; + + /** + * @public + * + * @return void + */ + function redoApplicationState() { + _getApplicationStateStack().decrementCurrentStackPointer(); + }; + + /** + * @public + * + * @return int + */ + function getMaximalApplicationStates() { + return _getApplicationStateStack().getMaximalStackSize(); + }; + + /** + * @public + * + * @return int + */ + function getCurrentApplicationStates() { + return _getApplicationStateStack().getCurrentStackSize(); + }; + + /** + * @public + * + * @return int + */ + function getCurrentApplicationStatePosition() { + return _getApplicationStateStack().getCurrentStackPointer(); + }; + + /** + * @public + * + * @param string type + * @return object + * @throws 1475378543 + */ + function getRunningAjaxRequest(type) { + assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543); + return _core.getRunningAjaxRequest(type); + }; + + /** + * @public + * + * @return object + */ + function getUtility() { + return _core.getUtility(); + }; + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + getUtility().assert(test, message, messageCode); + }; + + /** + * @public + * + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param boolean allowEmptyReturnValue + * @return string + */ + function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @param function func + * @return void + */ + function addPropertyValidationValidator(validatorIdentifier, func) { + _getPropertyValidationService().addValidator(validatorIdentifier, func); + }; + + /** + * @public + * + * @param string propertyPath + * @return object + */ + function validateCurrentlySelectedFormElementProperty(propertyPath) { + return validateFormElementProperty( + getCurrentlySelectedFormElement(), + propertyPath + ); + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @return object + */ + function validateFormElementProperty(formElement, propertyPath) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath); + }; + + /** + * @public + * + * @param object formElement + * @return object + */ + function validateFormElement(formElement) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElement(formElement); + }; + + /** + * @public + * + * @param object validationResults + * @return boolean + */ + function validationResultsHasErrors(validationResults) { + return _getPropertyValidationService().validationResultsHasErrors(validationResults); + }; + + /** + * @public + * + * @param object formElement + * @param boolean returnAfterFirstMatch + * @return object + */ + function validateFormElementRecursive(formElement, returnAfterFirstMatch) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch); + }; + + /** + * @public + * + * @param bool unsavedContent + * @return void + * @throws 1475378544 + */ + function setUnsavedContent(unsavedContent) { + assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544); + _unsavedContent = unsavedContent; + }; + + /** + * @public + * + * @return boolean + */ + function getUnsavedContent() { + return _unsavedContent; + }; + + /** + * @public + * + * @return object + */ + function getRootFormElement() { + return _getRepository().getRootFormElement(); + }; + + /** + * @public + * + * @return string + */ + function getCurrentlySelectedFormElement() { + return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')); + }; + + /** + * @public + * + * @param string|object formElement + * @param boolean doNotRefreshCurrentlySelectedPageIndex + * @return void + * @publish core/currentlySelectedFormElementChanged + */ + function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) { + doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex; + + formElement = _getRepository().findFormElement(formElement); + _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath')); + + if (!doNotRefreshCurrentlySelectedPageIndex) { + refreshCurrentlySelectedPageIndex(); + } + getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]); + }; + + /** + * @public + * + * @param string identifierPath + * @return object + * @throws 1475378545 + */ + function getFormElementByIdentifierPath(identifierPath) { + assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545); + return _getRepository().findFormElementByIdentifierPath(identifierPath); + }; + + /** + * @public + * + * @param string identifierPath + * @return bool + */ + function isFormElementIdentifierUsed(formElementIdentifier) { + return _getRepository().isFormElementIdentifierUsed(formElementIdentifier); + } + + /** + * @public + * + * @param string formElementType + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + */ + function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { + var formElement; + formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet); + formElement.set('renderables', formElement.get('renderables')); + return formElement; + }; + + /** + * @public + * + * @param object formElement + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475434337 + */ + function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) { + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(referenceFormElement)) { + referenceFormElement = getCurrentlySelectedFormElement(); + } + referenceFormElement = _getRepository().findFormElement(referenceFormElement); + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337); + return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string formElementType + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475434336 + * @throws 1475435857 + */ + function createFormElement(formElementType, disablePublishersOnSet) { + var formElementDefinition, identifier; + assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336); + + identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType); + formElementDefinition = getFormElementDefinitionByType(formElementType); + return _getFactory().createFormElement({ + type: formElementType, + identifier: identifier, + label: formElementDefinition['label'] || formElementType + }, undefined, undefined, undefined, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string|object formElementToRemove + * @param boolean disablePublishersOnSet + * @return object + */ + function removeFormElement(formElementToRemove, disablePublishersOnSet) { + var parentFormElement; + _saveApplicationState(); + + formElementToRemove = _getRepository().findFormElement(formElementToRemove); + parentFormElement = formElementToRemove.get('__parentRenderable'); + _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet); + return parentFormElement; + }; + + /** + * @public + * + * @param string|object formElementToMove + * @param string position + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return string + * @throws 1475378551 + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + _saveApplicationState(); + + formElementToMove = _getRepository().findFormElement(formElementToMove); + referenceFormElement = _getRepository().findFormElement(referenceFormElement); + + assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551); + + formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true); + disablePublishersOnSet = !!disablePublishersOnSet; + if (!disablePublishersOnSet) { + formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables')); + } + return formElementToMove; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @return object (dereferenced) + * @throws 1475378555 + * @throws 1475378556 + * @throws 1475446108 + */ + function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) { + var collection, collectionElement, formElementDefinition; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556); + + formElementDefinition = getFormElementDefinitionByType(formElement.get('type')); + collection = formElementDefinition['propertyCollections'][collectionName]; + assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108); + collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection); + + return $.extend(true, {}, collectionElement); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @return int + * @throws 1475378557 + * @throws 1475378558 + */ + function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) { + var indexFromPropertyCollectionElement; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558); + + indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier( + collectionElementIdentifier, + collectionName, + formElement + ); + + return indexFromPropertyCollectionElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param object collectionElementConfiguration + * @param string referenceCollectionElementIdentifier + * @return object + */ + function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) { + return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier); + }; + + /** + * @public + * + * @param object collectionElement + * @param string collectionName + * @param string|object formElement + * @param string referenceCollectionElementIdentifier + * @return object + * @throws 1475443300 + * @throws 1475443301 + */ + function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) { + var collection; + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300); + + if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { + collection = formElement.get(collectionName); + if ('array' === $.type(collection) && collection.length > 0) { + referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier']; + } + } + + return _getRepository().addPropertyCollectionElement( + collectionElement, + collectionName, + formElement, + referenceCollectionElementIdentifier, + false + ); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object collectionElementConfiguration + * @return void + * @throws 1475378559 + * @throws 1475378560 + */ + function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) { + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560); + if ('object' !== $.type(collectionElementConfiguration)) { + collectionElementConfiguration = {}; + } + + return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @param bool disablePublishersOnSet + * @return void + * @throws 1475378561 + * @throws 1475378562 + */ + function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562); + + _getRepository().removePropertyCollectionElementByIdentifier( + formElement, + collectionElementIdentifier, + collectionName, + true + ); + + disablePublishersOnSet = !!disablePublishersOnSet; + if (!disablePublishersOnSet) { + getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']); + } + }; + + /** + * @public + * + * @param string collectionElementToMove + * @param string position + * @param string referenceCollectionElement + * @param string collectionName + * @param object formElement + * @param boolean disablePublishersOnSet + * @return string + * @throws 1477404352 + * @throws 1477404353 + * @throws 1477404354 + * @throws 1477404355 + */ + function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { + _saveApplicationState(); + + formElement = _getRepository().findFormElement(formElement); + + assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352); + assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353); + assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355); + + return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string elementType + * @param string formElementDefinitionKey + * @returnmixed + * @throws 1475378563 + */ + function getFormElementDefinitionByType(elementType, formElementDefinitionKey) { + var formElementDefinition; + assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563); + + formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType); + + if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) { + formElementDefinition = formElementDefinition[formElementDefinitionKey]; + } + + if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) { + return $.extend(true, {}, formElementDefinition); + } else { + return formElementDefinition; + } + }; + + /** + * @public + * + * @param object formElement + * @param string formElementDefinitionKey + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + formElement = _getRepository().findFormElement(formElement); + return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey); + }; + + /** + * @public + * + * @param string collectionName + * @param string collectionElementIdentifier + * @return mixed + */ + function getFormEditorDefinition(definitionName, subject) { + return _getRepository().getFormEditorDefinition(definitionName, subject); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @return object (dereferenced) + * @throws 1475672362 + */ + function getFormElementPropertyValidatorDefinition(validatorIdentifier) { + var validatorDefinition; + assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362); + + validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier); + return $.extend(true, {}, validatorDefinition); + }; + + /** + * @public + * + * @return int + */ + function getCurrentlySelectedPageIndex() { + return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'); + }; + + /** + * @public + * + * @return void + */ + function refreshCurrentlySelectedPageIndex() { + _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement())); + }; + + /** + * @public + * + * @return object + * @throws 1477786068 + */ + function getCurrentlySelectedPage() { + var currentPage; + + currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()]; + assert('object' === $.type(currentPage), 'No page found', 1477786068); + return currentPage; + }; + + /** + * @public + * + * @return object + */ + function getLastTopLevelElementOnCurrentPage() { + var lastRenderable, renderables; + + renderables = getCurrentlySelectedPage().get('renderables'); + if (getUtility().isUndefinedOrNull(renderables)) { + return undefined; + } + lastRenderable = renderables[renderables.length - 1]; + return lastRenderable; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getLastFormElementWithinParentFormElement(formElement) { + var lastElement; + + formElement = _getRepository().findFormElement(formElement); + if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { + return formElement; + } + return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1]; + }; + + /** + * @public + * + * @param object + * @return int + */ + function getPageIndexFromFormElement(formElement) { + formElement = _getRepository().findFormElement(formElement); + + return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement( + formElement + ); + }; + + /** + * @public + * + * @return void + */ + function renderCurrentFormPage() { + renderFormPage(getCurrentlySelectedPageIndex()); + }; + + /** + * @public + * + * @param int pageIndex + * @return void + * @throws 1475446442 + */ + function renderFormPage(pageIndex) { + assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442); + _getDataBackend().renderFormDefinitionPage(pageIndex); + }; + + /** + * @public + * + * @param object formElement + * @return object|null + */ + function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { + return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel( + _getRepository().findFormElement(formElement) + ); + }; + + /** + * @public + * + * @return boolean + */ + function isRootFormElementSelected() { + return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath')); + }; + + /** + * @public + * + * @return object + */ + function getViewModel() { + return _viewModel; + }; + + /** + * @public + * + * @return void + */ + function saveFormDefinition() { + _getDataBackend().saveFormDefinition(); + }; + + /** + * @private + * + * @return object + */ + function _getDataBackend() { + return _core.getDataBackend(); + }; + + /** + * @private + * + * @return object + */ + function _getFactory() { + return _core.getFactory(); + }; + + /** + * @private + * + * @return object + */ + function _getRepository() { + return _core.getRepository(); + }; + + /** + * @private + * + * @return object + */ + function _getPropertyValidationService() { + return _core.getPropertyValidationService(); + }; + + /** + * @public + * + * @return object + */ + function _getApplicationStateStack() { + return _core.getApplicationStateStack(); + }; + + /** + * @private + * + * @return void + * @publish ajax/beforeSend + * @publish ajax/complete + */ + function _ajaxSetup() { + $.ajaxSetup({ + beforeSend: function() { + getPublisherSubscriber().publish('ajax/beforeSend'); + }, + complete: function() { + getPublisherSubscriber().publish('ajax/complete'); + } + }); + }; + + /** + * @private + * + * @param object endpoints + * @param string prototypeName + * @param string formPersistenceIdentifier + * @return void + * @throws 1475379748 + * @throws 1475379749 + * @throws 1475927876 + */ + function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) { + assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748); + assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876); + assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749); + + _core.getDataBackend().setEndpoints(endpoints); + _core.getDataBackend().setPrototypeName(prototypeName); + _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier); + }; + + /** + * @private + * + * @param object formEditorDefinitions + * @return void + * @throws 1475379750 + */ + function _repositorySetup(formEditorDefinitions) { + assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750); + + _getRepository().setFormEditorDefinitions(formEditorDefinitions); + } + + /** + * @private + * + * @param object additionalViewModelModules + * @return void + * @throws 1475379752 + * @throws 1475492374 + */ + function _viewSetup(additionalViewModelModules) { + assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374); + + if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) { + assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752); + } else { + additionalViewModelModules = []; + } + _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules); + }; + + /** + * @private + * + * @return void + * @throws 1475492032 + */ + function _mediatorSetup() { + assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032); + _mediator.bootstrap(_formEditorInstance, _viewModel); + }; + + /** + * @private + * + * @param object rootFormElement + * @param int maximumUndoSteps + * @return void + * @throws 1475379751 + */ + function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) { + assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751); + + if ('number' !== $.type(maximumUndoSteps)) { + maximumUndoSteps = 10; + } + _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps); + + _getApplicationStateStack().addAndReset({ + currentlySelectedPageIndex: 0, + currentlySelectedFormElementIdentifierPath: rootFormElement['identifier'] + }, true); + + _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true)); + }; + + /** + * @private + * + * @return void + */ + function _bootstrap() { + _configuration = _configuration || {}; + + _mediatorSetup(); + _ajaxSetup(); + _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']); + _repositorySetup(_configuration['formEditorDefinitions']); + _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']); + setCurrentlySelectedFormElement(_getRepository().getRootFormElement()); + + _viewSetup(_configuration['additionalViewModelModules']); + }; + + /** + * @public + * + * @return TYPO3/CMS/Form/Backend/FormEditor + * @throws 1473200696 + */ + function run() { + if (_isRunning) { + throw 'You can not run the app twice (1473200696)'; + } + + _bootstrap(); + _isRunning = true; + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getRootFormElement: getRootFormElement, + + createAndAddFormElement: createAndAddFormElement, + createFormElement: createFormElement, + addFormElement: addFormElement, + moveFormElement: moveFormElement, + removeFormElement: removeFormElement, + + getCurrentlySelectedFormElement: getCurrentlySelectedFormElement, + setCurrentlySelectedFormElement: setCurrentlySelectedFormElement, + + getFormElementByIdentifierPath: getFormElementByIdentifierPath, + isFormElementIdentifierUsed: isFormElementIdentifierUsed, + + createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, + createPropertyCollectionElement: createPropertyCollectionElement, + addPropertyCollectionElement: addPropertyCollectionElement, + removePropertyCollectionElement: removePropertyCollectionElement, + movePropertyCollectionElement: movePropertyCollectionElement, + getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement, + getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration, + + saveFormDefinition: saveFormDefinition, + renderCurrentFormPage: renderCurrentFormPage, + renderFormPage: renderFormPage, + + getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex, + refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex, + getPageIndexFromFormElement: getPageIndexFromFormElement, + getCurrentlySelectedPage: getCurrentlySelectedPage, + getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage, + findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, + isRootFormElementSelected: isRootFormElementSelected, + getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement, + + getFormElementDefinitionByType: getFormElementDefinitionByType, + getFormElementDefinition: getFormElementDefinition, + getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition, + getFormEditorDefinition: getFormEditorDefinition, + + getPublisherSubscriber: getPublisherSubscriber, + getRunningAjaxRequest: getRunningAjaxRequest, + + setUnsavedContent: setUnsavedContent, + getUnsavedContent: getUnsavedContent, + + addPropertyValidationValidator: addPropertyValidationValidator, + validateFormElementProperty: validateFormElementProperty, + validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty, + validateFormElement: validateFormElement, + validateFormElementRecursive: validateFormElementRecursive, + validationResultsHasErrors: validationResultsHasErrors, + + getUtility: getUtility, + assert: assert, + buildPropertyPath: buildPropertyPath, + + getViewModel: getViewModel, + undoApplicationState: undoApplicationState, + redoApplicationState: redoApplicationState, + getMaximalApplicationStates: getMaximalApplicationStates, + getCurrentApplicationStates: getCurrentApplicationStates, + getCurrentApplicationStatePosition: getCurrentApplicationStatePosition, + + run: run + }; + }; + + /** + * Emulation of static methods + */ + return { + /** + * @public + * @static + * + * Implement the "Singleton Pattern". + * + * Return a singleton instance of a + * "FormEditor" object. + * + * @param object configuration + * @param object mediator + * @param object viewModel + * @return object + */ + getInstance: function(configuration, mediator, viewModel) { + if(_formEditorInstance === null) { + _formEditorInstance = new FormEditor(configuration, mediator, viewModel); + } + return _formEditorInstance; + } + }; + })(core); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js new file mode 100644 index 0000000000000000000000000000000000000000..0fd0b84ba7f22cd5298033fb2ec6537906db4a39 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js @@ -0,0 +1,2127 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/Core + */ +define(['jquery'], function($) { + 'use strict'; + + return (function($) { + + /** + * @private + * + * @var object + */ + var _dataBackendEndpoints = {}; + + /** + * @private + * + * @var string + */ + var _dataBackendPrototypeName = null; + + /** + * @private + * + * @var string + */ + var _dataBackendPersistenceIdentifier = null; + + /** + * @private + * + * @var object + */ + var _publisherSubscriberTopics = {}; + + /** + * @private + * + * @var int + */ + var _publisherSubscriberUid = -1; + + /** + * @private + * + * @var object + */ + var _repositoryFormEditorDefinitions = {}; + + /** + * @private + * + * @var object + */ + var _runningAjaxRequests = []; + + /** + * @private + * + * @var object + */ + var _propertyValidationServiceValidators = {}; + + /** + * @private + * + * @var int + */ + var _applicationStateStackSize = 10; + + /** + * @private + * + * @var int + */ + var _applicationStateStackPointer = 0; + + /** + * @private + * + * @var object + */ + var _applicationStateStack = []; + + /** + * @public + * + * @return object + */ + function utility() { + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + if ('function' === $.type(test)) { + test = (test() !== false); + } + if (!test) { + message = message || "Assertion failed"; + if (messageCode) { + message = message + ' (' + messageCode + ')'; + } + if ('undefined' !== typeof Error) { + throw new Error(message); + } + throw message; + } + }; + + /** + * @public + * + * @param mixed value + * @return bool + */ + function isUndefinedOrNull(value) { + return ('undefined' === $.type(value) || 'null' === $.type(value)); + }; + + /** + * @public + * + * @param mixed value + * @return bool + */ + function isNonEmptyString(value) { + return ('string' === $.type(value) && value.length > 0); + }; + + /** + * @public + * + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param boolean allowEmptyReturnValue + * @return string + * @throws 1475412569 + * @throws 1475412570 + * @throws 1475415988 + * @throws 1475663210 + */ + function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { + var newPropertyPath = ''; + + allowEmptyReturnValue = !!allowEmptyReturnValue; + if (isNonEmptyString(collectionElementIdentifier) || isNonEmptyString(collectionName)) { + assert(isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475412569); + assert(isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475412570); + newPropertyPath = collectionName + '.' + repository().getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); + } else { + newPropertyPath = ''; + } + + if (!isUndefinedOrNull(propertyPath)) { + assert(isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475415988); + if (isNonEmptyString(newPropertyPath)) { + newPropertyPath = newPropertyPath + '.' + propertyPath; + } else { + newPropertyPath = propertyPath; + } + } + + if (!allowEmptyReturnValue) { + assert(isNonEmptyString(newPropertyPath), 'The property path could not be resolved', 1475663210); + } + return newPropertyPath; + }; + + /** + * @public + * + * @param object formElement + * @return object + * @throws 1475377782 + */ + function convertToSimpleObject(formElement) { + var childFormElements, simpleObject, objectData; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475377782); + + simpleObject = {}; + objectData = ('function' === $.type(formElement.getObjectData)) ? formElement.getObjectData() : formElement; + childFormElements = objectData['renderables']; + delete objectData['renderables']; + + for (var key in objectData) { + if (!objectData.hasOwnProperty(key)) { + continue; + } + var value = objectData[key]; + if (key.match(/^__/)) { + continue; + } + + if ('object' === $.type(value)) { + simpleObject[key] = convertToSimpleObject(value); + } else if ('function' !== $.type(value) && 'undefined' !== $.type(value)) { + simpleObject[key] = value; + } + } + + if ('array' === $.type(childFormElements)) { + simpleObject['renderables'] = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + simpleObject['renderables'].push(convertToSimpleObject(childFormElements[i])); + } + } + + return simpleObject; + }; + + /** + * Publish the public methods. + */ + return { + assert: assert, + convertToSimpleObject: convertToSimpleObject, + isNonEmptyString: isNonEmptyString, + isUndefinedOrNull: isUndefinedOrNull, + buildPropertyPath: buildPropertyPath + }; + }; + + /** + * @public + * + * @return object + */ + function propertyValidationService() { + + /** + * @public + * + * @param object formElement + * @param object validators + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object configuration + * @return void + * @throws 1475661025 + * @throws 1475661026 + * @throws 1479238074 + */ + function addValidatorIdentifiersToFormElementProperty(formElement, validators, propertyPath, collectionElementIdentifier, collectionName, configuration) { + var formElementIdentifierPath, propertyPath, propertyValidationServiceRegisteredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475661025); + utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1475661026); + utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1479238074); + + formElementIdentifierPath = formElement.get('__identifierPath'); + propertyPath = utility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement); + + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = {}; + } + if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath] = { + validators: [], + configuration: configuration + }; + } + for (var i = 0, len = validators.length; i < len; ++i) { + if (propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].indexOf(validators[i]) === -1) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].push(validators[i]); + } + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @return void + * @throws 1475700618 + * @throws 1475706896 + */ + function removeValidatorIdentifiersFromFormElementProperty(formElement, propertyPath) { + var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, registeredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475700618); + utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475706896); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + registeredValidators = {}; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { + if ( + !propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath) + || registeredPropertyPath.indexOf(propertyPath) > -1 + ) { + continue; + } + registeredValidators[registeredPropertyPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][registeredPropertyPath]; + } + propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = registeredValidators; + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + }; + + /** + * @public + * + * @param string|object formElement + * @return void + * @throws 1475668189 + */ + function removeAllValidatorIdentifiersFromFormElement(formElement) { + var propertyValidationServiceRegisteredValidators, registeredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475668189); + + registeredValidators = {}; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + for (var formElementIdentifierPath in propertyValidationServiceRegisteredValidators) { + if ( + !propertyValidationServiceRegisteredValidators.hasOwnProperty(formElementIdentifierPath) + || formElementIdentifierPath === formElement.get('__identifierPath') + || formElementIdentifierPath.indexOf(formElement.get('__identifierPath') + '/') > -1 + ) { + continue; + } + registeredValidators[formElementIdentifierPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath]; + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', registeredValidators); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @param function func + * @return void + * @throws 1475669143 + * @throws 1475669144 + * @throws 1475669145 + */ + function addValidator(validatorIdentifier, func) { + utility().assert(utility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475669143); + utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475669144); + utility().assert('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier]), 'The validator "' + validatorIdentifier + '" is already registered', 1475669145); + + _propertyValidationServiceValidators[validatorIdentifier] = func; + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @param string errorMessage + * @return object + * @throws 1475676517 + * @throws 1475676518 + */ + function validateFormElementProperty(formElement, propertyPath) { + var configuration, formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475676517); + utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475676518); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + validationResults = []; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + configuration = { + propertyValidatorsMode: 'AND' + }; + + if ( + !utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) + && 'object' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]) + && 'array' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators']) + ) { + configuration = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['configuration']; + for (var i = 0, len = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length; i < len; ++i) { + var validatorIdentifier, validationResult; + + validatorIdentifier = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'][i]; + if ('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier])) { + continue; + } + validationResult = _propertyValidationServiceValidators[validatorIdentifier](formElement, propertyPath); + + if (utility().isNonEmptyString(validationResult)) { + validationResults.push(validationResult); + } + } + } + + if ( + validationResults.length > 0 + && configuration['propertyValidatorsMode'] === 'OR' + && validationResults.length !== propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length + ) { + return []; + } + + return validationResults; + }; + + /** + * @public + * + * @param object formElement + * @return object + * @throws 1475749668 + */ + function validateFormElement(formElement) { + var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475749668); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + validationResults = []; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { + for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { + var validationResult; + if (!propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)) { + continue; + } + validationResult = { + propertyPath: registeredPropertyPath, + validationResults: validateFormElementProperty(formElement, registeredPropertyPath) + }; + validationResults.push(validationResult); + } + } + return validationResults; + }; + + /** + * @public + * + * @param array validationResults + * @return bool + * @throws 1478613477 + */ + function validationResultsHasErrors(validationResults) { + utility().assert('array' === $.type(validationResults), 'Invalid parameter "validationResults"', 1478613477); + + for (var i = 0, len = validationResults.length; i < len; ++i) { + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + return true; + } + } + } + return false; + }; + + /** + * @public + * + * @param object formElement + * @param boolean returnAfterFirstMatch + * @param object validationResults + * @return object + * @throws 1475749668 + */ + function validateFormElementRecursive(formElement, returnAfterFirstMatch, validationResults) { + var formElements, validationResult, validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475756764); + returnAfterFirstMatch = !!returnAfterFirstMatch; + + validationResults = validationResults || []; + validationResult = { + formElementIdentifierPath: formElement.get('__identifierPath'), + validationResults: validateFormElement(formElement) + }; + validationResults.push(validationResult); + + if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { + return validationResults; + } + + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + validateFormElementRecursive(formElements[i], returnAfterFirstMatch, validationResults); + if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { + return validationResults; + } + } + } + + return validationResults; + } + + /** + * @public + * + * @param object formElement + * @return void + * @throws 1475707334 + */ + function addValidatorIdentifiersFromFormElementPropertyCollections(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475707334); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + + if (!utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'])) { + for (var collectionName in formElementTypeDefinition['propertyCollections']) { + if ( + !formElementTypeDefinition['propertyCollections'].hasOwnProperty(collectionName) + || 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName]) + ) { + continue; + } + for (var i = 0, len1 = formElementTypeDefinition['propertyCollections'][collectionName].length; i < len1; ++i) { + if ( + 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors']) + || repository().getIndexFromPropertyCollectionElementByIdentifier(formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], collectionName, formElement) === -1 + ) { + continue; + } + for (var j = 0, len2 = formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'].length; j < len2; ++j) { + var configuration = {}; + + if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) { + continue; + } + + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode']) + && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'], + formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyPath'], + formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], + collectionName, + configuration + ); + } + } + } + } + }; + + /** + * Publish the public methods. + */ + return { + addValidatorIdentifiersToFormElementProperty: addValidatorIdentifiersToFormElementProperty, + removeValidatorIdentifiersFromFormElementProperty: removeValidatorIdentifiersFromFormElementProperty, + removeAllValidatorIdentifiersFromFormElement: removeAllValidatorIdentifiersFromFormElement, + validateFormElementProperty: validateFormElementProperty, + validateFormElement: validateFormElement, + validateFormElementRecursive: validateFormElementRecursive, + validationResultsHasErrors: validationResultsHasErrors, + addValidator: addValidator, + addValidatorIdentifiersFromFormElementPropertyCollections: addValidatorIdentifiersFromFormElementPropertyCollections + }; + }; + + /** + * @public + * + * @param string ajaxRequestIdentifier + * @return object|null + * @throws 1475358064 + */ + function getRunningAjaxRequest(ajaxRequestIdentifier) { + utility().assert(utility().isNonEmptyString(ajaxRequestIdentifier), 'Invalid parameter "ajaxRequestIdentifier"', 1475358064); + return _runningAjaxRequests[ajaxRequestIdentifier] || null; + }; + + /** + * @public + * + * Implements the "Publish/Subscribe Pattern" + * + * @return object + * @credits Addy Osmani https://addyosmani.com/resources/essentialjsdesignpatterns/book/#highlighter_634280 + */ + function publisherSubscriber() { + + /** + * @public + * + * @param string topic + * @param mixed args + * @return void + * @throws 1475358066 + */ + function publish(topic, args) { + utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358066); + if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { + return; + } + + for (var i = 0, len = _publisherSubscriberTopics[topic].length; i < len; ++i) { + _publisherSubscriberTopics[topic][i].func(topic, args); + } + }; + + /** + * @public + * + * @param string topic + * @param function func + * @return string + * @throws 1475358067 + */ + function subscribe(topic, func) { + utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358067); + utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475411986); + + if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { + _publisherSubscriberTopics[topic] = []; + } + + var token = (++_publisherSubscriberUid).toString(); + _publisherSubscriberTopics[topic].push({ + token: token, + func: func + }); + return token; + }; + + /** + * @public + * + * @param string token + * @return null|string + * @throws 1475358068 + */ + function unsubscribe(token) { + utility().assert(utility().isNonEmptyString(token), 'Invalid parameter "token"', 1475358068); + + for (var key in _publisherSubscriberTopics) { + if (!_publisherSubscriberTopics.hasOwnProperty(key)) { + continue; + } + for (var i = 0, len = _publisherSubscriberTopics[key].length; i < len; ++i) { + if (_publisherSubscriberTopics[key][i].token === token) { + _publisherSubscriberTopics[key].splice(i, 1); + return token; + } + } + } + return null; + }; + + /** + * Publish the public methods. + */ + return { + publish: publish, + subscribe: subscribe, + unsubscribe: unsubscribe + }; + }; + + /** + * @private + * + * @param object modelToExtend + * @param object modelExtension + * @param string pathPrefix + * @return void + * @throws 1474640022 + * @throws 1475358069 + * @throws 1475358070 + * @publish core/formElement/somePropertyChanged + */ + function extendModel(modelToExtend, modelExtension, pathPrefix, disablePublishersOnSet) { + utility().assert('object' === $.type(modelToExtend), 'Invalid parameter "modelToExtend"', 1475358069); + utility().assert('object' === $.type(modelExtension) || 'array' === $.type(modelExtension), 'Invalid parameter "modelExtension"', 1475358070); + + disablePublishersOnSet = !!disablePublishersOnSet; + pathPrefix = pathPrefix || ''; + + if ($.isEmptyObject(modelExtension)) { + utility().assert('' !== pathPrefix, 'Empty path is not allowed', 1474640022); + modelToExtend.on(pathPrefix, 'core/formElement/somePropertyChanged'); + modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet); + } else { + for (var key in modelExtension) { + if (!modelExtension.hasOwnProperty(key)) { + continue; + } + var path = (pathPrefix === '') ? key : pathPrefix + '.' + key; + + modelToExtend.on(path, 'core/formElement/somePropertyChanged'); + + if ('object' === $.type(modelExtension[key]) || 'array' === $.type(modelExtension[key])) { + extendModel(modelToExtend, modelExtension[key], path, disablePublishersOnSet); + } else { + modelToExtend.set(path, modelExtension[key], disablePublishersOnSet); + } + } + } + }; + + /** + * @private + * + * @param object modelExtension + * @return object + */ + function createModel(modelExtension) { + var newModel; + + modelExtension = modelExtension || {}; + + function M() { + + /** + * @private + */ + var _objectData = {}; + + /** + * @private + */ + var _publisherTopics = {}; + + /** + * @public + * + * @param string key + * @return mixed|undefined + * @throws 1475361755 + */ + function get(key) { + var firstPartOfPath, obj; + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361755); + + obj = _objectData; + while (key.indexOf('.') > 0) { + firstPartOfPath = key.slice(0, key.indexOf('.')); + key = key.slice(firstPartOfPath.length + 1); + if (!obj.hasOwnProperty(firstPartOfPath)) { + return undefined; + } + obj = obj[firstPartOfPath]; + } + + return obj[key]; + }; + + /** + * @public + * + * @param string key + * @param mixed value + * @param bool disablePublishersOnSet + * @return void + * @throws 1475361756 + * @publish mixed + */ + function set(key, value, disablePublishersOnSet) { + var obj, oldValue, path; + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361756); + disablePublishersOnSet = !!disablePublishersOnSet; + + oldValue = get(key); + obj = _objectData; + path = key; + + while (path.indexOf('.') > 0) { + var firstPartOfPath, nextPartOfPath; + + firstPartOfPath = path.slice(0, path.indexOf('.')); + path = path.slice(firstPartOfPath.length + 1); + if ($.isNumeric(firstPartOfPath)) { + firstPartOfPath = parseInt(firstPartOfPath); + } + if ('undefined' === $.type(obj[firstPartOfPath])) { + nextPartOfPath = path.slice(0, path.indexOf('.')); + if ($.isNumeric(nextPartOfPath)) { + obj[firstPartOfPath] = []; + } else { + obj[firstPartOfPath] = {}; + } + } + obj = obj[firstPartOfPath]; + } + obj[path] = value; + + if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) { + for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) { + publisherSubscriber().publish(_publisherTopics[key][i], [key, value, oldValue, _objectData['__identifierPath']]); + } + } + }; + + /** + * @public + * + * @param string key + * @param string topicName + * @return void + * @throws 1475361757 + * @throws 1475361758 + */ + function on(key, topicName) { + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361757); + utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361758); + + if ('array' !== $.type(_publisherTopics[key])) { + _publisherTopics[key] = []; + } + if (_publisherTopics[key].indexOf(topicName) === -1) { + _publisherTopics[key].push(topicName); + } + }; + + /** + * @public + * + * @param string key + * @param string topicName + * @return void + * @throws 1475361759 + * @throws 1475361760 + */ + function off(key, topicName) { + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361759); + utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361760); + + if ('array' === $.type(_publisherTopics[key])) { + _publisherTopics[key] = _publisherTopics[key].filter(function (topicName) { + return topicName !== topicName; + }); + } + }; + + /** + * @public + * + * @return object (dereferenced) + */ + function getObjectData() { + return $.extend(true, {}, _objectData); + }; + + /** + * @public + * + * @return string + */ + function toString() { + var childFormElements, objectData; + + objectData = getObjectData(); + childFormElements = objectData['renderables'] || null; + delete objectData['renderables']; + + if (!utility().isUndefinedOrNull(objectData['__parentRenderable'])) { + objectData['__parentRenderable'] = objectData['__parentRenderable'].getObjectData()['__identifierPath'] + ' (filtered)'; + } + + if (null !== childFormElements) { + objectData['renderables'] = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + var childFormElement = childFormElements[i]; + objectData['renderables'].push(JSON.parse(childFormElement.toString())); + } + } + + return JSON.stringify(objectData, null, 2); + }; + + /** + * @public + * + * @return object + */ + function clone() { + var childFormElements, newModel, newRenderables, objectData; + + objectData = getObjectData(); + childFormElements = objectData['renderables'] || null; + delete objectData['renderables']; + delete objectData['__parentRenderable']; + objectData['renderables'] = (childFormElements) ? true : null, + + newModel = new M(); + extendModel(newModel, objectData, '', true); + + if (null !== childFormElements) { + newRenderables = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + var childFormElement = childFormElements[i]; + + childFormElement = childFormElement.clone(); + childFormElement.set('__parentRenderable', newModel, true); + newRenderables.push(childFormElement); + } + newModel.set('renderables', newRenderables, true); + } + + return newModel; + }; + + /** + * Publish the public methods. + */ + return { + get: get, + set: set, + + on: on, + off: off, + + getObjectData: getObjectData, + toString: toString, + clone: clone + }; + }; + + newModel = new M(); + extendModel(newModel, modelExtension, '', true); + + return newModel; + }; + + /** + * @public + * + * @return object + */ + function repository() { + + /** + * @public + * + * @param object typeDefinitions + * @return void + * @throws 1475364394 + */ + function setFormEditorDefinitions(formEditorDefinitions) { + utility().assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475364394); + + for (var key1 in formEditorDefinitions) { + if (!formEditorDefinitions.hasOwnProperty(key1) || 'object' !== $.type(formEditorDefinitions[key1])) { + continue; + } + for (var key2 in formEditorDefinitions[key1]) { + if (!formEditorDefinitions[key1].hasOwnProperty(key2)) { + continue; + } + if ('object' !== $.type(formEditorDefinitions[key1][key2])) { + formEditorDefinitions[key1][key2] = {}; + } + } + } + _repositoryFormEditorDefinitions = formEditorDefinitions; + }; + + /** + * @public + * + * @param string typeName + * @param string subject + * @return object (dereferenced) + * @throws 1475364952 + * @throws 1475364953 + */ + function getFormEditorDefinition(definitionName, subject) { + utility().assert(utility().isNonEmptyString(definitionName), 'Invalid parameter "definitionName"', 1475364952); + utility().assert(utility().isNonEmptyString(subject), 'Invalid parameter "subject"', 1475364953); + return $.extend(true, {}, _repositoryFormEditorDefinitions[definitionName][subject]); + }; + + /** + * @public + * + * @return object + */ + function getRootFormElement() { + return getApplicationStateStack().getCurrentState('formDefinition'); + }; + + /** + * @public + * + * @param object formElement + * @param object referenceFormElement + * @param boolean registerPropertyValidators + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475436224 + * @throws 1475364956 + */ + function addFormElement(formElement, referenceFormElement, registerPropertyValidators, disablePublishersOnSet) { + var enclosingCompositeFormElement, identifier, formElementTypeDefinition, parentFormElementsArray, referenceFormElementElements, referenceFormElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475436224); + utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364956); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + registerPropertyValidators = !!registerPropertyValidators; + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); + + if (!formElementTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isCompositeFormElement']) { + if ('array' !== $.type(referenceFormElement.get('renderables'))) { + referenceFormElement.set('renderables', [], disablePublishersOnSet); + } + + formElement.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); + formElement.set('__identifierPath', referenceFormElement.get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); + referenceFormElement.get('renderables').push(formElement); + } else { + if (referenceFormElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { + referenceFormElementElements = referenceFormElement.get('renderables'); + referenceFormElement = referenceFormElementElements[referenceFormElementElements.length - 1]; + } else if (formElementTypeDefinition['_isTopLevelFormElement'] && !referenceFormElementTypeDefinition['_isTopLevelFormElement']) { + referenceFormElement = findEnclosingCompositeFormElementWhichIsOnTopLevel(referenceFormElement); + } else if (formElementTypeDefinition['_isCompositeFormElement']) { + enclosingCompositeFormElement = findEnclosingCompositeFormElementWhichIsNotOnTopLevel(referenceFormElement); + if (enclosingCompositeFormElement) { + referenceFormElement = enclosingCompositeFormElement; + } + } + + formElement.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); + formElement.set('__identifierPath', referenceFormElement.get('__parentRenderable').get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); + parentFormElementsArray = referenceFormElement.get('__parentRenderable').get('renderables'); + parentFormElementsArray.splice(parentFormElementsArray.indexOf(referenceFormElement) + 1, 0, formElement); + } + + if (registerPropertyValidators) { + if ('array' === $.type(formElementTypeDefinition['editors'])) { + for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { + var configuration = {}; + + if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { + continue; + } + + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) + && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + + propertyValidationService().addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['editors'][i]['propertyValidators'], + formElementTypeDefinition['editors'][i]['propertyPath'], + undefined, + undefined, + configuration + ); + } + } + } + + return formElement; + }; + + /** + * @param object formElement + * @param boolean removeRegisteredPropertyValidators + * @param boolean disablePublishersOnSet + * @return void + * @throws 1472553024 + * @throws 1475364957 + */ + function removeFormElement(formElement, removeRegisteredPropertyValidators, disablePublishersOnSet) { + var parentFormElementElements; + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + removeRegisteredPropertyValidators = !!removeRegisteredPropertyValidators; + + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364957); + utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'Removing the root element is not allowed', 1472553024); + + parentFormElementElements = formElement.get('__parentRenderable').get('renderables'); + parentFormElementElements.splice(parentFormElementElements.indexOf(formElement), 1); + formElement.get('__parentRenderable').set('renderables', parentFormElementElements, disablePublishersOnSet); + + if (removeRegisteredPropertyValidators) { + propertyValidationService().removeAllValidatorIdentifiersFromFormElement(formElement); + } + }; + + /** + * @param object formElementToMove + * @param string position + * @param object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475364958 + * @throws 1475364959 + * @throws 1475364960 + * @throws 1475364961 + * @throws 1475364962 + * @throws 1476993731 + * @throws 1476993732 + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + var formElementToMoveTypeDefinition, referenceFormElementParentElements, referenceFormElementElements, referenceFormElementIndex, referenceFormElementTypeDefinition, reSetIdentifierPath; + utility().assert('object' === $.type(formElementToMove), 'Invalid parameter "formElementToMove"', 1475364958); + utility().assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475364959); + utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364960); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + formElementToMoveTypeDefinition = repository().getFormEditorDefinition('formElements', formElementToMove.get('type')); + referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); + + removeFormElement(formElementToMove, false); + reSetIdentifierPath = function(formElement, pathPrefix) { + var formElements, newIdentifierPath, oldIdentifierPath, propertyValidationServiceRegisteredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961); + utility().assert(utility().isNonEmptyString(pathPrefix), 'Invalid parameter "pathPrefix"', 1475364962); + + oldIdentifierPath = formElement.get('__identifierPath'); + newIdentifierPath = pathPrefix + '/' + formElement.get('identifier'); + + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[oldIdentifierPath])) { + propertyValidationServiceRegisteredValidators[newIdentifierPath] = propertyValidationServiceRegisteredValidators[oldIdentifierPath]; + delete propertyValidationServiceRegisteredValidators[oldIdentifierPath]; + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + + formElement.set('__identifierPath', newIdentifierPath, disablePublishersOnSet); + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + reSetIdentifierPath(formElements[i], formElement.get('__identifierPath')); + } + } + }; + + /** + * This is true on: + * * Drag a Element on a Page Element (tree) + * * Drag a Element on a Section Element (tree) + */ + if (position === 'inside') { + utility().assert(!formElementToMoveTypeDefinition['_isTopLevelFormElement'], 'This move is not allowed', 1476993731); + utility().assert(referenceFormElementTypeDefinition['_isCompositeFormElement'], 'This move is not allowed', 1476993732); + + formElementToMove.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); + reSetIdentifierPath(formElementToMove, referenceFormElement.get('__identifierPath')); + + referenceFormElementElements = referenceFormElement.get('renderables'); + if (utility().isUndefinedOrNull(referenceFormElementElements)) { + referenceFormElementElements = []; + } + referenceFormElementElements.splice(0, 0, formElementToMove); + referenceFormElement.set('renderables', referenceFormElementElements, disablePublishersOnSet); + } else { + /** + * This is true on: + * * Drag a Page before another Page (tree) + * * Drag a Page after another Page (tree) + */ + if (formElementToMoveTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isTopLevelFormElement']) { + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + + if (position === 'after') { + referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); + } else { + referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); + } + + referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); + } else { + /** + * This is true on: + * * Drag a Element before another Element within the same level (tree) + * * Drag a Element after another Element within the same level (tree) + * * Drag a Element before another Element (stage) + * * Drag a Element after another Element (stage) + */ + if (formElementToMove.get('__parentRenderable').get('identifier') === referenceFormElement.get('__parentRenderable').get('identifier')) { + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + } else { + /** + * This is true on: + * * Drag a Element before an Element on another page (tree) + * * Drag a Element after an Element on another page (tree) + */ + formElementToMove.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); + reSetIdentifierPath(formElementToMove, referenceFormElement.get('__parentRenderable').get('__identifierPath')); + + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + } + + if (position === 'after') { + referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); + } else { + referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); + } + + referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); + } + } + + return formElementToMove; + }; + + /** + * @param object formElement + * @return int + * @throws 1475364963 + */ + function getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(formElement) { + var enclosingCompositeFormElementWhichIsOnTopLevel, formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364963); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + + if (formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { + enclosingCompositeFormElementWhichIsOnTopLevel = formElement; + } else if (formElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { + enclosingCompositeFormElementWhichIsOnTopLevel = getApplicationStateStack().getCurrentState('formDefinition').get('renderables')[0]; + } else { + enclosingCompositeFormElementWhichIsOnTopLevel = findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement); + } + return enclosingCompositeFormElementWhichIsOnTopLevel.get('__parentRenderable').get('renderables').indexOf(enclosingCompositeFormElementWhichIsOnTopLevel); + }; + + /** + * @param object formElement + * @return object + * @throws 1472556223 + * @throws 1475364964 + */ + function findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364964); + utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'The root element is never encloused by anything', 1472556223); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isTopLevelFormElement']) { + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + + return formElement; + }; + + /** + * @param object formElement + * @return object|null + * @throws 1475364965 + */ + function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364965); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isCompositeFormElement']) { + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + return formElement; + }; + + /** + * @param string identifier + * @returl bool + * @throws 1475364966 + */ + function isFormElementIdentifierUsed(identifier) { + var checkIdentifier, identifierFound; + utility().assert(utility().isNonEmptyString(identifier), 'Invalid parameter "identifier"', 1475364966); + + checkIdentifier = function(formElement) { + var formElements; + + if (formElement.get('identifier') === identifier) { + identifierFound = true; + } + + if (!identifierFound) { + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + checkIdentifier(formElements[i]); + if (identifierFound) { + break; + } + } + } + } + } + + checkIdentifier(getApplicationStateStack().getCurrentState('formDefinition')); + return identifierFound; + }; + + /** + * @param string formElementType + * @return string + * @throws 1475373676 + */ + function getNextFreeFormElementIdentifier(formElementType) { + var i, prefix; + utility().assert(utility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475373676); + + prefix = formElementType.toLowerCase().replace(/[^a-z0-9]/g, '-') + '-'; + i = 1; + while (isFormElementIdentifierUsed(prefix + i)) { + i++; + } + return prefix + i; + }; + + /** + * @param string identifierPath + * @return object + * @throws 1472424333 + * @throws 1472424334 + * @throws 1472424330 + * @throws 1475373677 + */ + function findFormElementByIdentifierPath(identifierPath) { + var obj, pathParts, pathPartsLength, formElement, formElements; + + utility().assert(utility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475373677); + + formElement = getApplicationStateStack().getCurrentState('formDefinition'); + pathParts = identifierPath.split('/'); + pathPartsLength = pathParts.length; + + for (var i = 0; i < pathPartsLength; ++i) { + var key = pathParts[i]; + if (i === 0 || i === pathPartsLength) { + utility().assert(key === formElement.get('identifier'), '"' + key + '" does not exist in path "' + identifierPath + '"', 1472424333); + continue; + } + + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + obj = null; + for (var j = 0, len = formElements.length; j < len; ++j) { + if (key === formElements[j].get('identifier')) { + obj = formElements[j]; + break; + } + } + + utility().assert('null' !== $.type(obj), 'Could not find form element "' + key + '" in path "' + identifierPath + '"', 1472424334); + formElement = obj; + } else { + utility().assert(false, 'No form elements found', 1472424330); + } + } + return formElement; + }; + + /** + * @param string|object formElement + * @return object + */ + function findFormElement(formElement) { + if ('object' === $.type(formElement)) { + formElement = formElement.get('__identifierPath'); + } + return findFormElementByIdentifierPath(formElement); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param object collection + * @return undefined|object + * @throws 1475375281 + * @throws 1475375282 + */ + function findCollectionElementByIdentifierPath(collectionElementIdentifier, collection) { + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375281); + utility().assert('array' === $.type(collection), 'Invalid parameter "collection"', 1475375282); + + for (var i = 0, len = collection.length; i < len; ++i) { + if (collection[i]['identifier'] === collectionElementIdentifier) { + return collection[i]; + } + } + + return undefined; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return int + * @throws 1475375283 + * @throws 1475375284 + * @throws 1475375285 + */ + function getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement) { + var collection; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375283); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375284); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375285); + + collection = formElement.get(collectionName); + if ('array' === $.type(collection)) { + for (var i = 0, len = collection.length; i < len; ++i) { + if (collection[i]['identifier'] === collectionElementIdentifier) { + return i; + } + } + } + return -1; + }; + + /** + * @public + * + * @param object collectionElementToAdd + * @param string collectionName + * @param object formElement + * @param string referenceCollectionElementIdentifier + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475375686 + * @throws 1475375687 + * @throws 1475375688 + * @throws 1477413154 + */ + function addPropertyCollectionElement(collectionElementToAdd, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) { + var collection, formElementTypeDefinition, newCollection, newCollectionElementIndex; + utility().assert('object' === $.type(collectionElementToAdd), 'Invalid parameter "collectionElementToAdd"', 1475375686); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375687); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375688); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + collection = formElement.get(collectionName); + if ('array' !== $.type(collection)) { + extendModel(formElement, [], collectionName, true); + collection = formElement.get(collectionName); + } + + if (utility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { + newCollectionElementIndex = 0; + } else { + newCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement) + 1; + utility().assert(-1 < newCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477413154); + } + + collection.splice(newCollectionElementIndex, 0, collectionElementToAdd); + formElement.set(collectionName, collection, true); + + propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); + + for (var i = 0, len = collection.length; i < len; ++i) { + extendModel(formElement, collection[i], collectionName + '.' + i, true); + } + + formElement.set(collectionName, collection, true); + propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); + formElement.set(collectionName, collection, disablePublishersOnSet); + + return formElement; + }; + + /** + * @public + * + * @param object formElement + * @param string collectionElementIdentifier + * @param string collectionName + * @param boolean disablePublishersOnSet + * @return void + * @throws 1475375689 + * @throws 1475375690 + * @throws 1475375691 + * @throws 1475375692 + */ + function removePropertyCollectionElementByIdentifier(formElement, collectionElementIdentifier, collectionName, disablePublishersOnSet) { + var collection, collectionElementIndex; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375689); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375690); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375691); + + collection = formElement.get(collectionName); + utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1475375692); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); + collectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); + collection.splice(collectionElementIndex, 1); + formElement.set(collectionName, collection, disablePublishersOnSet); + propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); + }; + + /** + * @param string collectionElementToMoveIdentifier + * @param string position + * @param string referenceCollectionElementIdentifier + * @param string position + * @param object formElement + * @param boolean disablePublishersOnSet + * @return void + * @throws 1477404484 + * @throws 1477404485 + * @throws 1477404486 + * @throws 1477404488 + * @throws 1477404489 + * @throws 1477404490 + */ + function movePropertyCollectionElement(collectionElementToMoveIdentifier, position, referenceCollectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + var collection, collectionElementToMove, referenceCollectionElement, referenceCollectionElementIndex; + + utility().assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404485); + utility().assert('string' === $.type(referenceCollectionElementIdentifier), 'Invalid parameter "referenceCollectionElementIdentifier"', 1477404486); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1477404488); + + collection = formElement.get(collectionName); + utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1477404490); + + collectionElementToMove = findCollectionElementByIdentifierPath(collectionElementToMoveIdentifier, collection); + utility().assert('object' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404484); + + removePropertyCollectionElementByIdentifier(formElement, collectionElementToMoveIdentifier, collectionName); + + referenceCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement); + utility().assert(-1 < referenceCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477404489); + + if ('before' === position) { + referenceCollectionElement = collection[referenceCollectionElementIndex - 1]; + if (utility().isUndefinedOrNull(referenceCollectionElement)) { + referenceCollectionElementIdentifier = undefined; + } else { + referenceCollectionElementIdentifier = referenceCollectionElement['identifier']; + } + } + + addPropertyCollectionElement(collectionElementToMove, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) + }; + + /** + * Publish the public methods. + */ + return { + getRootFormElement: getRootFormElement, + + getFormEditorDefinition: getFormEditorDefinition, + setFormEditorDefinitions: setFormEditorDefinitions, + + findFormElement: findFormElement, + findFormElementByIdentifierPath: findFormElementByIdentifierPath, + findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, + findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel, + getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement, + + getNextFreeFormElementIdentifier: getNextFreeFormElementIdentifier, + isFormElementIdentifierUsed: isFormElementIdentifierUsed, + + addFormElement: addFormElement, + moveFormElement: moveFormElement, + removeFormElement: removeFormElement, + + findCollectionElementByIdentifierPath: findCollectionElementByIdentifierPath, + getIndexFromPropertyCollectionElementByIdentifier: getIndexFromPropertyCollectionElementByIdentifier, + addPropertyCollectionElement: addPropertyCollectionElement, + removePropertyCollectionElementByIdentifier: removePropertyCollectionElementByIdentifier, + movePropertyCollectionElement: movePropertyCollectionElement + }; + }; + + /** + * @public + * + * @return object + */ + function factory() { + + /** + * @public + * + * @param object configuration + * @param string identifierPathPrefix + * @param object parentFormElement + * @param boolean registerPropertyValidators + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475375693 + * @throws 1475436040 + * @throws 1475604050 + */ + function createFormElement(configuration, identifierPathPrefix, parentFormElement, registerPropertyValidators, disablePublishersOnSet) { + var currentChildFormElements, collections, formElementTypeDefinition, identifierPath, rawChildFormElements, formElement; + utility().assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1475375693); + utility().assert(utility().isNonEmptyString(configuration['identifier']), '"identifier" must not be empty', 1475436040); + utility().assert(utility().isNonEmptyString(configuration['type']), '"type" must not be empty', 1475604050); + + registerPropertyValidators = !!registerPropertyValidators; + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', configuration['type']); + rawChildFormElements = configuration['renderables']; + delete configuration['renderables']; + + collections = {}; + for (var collectionName in configuration) { + if (!configuration.hasOwnProperty(collectionName)) { + continue; + } + if (utility().isUndefinedOrNull(_repositoryFormEditorDefinitions[collectionName])) { + continue; + } + collections[collectionName] = configuration[collectionName]; + delete configuration[collectionName]; + } + + identifierPathPrefix = identifierPathPrefix || ''; + identifierPath = (identifierPathPrefix === '') ? configuration['identifier'] : identifierPathPrefix + '/' + configuration['identifier']; + + configuration = $.extend( + formElementTypeDefinition['predefinedDefaults'] || {}, + configuration, + { + renderables: (rawChildFormElements) ? true : null, + __parentRenderable: null, + __identifierPath: identifierPath + } + ); + + formElement = createModel(configuration); + formElement.set('__parentRenderable', parentFormElement || null, disablePublishersOnSet); + + for (var collectionName in collections) { + if (!collections.hasOwnProperty(collectionName)) { + continue; + } + + for (var i in collections[collectionName]) { + var previousCreatePropertyCollectionElementIdentifier, propertyCollectionElement; + if (!collections[collectionName].hasOwnProperty(i)) { + continue; + } + propertyCollectionElement = createPropertyCollectionElement( + collections[collectionName][i]['identifier'], + collections[collectionName][i], + collectionName + ); + if (i > 0) { + previousCreatePropertyCollectionElementIdentifier = collections[collectionName][i - 1]['identifier'] + } + repository().addPropertyCollectionElement(propertyCollectionElement, collectionName, formElement, previousCreatePropertyCollectionElementIdentifier, true); + } + } + + if (registerPropertyValidators) { + if ('array' === $.type(formElementTypeDefinition['editors'])) { + for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { + var configuration = {}; + + if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { + continue; + } + + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) + && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + + propertyValidationService().addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['editors'][i]['propertyValidators'], + formElementTypeDefinition['editors'][i]['propertyPath'], + undefined, + undefined, + configuration + ); + } + } + } + + if ('array' === $.type(rawChildFormElements)) { + currentChildFormElements = []; + for (var i = 0, len = rawChildFormElements.length; i < len; ++i) { + currentChildFormElements.push(createFormElement(rawChildFormElements[i], identifierPath, formElement, registerPropertyValidators, disablePublishersOnSet)); + } + formElement.set('renderables', currentChildFormElements, disablePublishersOnSet); + } + return formElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param object collectionElementConfiguration + * @param string collectionName + * @return object + * @throws 1475377160 + * @throws 1475377161 + * @throws 1475377162 + */ + function createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName) { + var collectionDefinition, collectionElementPresets; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475377160); + utility().assert('object' === $.type(collectionElementConfiguration), 'Invalid parameter "collectionElementConfiguration"', 1475377161); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475377162); + + collectionElementConfiguration['identifier'] = collectionElementIdentifier; + collectionDefinition = repository().getFormEditorDefinition(collectionName, collectionElementIdentifier); + if (collectionDefinition['predefinedDefaults']) { + collectionElementPresets = collectionDefinition['predefinedDefaults']; + } else { + collectionElementPresets = {}; + } + + return $.extend(collectionElementPresets, collectionElementConfiguration); + }; + + /** + * Publish the public methods. + */ + return { + createFormElement: createFormElement, + createPropertyCollectionElement: createPropertyCollectionElement + }; + }; + + /** + * @public + * + * @return object + */ + function dataBackend() { + + /** + * @public + * + * @param object endpoints + * @return void + * @throws 1475377488 + */ + function setEndpoints(endpoints) { + utility().assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475377488); + _dataBackendEndpoints = endpoints; + }; + + /** + * @public + * + * @param string prototypeName + * @return void + * @throws 1475377489 + */ + function setPrototypeName(prototypeName) { + utility().assert(utility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475928095); + _dataBackendPrototypeName = prototypeName; + }; + + /** + * @public + * + * @param string persistenceIdentifier + * @return void + * @throws 1475377489 + */ + function setPersistenceIdentifier(persistenceIdentifier) { + utility().assert(utility().isNonEmptyString(persistenceIdentifier), 'Invalid parameter "persistenceIdentifier"', 1475377489); + _dataBackendPersistenceIdentifier = persistenceIdentifier; + }; + + /** + * @public + * + * @return void + * @publish core/ajax/saveFormDefinition/success + * @publish core/ajax/error + * @throws 1475520918 + */ + function saveFormDefinition() { + utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['saveForm']), 'The endpoint "saveForm" is not configured', 1475520918); + + if (_runningAjaxRequests['saveForm']) { + _runningAjaxRequests['saveForm'].abort(); + } + + _runningAjaxRequests['saveForm'] = $.post(_dataBackendEndpoints['saveForm'], { + tx_form_web_formformbuilder: { + formPersistenceIdentifier: _dataBackendPersistenceIdentifier, + formDefinition: utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition')) + } + }, function(data, textStatus, jqXHR) { + if (_runningAjaxRequests['saveForm'] !== jqXHR) { + return; + } + _runningAjaxRequests['saveForm'] = null; + publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]); + }).fail(function(jqXHR, textStatus, errorThrown) { + publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); + }); + }; + + /** + * @public + * + * @param int pageIndex + * @return void + * @publish core/ajax/renderFormDefinitionPage/success + * @publish core/ajax/error + * @throws 1473447677 + * @throws 1475377781 + * @throws 1475377782 + */ + function renderFormDefinitionPage(pageIndex) { + utility().assert($.isNumeric(pageIndex), 'Invalid parameter "pageIndex"', 1475377781); + utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['formPageRenderer']), 'The endpoint "formPageRenderer" is not configured', 1473447677); + + if (_runningAjaxRequests['renderFormDefinitionPage']) { + _runningAjaxRequests['renderFormDefinitionPage'].abort(); + } + + _runningAjaxRequests['renderFormDefinitionPage'] = $.post(_dataBackendEndpoints['formPageRenderer'], { + tx_form_web_formformbuilder: { + formDefinition: utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition')), + pageIndex: pageIndex, + prototypeName: _dataBackendPrototypeName + } + }, function(data, textStatus, jqXHR) { + if (_runningAjaxRequests['renderFormDefinitionPage'] !== jqXHR) { + return; + } + _runningAjaxRequests['renderFormDefinitionPage'] = null; + publisherSubscriber().publish('core/ajax/renderFormDefinitionPage/success', [data, pageIndex]); + }).fail(function(jqXHR, textStatus, errorThrown) { + publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); + }); + }; + + /** + * Publish the public methods. + */ + return { + renderFormDefinitionPage: renderFormDefinitionPage, + saveFormDefinition: saveFormDefinition, + setEndpoints: setEndpoints, + setPersistenceIdentifier: setPersistenceIdentifier, + setPrototypeName: setPrototypeName + }; + }; + + /** + * @public + * + * @return object + */ + function getApplicationStateStack() { + + /** + * @public + * + * @param object applicationState + * @param bool disablePublishersOnSet + * @return void + * @publish core/applicationState/add + * @throws 1477847415 + */ + function add(applicationState, disablePublishersOnSet) { + utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477847415); + disablePublishersOnSet = !!disablePublishersOnSet; + + $.extend(applicationState, { + propertyValidationServiceRegisteredValidators: $.extend(true, {}, getCurrentState('propertyValidationServiceRegisteredValidators')) + }); + + _applicationStateStack.splice(0, 0, applicationState); + if (_applicationStateStack.length > _applicationStateStackSize) { + _applicationStateStack.splice(_applicationStateStackSize - 1, (_applicationStateStack.length - _applicationStateStackSize)); + } + + if (!disablePublishersOnSet) { + publisherSubscriber().publish('core/applicationState/add', [applicationState, getCurrentStackPointer(), getCurrentStackSize()]); + } + }; + + /** + * @public + * + * @param applicationState + * @param bool disablePublishersOnSet + * @return void + * @publish core/applicationState/add + * @throws 1477872641 + */ + function addAndReset(applicationState, disablePublishersOnSet) { + utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477872641); + + if (_applicationStateStackPointer > 0) { + _applicationStateStack.splice(0, _applicationStateStackPointer); + } + + _applicationStateStackPointer = 0; + add(applicationState, true); + + if (!disablePublishersOnSet) { + publisherSubscriber().publish('core/applicationState/add', [getCurrentState(), getCurrentStackPointer(), getCurrentStackSize()]); + } + }; + + /** + * @public + * + * @param string + * @return object + * @throws 1477932754 + */ + function getCurrentState(type) { + if (!utility().isUndefinedOrNull(type)) { + utility().assert( + 'formDefinition' === type + || 'currentlySelectedPageIndex' === type + || 'currentlySelectedFormElementIdentifierPath' === type + || 'propertyValidationServiceRegisteredValidators' === type, + + 'Invalid parameter "type"', 1477932754 + ); + + if ('undefined' === $.type(_applicationStateStack[_applicationStateStackPointer])) { + return undefined; + } + return _applicationStateStack[_applicationStateStackPointer][type]; + } + return _applicationStateStack[_applicationStateStackPointer]; + }; + + /** + * @public + * + * @param string + * @param mixed + * @return void + * @throws 1477934111 + */ + function setCurrentState(type, value) { + utility().assert( + 'formDefinition' === type + || 'currentlySelectedPageIndex' === type + || 'currentlySelectedFormElementIdentifierPath' === type + || 'propertyValidationServiceRegisteredValidators' === type, + + 'Invalid parameter "type"', 1477934111 + ); + _applicationStateStack[_applicationStateStackPointer][type] = value; + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1477846933 + */ + function setMaximalStackSize(stackSize) { + utility().assert('number' === $.type(stackSize), 'Invalid parameter "size"', 1477846933); + _applicationStateStackSize = stackSize; + }; + + /** + * @public + * + * @return int + */ + function getMaximalStackSize() { + return _applicationStateStackSize; + }; + + /** + * @public + * + * @return int + */ + function getCurrentStackSize() { + return _applicationStateStack.length; + }; + + /** + * @public + * + * @return object + */ + function getCurrentStackPointer() { + return _applicationStateStackPointer; + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1477852138 + */ + function setCurrentStackPointer(stackPointer) { + utility().assert('number' === $.type(stackPointer), 'Invalid parameter "size"', 1477852138); + if (stackPointer < 0) { + _applicationStateStackPointer = 0; + } else if (stackPointer > _applicationStateStack.length - 1) { + _applicationStateStackPointer = _applicationStateStack.length - 1; + } else { + _applicationStateStackPointer = stackPointer; + } + }; + + + /** + * @public + * + * @return void + */ + function decrementCurrentStackPointer() { + setCurrentStackPointer(--_applicationStateStackPointer); + }; + + /** + * @public + * + * @return void + */ + function incrementCurrentStackPointer() { + setCurrentStackPointer(++_applicationStateStackPointer); + }; + + /** + * Publish the public methods. + */ + return { + add: add, + addAndReset: addAndReset, + getCurrentState: getCurrentState, + setCurrentState: setCurrentState, + getCurrentStackPointer: getCurrentStackPointer, + setCurrentStackPointer: setCurrentStackPointer, + decrementCurrentStackPointer: decrementCurrentStackPointer, + incrementCurrentStackPointer: incrementCurrentStackPointer, + setMaximalStackSize: setMaximalStackSize, + getMaximalStackSize: getMaximalStackSize, + getCurrentStackSize: getCurrentStackSize + }; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getDataBackend: dataBackend, + getFactory: factory, + getPublisherSubscriber: publisherSubscriber, + getRepository: repository, + getUtility: utility, + getPropertyValidationService: propertyValidationService, + getRunningAjaxRequest: getRunningAjaxRequest, + getApplicationStateStack: getApplicationStateStack + }; + })($); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js new file mode 100644 index 0000000000000000000000000000000000000000..c0969bd6b3732cb68e040057bee48cbdc3deb806 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js @@ -0,0 +1,310 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/Helper + */ +define(['jquery'], function($) { + 'use strict'; + + return (function($) { + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _configuration = {}; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + active: 'active', + buttonCollectionElementRemove: 't3-form-collection-element-remove-button', + buttonFormEditor: 't3-form-button', + disabled: 'disabled', + hidden: 'hidden', + icon: 't3-form-icon', + jQueryUiStateDisabled: 'ui-state-disabled', + sortableHover: 'sortable-hover' + }, + domElementDataAttributeNames: { + elementIdentifier: 'data-element-identifier-path', + identifier: 'data-identifier', + template: 'data-template-name', + templateProperty: 'data-template-property' + }, + domElementSelectorPattern: { + bracesWithKey: '[{0}]', + bracesWithKeyValue: '[{0}="{1}"]', + class: '.{0}', + id: '#{0}', + keyValue: '{0}="{1}"' + } + }; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @param object + * @return this + * @throws 1478950623 + */ + function setConfiguration(configuration) { + assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1478950623); + _configuration = $.extend(true, _defaultConfiguration, configuration); + return this; + }; + + /** + * @public + * + * @param string + * @param array + * @return string + * @throws 1478801251 + * @throws 1478801252 + */ + function buildDomElementSelectorHelper(patternIdentifier, replacements) { + var newString; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][patternIdentifier]), + 'Invalid parameter "patternIdentifier" (' + patternIdentifier + ')', + 1478801251 + ); + assert('array' === $.type(replacements), 'Invalid parameter "replacements"', 1478801252); + + newString = _configuration['domElementSelectorPattern'][patternIdentifier]; + for (var i = 0, len = replacements.length; i < len; ++i) { + newString = newString.replace('{' + i + '}', replacements[i]); + } + return newString; + }; + + /** + * @public + * + * @param string + * @param array + * @return string + * @throws 1478372374 + */ + function getDomElementSelector(selectorIdentifier, args) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][selectorIdentifier]), + 'Invalid parameter "selectorIdentifier" (' + selectorIdentifier + ')', + 1478372374 + ); + return buildDomElementSelectorHelper(selectorIdentifier, args); + }; + + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1478803906 + */ + function getDomElementClassName(classNameIdentifier, asSelector) { + var className; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementClassNames'][classNameIdentifier]), + 'Invalid parameter "classNameIdentifier" (' + classNameIdentifier + ')', + 1478803906 + ); + + className = _configuration['domElementClassNames'][classNameIdentifier]; + if (!!asSelector) { + className = getDomElementSelector('class', [className]); + } + return className; + }; + + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1479251518 + */ + function getDomElementIdName(idNameIdentifier, asSelector) { + var idName; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementIdNames'][idNameIdentifier]), + 'Invalid parameter "domElementIdNames" (' + idNameIdentifier + ')', + 1479251518 + ); + + idName = _configuration['domElementIdNames'][idNameIdentifier]; + if (!!asSelector) { + idName = getDomElementSelector('id', [idName]); + } + return idName; + }; + + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1478806884 + */ + function getDomElementDataAttributeValue(dataAttributeValueIdentifier) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]), + 'Invalid parameter "dataAttributeValueIdentifier" (' + dataAttributeValueIdentifier + ')', + 1478806884 + ); + return _configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]; + }; + + /** + * @public + * + * @param string + * @param string + * @param array + * @return string + * @throws 1478808035 + */ + function getDomElementDataAttribute(dataAttributeIdentifier, selectorIdentifier, additionalSelectorArgs) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]), + 'Invalid parameter "dataAttributeIdentifier" (' + dataAttributeIdentifier + ')', + 1478808035 + ); + + if (getUtility().isUndefinedOrNull(selectorIdentifier)) { + return _configuration['domElementDataAttributeNames'][dataAttributeIdentifier]; + } + + additionalSelectorArgs = additionalSelectorArgs || []; + return getDomElementSelector( + selectorIdentifier, + [_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]].concat(additionalSelectorArgs) + ); + }; + + /** + * @public + * + * Return a string like [data-identifier="someValue"] + * + * @return string + */ + function getDomElementDataIdentifierSelector(dataAttributeValueIdentifier) { + return getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [getDomElementDataAttributeValue(dataAttributeValueIdentifier)]); + }; + + /** + * @public + * + * @param string + * @return object + */ + function getTemplate(templateName) { + return $(getDomElementDataAttribute('template', 'bracesWithKeyValue', [getDomElementDataAttributeValue(templateName)])); + }; + + /** + * @public + * + * @param string + * @param object + * @return object + */ + function getTemplatePropertyDomElement(templatePropertyName, templateDomElement) { + return $(getDomElementDataAttribute('templateProperty', 'bracesWithKeyValue', [templatePropertyName]), $(templateDomElement)); + }; + + /** + * @public + * + * @param object formEditorApp + * @return void + */ + function bootstrap(formEditorApp) { + _formEditorApp = formEditorApp; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildDomElementSelectorHelper: buildDomElementSelectorHelper, + getDomElementClassName: getDomElementClassName, + getDomElementIdName: getDomElementIdName, + getDomElementDataAttribute: getDomElementDataAttribute, + getDomElementDataAttributeValue: getDomElementDataAttributeValue, + getDomElementDataIdentifierSelector: getDomElementDataIdentifierSelector, + getDomElementSelector: getDomElementSelector, + getTemplate: getTemplate, + getTemplatePropertyDomElement: getTemplatePropertyDomElement, + setConfiguration: setConfiguration + }; + })($); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..ae0855e02bd8c0369cd4c8467b2b6c9978276eca --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js @@ -0,0 +1,1777 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent + */ + +/** + * Add legacy functions to be accessible in the global scope. + * This is needed by TYPO3/CMS/Recordlist/ElementBrowser + */ +var setFormValueFromBrowseWin; + +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' + ], function($, Helper, Icons, Notification) { + 'use strict'; + + return (function($, Helper, Icons, Notification) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + buttonFormElementRemove: 't3-form-remove-element-button', + collectionElement: 't3-form-collection-element', + finisherEditorPrefix: 't3-form-inspector-finishers-editor-', + inspectorEditor: 'form-editor', + validatorEditorPrefix: 't3-form-inspector-validators-editor-' + }, + domElementDataAttributeNames: { + contentElementSelectorTarget: 'data-insert-target', + finisher: 'data-finisher-identifier', + validator: 'data-validator-identifier' + }, + domElementDataAttributeValues: { + collapse: 'actions-view-table-expand', + editorControlsWrapper: 'inspectorEditorControlsWrapper', + formElementHeaderEditor: 'inspectorFormElementHeaderEditor', + iconPage: 'apps-pagetree-page-default', + iconTtContent: 'mimetypes-x-content-text', + inspector: 'inspector', + 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor', + 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor', + 'Inspector-FinishersEditor': 'Inspector-FinishersEditor', + 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor', + 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor', + 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor', + 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor', + 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor', + 'Inspector-TextareaEditor': 'Inspector-TextareaEditor', + 'Inspector-TextEditor': 'Inspector-TextEditor', + 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor', + 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor', + inspectorFinishers: 'inspectorFinishers', + inspectorValidators: 'inspectorValidators', + propertyGridEditorAddRow: 'addRow', + propertyGridEditorAddRowItem: 'addRowItem', + propertyGridEditorContainer: 'propertyGridContainer', + propertyGridEditorDeleteRow: 'deleteRow', + propertyGridEditorLabel: 'label', + propertyGridEditorRowItem: 'rowItem', + propertyGridEditorSelectValue: 'selectValue', + propertyGridEditorSortRow: 'sortRow', + propertyGridEditorValue: 'value' + }, + domElementIdNames: { + finisherPrefix: 't3-form-inspector-finishers-', + validatorPrefix: 't3-form-inspector-validators-' + }, + isSortable: true + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return getFormEditorApp().getViewModel(); + }; + + /** + * @private + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @param object + * @param object + * @param string + * @param string + * @return void + * @publish view/inspector/editor/insert/perform + */ + function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + switch (editorConfiguration['templateName']) { + case 'Inspector-FormElementHeaderEditor': + renderFormElementHeaderEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CollectionElementHeaderEditor': + renderCollectionElementHeaderEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-TextEditor': + renderTextEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-FinishersEditor': + renderCollectionElementSelectionEditor( + 'finishers', + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-ValidatorsEditor': + renderCollectionElementSelectionEditor( + 'validators', + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-RemoveElementEditor': + renderRemoveElementEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-RequiredValidatorEditor': + renderRequiredValidatorEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CheckboxEditor': + renderCheckboxEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-SingleSelectEditor': + renderSingleSelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-PropertyGridEditor': + renderPropertyGridEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-TextareaEditor': + renderTextareaEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-Typo3WinBrowserEditor': + renderTypo3WinBrowserEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + } + getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [ + editorConfiguration, editorHtml, collectionElementIdentifier, collectionName + ]); + }; + + /** + * @private + * + * opens a popup window with the element browser + * + * @param string mode + * @param string params + * @param int width + * @param int height + */ + function _openTypo3WinBrowser(mode, params, width, height) { + var openedPopupWindow, url; + url = TYPO3.settings.FormEditor.typo3WinBrowserUrl + + '&mode=' + mode + '&bparams=' + params; + openedPopupWindow = window.open( + url, + 'Typo3WinBrowser', + 'height=' + height + ',width=' + width + ',status=0,menubar=0,resizable=1,scrollbars=1' + ); + openedPopupWindow.focus(); + }; + + /** + * @private + * + * @param string + * @param string + * @return object + */ + function _getCollectionElementClass(collectionName, collectionElementIdentifier) { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier; + } + }; + + /** + * @private + * + * @param string + * @param string + * @param bool + * @return object + */ + function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier; + } + }; + + /** + * @private + * + * @param object + * @param string + * @return void + */ + function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) { + sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({ + revert: 'true', + items: getHelper().getDomElementClassName('collectionElement', true), + cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,select', + delay: 200, + update: function(e, o) { + var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier, previousCollectionElementIdentifier; + + if (collectionName === 'finishers') { + dataAttributeName = getHelper().getDomElementDataAttribute('finisher'); + } else { + dataAttributeName = getHelper().getDomElementDataAttribute('validator'); + } + + movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName); + previousCollectionElementIdentifier = $(o.item) + .prevAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + nextCollectionElementIdentifier = $(o.item) + .nextAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + + getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [ + movedCollectionElementIdentifier, + previousCollectionElementIdentifier, + nextCollectionElementIdentifier, + collectionName + ]); + } + }); + }; + + /** + * @private + * + * @param object editorHtml + * @param bool multiSelection + * @param string propertyPath + * @param string propertyPathPrefix + * @return void + */ + function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) { + var defaultValue, newPropertyData; + + if (multiSelection) { + defaultValue = []; + + $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).each(function(i) { + defaultValue.push( + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val() + ); + }); + getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue); + } else { + getCurrentlySelectedFormElement().set( + propertyPathPrefix + 'defaultValue', + $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).first() + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(), + true + ); + } + + newPropertyData = []; + $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).each(function(i) { + var value, label, tmpObject; + + value = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(); + label = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel')) + .val(); + + if ('' === value) { + value = label; + } + + tmpObject = {}; + tmpObject[value] = label; + newPropertyData.push({ + _label: label, + _value: value + }); + }); + + getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData); + }; + + /** + * @private + * + * @param object + * @return object + */ + function _getEditorControlsWrapperDomElement(editorDomElement) { + return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement)); + }; + + /** + * @private + * + * @param string + * @param object + * @return void + */ + function _validateCollectionElement(propertyPath, editorHtml) { + var hasError, propertyPrefix, validationResults; + + validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath); + + if (validationResults.length > 0) { + getHelper() + .getTemplatePropertyDomElement('validationErrors', editorHtml) + .text(validationResults[0]); + getViewModel().setElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().setElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } else { + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text(''); + getViewModel().removeElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().removeElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } + + validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()); + propertyPrefix = propertyPath.split('.'); + propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1]; + + hasError = false; + for (var i = 0, len = validationResults.length; i < len; ++i) { + if ( + validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0 + && validationResults[i]['validationResults'] + && validationResults[i]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + getViewModel().setElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } else { + getViewModel().removeElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * callback from TYPO3/CMS/Recordlist/ElementBrowser + * + * @param string fieldReference + * @param string elValue + * @param string elName + * @return void + */ + setFormValueFromBrowseWin = function(fieldReference, elValue, elName) { + var result; + result = elValue.split('_'); + + $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference])) + .val(result.pop()) + .trigger('paste'); + }; + + /** + * @public + * + * @return object + */ + function getInspectorDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspector')); + }; + + /** + * @public + * + * @return object + */ + function getFinishersContainerDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement()); + }; + + /** + * @public + * + * @return object + */ + function getValidatorsContainerDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement()); + }; + + /** + * @public + * + * @param string + * @param string + * @return object + */ + function getCollectionElementDomElement(collectionName, collectionElementIdentifier) { + if (collectionName === 'finishers') { + return $(getHelper().getDomElementDataAttribute( + 'finisher', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getFinishersContainerDomElement()); + } else { + return $(getHelper().getDomElementDataAttribute( + 'validator', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getValidatorsContainerDomElement()); + } + }; + + /** + * @public + * + * @param object + * @param function + * @return void + */ + function renderEditors(formElement, callback) { + var formElementTypeDefinition; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + getInspectorDomElement().off().empty(); + + formElementTypeDefinition = getFormElementDefinition(formElement); + if ('array' !== $.type(formElementTypeDefinition['editors'])) { + return; + } + + for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) { + var html, template; + + template = getHelper() + .getTemplate(formElementTypeDefinition['editors'][i]['templateName']) + .clone(); + if (!template.length) { + continue; + } + html = $(template.html()); + + $(html) + .first() + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + getInspectorDomElement().append($(html)); + + _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html); + } + + if ('function' === $.type(callback)) { + callback(); + } + }; + + /** + * @public + * + * @param string collectionName + * @param string collectionElementIdentifier + * @return void + * @publish view/inspector/collectionElements/dnd/update + * @throws 1478354853 + * @throws 1478354854 + */ + function renderCollectionElementEditors(collectionName, collectionElementIdentifier) { + var collapseWrapper, collectionContainer, collectionContainerElementWrapper, collectionElementConfiguration, collectionElementEditorsLength; + + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid parameter "collectionName"', + 1478354853 + ); + assert( + getUtility().isNonEmptyString(collectionElementIdentifier), + 'Invalid parameter "collectionElementIdentifier"', + 1478354854 + ); + + collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( + collectionElementIdentifier, + collectionName + ); + if ('array' !== $.type(collectionElementConfiguration['editors'])) { + return; + } + + collectionContainerElementWrapper = $('<div></div>'). + addClass(getHelper().getDomElementClassName('collectionElement')); + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier); + } else { + collectionContainer = getValidatorsContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier); + } + collectionContainer.append(collectionContainerElementWrapper); + + collectionElementEditorsLength = collectionElementConfiguration['editors'].length; + if ( + collectionElementEditorsLength > 0 + && collectionElementConfiguration['editors'][0]['identifier'] === 'header' + ) { + collapseWrapper = $('<div role="tabpanel"></div>') + .addClass('panel-collapse collapse') + .prop('id', _getCollectionElementId( + collectionName, + collectionElementIdentifier + )); + } + + for (var i = 0; i < collectionElementEditorsLength; ++i) { + var html, template; + + template = getHelper() + .getTemplate(collectionElementConfiguration['editors'][i]['templateName']) + .clone(); + if (!template.length) { + continue; + } + html = $(template.html()); + + $(html).first() + .addClass(_getCollectionElementClass( + collectionName, + collectionElementConfiguration['editors'][i]['identifier'] + )) + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + + if (i === 0 && collapseWrapper) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier) + .append(html) + .append(collapseWrapper); + } else if ( + i === (collectionElementEditorsLength - 1) + && collapseWrapper + && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton' + ) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } else if (i > 0 && collapseWrapper) { + collapseWrapper.append(html); + } else { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } + + _renderEditorDispatcher( + collectionElementConfiguration['editors'][i], + html, + collectionElementIdentifier, + collectionName + ); + } + + if ( + collectionElementEditorsLength === 2 + && collectionElementConfiguration['editors'][0]['identifier'] === 'header' + && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton' + ) { + $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove(); + } + + if (_configuration['isSortable']) { + _addSortableCollectionElementsEvents(collectionContainer, collectionName); + } + }; + + /** + * @public + * + * @string collectionName + * @param object editorConfiguration + * @param object editorHtml + * @return void + * @publish view/inspector/collectionElement/existing/selected + * @publish view/inspector/collectionElement/new/selected + * @throws 1475423098 + * @throws 1475423099 + * @throws 1475423100 + * @throws 1475423101 + * @throws 1478362968 + */ + function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) { + var alreadySelectedCollectionElements, selectElement, collectionContainer; + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid configuration "collectionName"', + 1478362968 + ); + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475423098 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475423099 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475423100 + ); + assert( + 'array' === $.type(editorConfiguration['selectOptions']), + 'Invalid configuration "selectOptions"', + 1475423101 + ); + + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + alreadySelectedCollectionElements = getRootFormElement().get(collectionName); + } else { + collectionContainer = getValidatorsContainerDomElement(); + alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName); + } + + collectionContainer.off().empty(); + + getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']); + selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml); + + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) { + getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [ + alreadySelectedCollectionElements[i]['identifier'], + collectionName + ]); + } + } + + for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { + var appendOption = true; + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) { + if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) { + appendOption = false; + break; + } + } + } + if (appendOption) { + selectElement.append(new Option( + editorConfiguration['selectOptions'][i]['label'], + editorConfiguration['selectOptions'][i]['value'] + )); + } + } + + selectElement.on('change', function() { + if ($(this).val() !== '') { + var value = $(this).val(); + $('option[value="' + value + '"]', $(this)).remove(); + + getFormEditorApp().getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [value, collectionName] + ); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421525 + * @throws 1475421526 + * @throws 1475421527 + * @throws 1475421528 + */ + function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526); + + Icons.getIcon( + getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + getHelper().getTemplatePropertyDomElement('header-label', editorHtml) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))) + .append(buildTitleByFormElement()); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421257 + * @throws 1475421258 + * @throws 1475421259 + */ + function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var collectionElementConfiguration, setData; + + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421258 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421257 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421259 + ); + + setData = function(icon) { + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend($(icon)); + + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('collapse'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + var iconWrap; + iconWrap = $('<a></a>') + .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true)) + .attr('data-toggle', 'collapse') + .attr('aria-expanded', 'true') + .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier)) + .addClass('collapsed') + .append($(icon)); + + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend(iconWrap); + }); + }; + + collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier); + if (collectionName === 'validators') { + Icons.getIcon( + collectionElementConfiguration['iconIdentifier'], + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + setData(icon); + }); + } else { + Icons.getIcon( + collectionElementConfiguration['iconIdentifier'], + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + setData(icon); + }); + } + + if (editorConfiguration['label']) { + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + } + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421053 + * @throws 1475421054 + * @throws 1475421055 + * @throws 1475421056 + */ + function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyPath, propertyData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421053 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421054 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421055 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475421056 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration['propertyPath'], + collectionElementIdentifier, + collectionName + ); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + _validateCollectionElement(propertyPath, editorHtml); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + _validateCollectionElement(propertyPath, editorHtml); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421048 + * @throws 1475421049 + * @throws 1475421050 + * @throws 1475421051 + * @throws 1475421052 + */ + function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath, selectElement; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421048 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421049 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421050 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475421051 + ); + assert( + 'array' === $.type(editorConfiguration['selectOptions']), + 'Invalid configuration "selectOptions"', + 1475421052 + ); + + propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration['propertyPath'], + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) { + var option; + + if (editorConfiguration['selectOptions'][i]['value'] === propertyData) { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); + } else { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i); + } + $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); + selectElement.append(option); + } + + selectElement.on('change', function() { + getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value')); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475419226 + * @throws 1475419227 + * @throws 1475419228 + * @throws 1475419229 + * @throws 1475419230 + * @throws 1475419231 + * @throws 1475419232 + */ + function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix, rowItemTemplate, setData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475419226 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475419227 + ); + assert( + 'boolean' === $.type(editorConfiguration['enableAddRow']), + 'Invalid configuration "enableAddRow"', + 1475419228 + ); + assert( + 'boolean' === $.type(editorConfiguration['enableDeleteRow']), + 'Invalid configuration "enableDeleteRow"', + 1475419230 + ); + assert( + 'boolean' === $.type(editorConfiguration['isSortable']), + 'Invalid configuration "isSortable"', + 1475419229 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475419231 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475419232 + ); + + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + propertyPathPrefix = getFormEditorApp().buildPropertyPath( + undefined, + collectionElementIdentifier, + collectionName, + undefined, + true + ); + if (getUtility().isNonEmptyString(propertyPathPrefix)) { + propertyPathPrefix = propertyPathPrefix + '.'; + } + + if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) { + multiSelection = false; + } else { + multiSelection = !!editorConfiguration['multiSelection']; + } + + rowItemTemplate = $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove(); + + if (!!editorConfiguration['enableDeleteRow']) { + $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), + $(rowItemTemplate) + ).on('click', function() { + if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .off() + .empty() + .remove(); + + _setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration['propertyPath'], + propertyPathPrefix + ); + } else { + Notification.error( + editorConfiguration['removeLastAvailableRowFlashMessageTitle'], + editorConfiguration['removeLastAvailableRowFlashMessageMessage'], + 2 + ); + } + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + if (!!editorConfiguration['isSortable']) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .addClass(getHelper().getDomElementClassName('sortable')) + .sortable({ + revert: 'true', + items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + update: function(e, o) { + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); + } + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), + $(rowItemTemplate) + ).on('change', function() { + if (!multiSelection) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml)) + .not($(this)) + .prop('checked', false); + } + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); + }); + + $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), + $(rowItemTemplate) + ).on('keyup paste', function() { + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); + }); + + $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), + $(rowItemTemplate) + ).on('focusout', function() { + if ('' === $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val() + ) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val($(this).val()); + } + }); + + if (!!editorConfiguration['enableAddRow']) { + addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem')) + .before($(rowItemTemplate).clone(true, true)); + }); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(addRowTemplate).clone(true, true)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + } + + defaultValue = {}; + if (multiSelection) { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'); + } + } else { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')}; + } + } + propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {}; + + setData = function(label, value) { + var isPreselected, newRowTemplate; + + isPreselected = false; + newRowTemplate = $(rowItemTemplate).clone(true, true); + + for (var defaultValueKey in defaultValue) { + if (!defaultValue.hasOwnProperty(defaultValueKey)) { + continue; + } + if (defaultValue[defaultValueKey] === value) { + isPreselected = true; + break; + } + } + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value); + if (isPreselected) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate)) + .prop('checked', true); + } + + if (!!editorConfiguration['enableAddRow']) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)) + .before($(newRowTemplate)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(newRowTemplate)); + } + }; + + if ('object' === $.type(propertyData)) { + for (var propertyDataKey in propertyData) { + if (!propertyData.hasOwnProperty(propertyDataKey)) { + continue; + } + setData(propertyData[propertyDataKey], propertyDataKey); + } + } else { + for (var i = 0, len = propertyData.length; i < len; ++i) { + setData(propertyData[i]['_label'], propertyData[i]['_value']); + } + } + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @publish view/inspector/collectionElement/new/selected + * @publish view/inspector/removeCollectionElement/perform + * @throws 1475417093 + * @throws 1475417094 + * @throws 1475417095 + * @throws 1475417096 + */ + function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var validatorIdentifier; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475417093 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475417094 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']), + 'Invalid configuration "validatorIdentifier"', + 1475417095 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475417096 + ); + + validatorIdentifier = editorConfiguration['validatorIdentifier']; + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + + if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function() { + if ($(this).is(":checked")) { + getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [validatorIdentifier, 'validators'] + ); + } else { + getPublisherSubscriber().publish( + 'view/inspector/removeCollectionElement/perform', + [validatorIdentifier, 'validators'] + ); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1476218671 + * @throws 1476218672 + * @throws 1476218673 + * @throws 1476218674 + */ + function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1476218671 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1476218672 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1476218673 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1476218674 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + if ( + ('boolean' === $.type(propertyData) && propertyData) + || propertyData === 'true' + || propertyData === 1 + || propertyData === "1" + ) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function() { + if ($(this).is(":checked")) { + getCurrentlySelectedFormElement().set(propertyPath, true); + } else { + getCurrentlySelectedFormElement().set(propertyPath, false); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475412567 + * @throws 1475412568 + * @throws 1475416098 + * @throws 1475416099 + */ + function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyPath, propertyData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475412567 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475412568 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475416098 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475416099 + ); + + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + $('textarea', $(editorHtml)).val(propertyData); + + $('textarea', $(editorHtml)).on('keyup paste', function() { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1477300587 + * @throws 1477300588 + * @throws 1477300589 + * @throws 1477300590 + * @throws 1477318981 + * @throws 1477319859 + */ + function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var iconType, propertyPath, propertyData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1477300587 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1477300588 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1477300589 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['buttonLabel']), + 'Invalid configuration "buttonLabel"', + 1477318981 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1477300590 + ); + assert( + 'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'], + 'Invalid configuration "browsableType"', + 1477319859 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + getHelper() + .getTemplatePropertyDomElement('buttonLabel', editorHtml) + .append(editorConfiguration['buttonLabel']); + + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']); + + iconType = ('tt_content' === editorConfiguration['browsableType']) + ? getHelper().getDomElementDataAttributeValue('iconTtContent') + : getHelper().getDomElementDataAttributeValue('iconPage'); + Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) { + getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon)); + }); + + getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() { + var insertTarget, randomIdentifier; + + randomIdentifier = Math.floor((Math.random() * 100000) + 1); + insertTarget = $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper')) + .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey')); + + insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier); + _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']); + }); + + propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + _validateCollectionElement(propertyPath, editorHtml); + getHelper() + .getTemplatePropertyDomElement('propertyPath', editorHtml) + .val(propertyData); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + _validateCollectionElement(propertyPath, editorHtml); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475412563 + * @throws 1475412564 + */ + function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564); + + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + + $('button', $(editorHtml)) + .addClass( + getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' + + getHelper().getDomElementClassName('buttonFormEditor') + ); + } else { + $('button', $(editorHtml)).addClass( + getHelper().getDomElementClassName('buttonCollectionElementRemove') + ); + } + + $('button', $(editorHtml)).on('click', function(e) { + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + getViewModel().showRemoveFormElementModal(); + } else { + getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName); + } + }); + }; + + /** + * @public + * + * @param string content + * @return void + */ + function setFormElementHeaderEditorContent(content) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) { + content = buildTitleByFormElement(); + } + + $(getHelper() + .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement()) + .html(content); + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1478967319 + */ + function buildTitleByFormElement(formElement) { + var label; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319); + + return $('<span></span>').text((formElement.get('label') + ? formElement.get('label') + : formElement.get('identifier'))); + }; + + /** + * @public + * + * @param object + * @param object + * @return this + */ + function bootstrap(formEditorApp, configuration) { + _formEditorApp = formEditorApp; + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + getCollectionElementDomElement: getCollectionElementDomElement, + getFinishersContainerDomElement: getFinishersContainerDomElement, + getInspectorDomElement: getInspectorDomElement, + getValidatorsContainerDomElement: getValidatorsContainerDomElement, + renderCheckboxEditor: renderCheckboxEditor, + renderCollectionElementEditors: renderCollectionElementEditors, + renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor, + renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor, + renderEditors: renderEditors, + renderFormElementHeaderEditor: renderFormElementHeaderEditor, + renderPropertyGridEditor: renderPropertyGridEditor, + renderRemoveElementEditor: renderRemoveElementEditor, + renderRequiredValidatorEditor: renderRequiredValidatorEditor, + renderSingleSelectEditor: renderSingleSelectEditor, + renderTextareaEditor: renderTextareaEditor, + renderTextEditor: renderTextEditor, + renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor, + setFormElementHeaderEditorContent: setFormElementHeaderEditorContent + }; + })($, Helper, Icons, Notification); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js new file mode 100644 index 0000000000000000000000000000000000000000..475b0f2d8b8b93455f4da3c6cd23bb1dea6139a8 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js @@ -0,0 +1,1059 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/Mediator + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper' + ], function($, Helper) { + 'use strict'; + + return (function($, Helper) { + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _viewModel = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return _viewModel; + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(getViewModel().getConfiguration()); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return void + */ + function _subscribeEvents() { + + /* ********************************************************* + * Misc + * ********************************************************/ + + /** + * @private + * + * @return string + */ + window.onbeforeunload = function(e) { + if (!getFormEditorApp().getUnsavedContent()) { + return; + } + e = e || window.event; + if (e) { + e.returnValue = getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'); + } + return getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'); + }; + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/ready + */ + getPublisherSubscriber().subscribe('view/ready', function(topic, args) { + getViewModel().onViewReadyBatch(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = applicationState + * args[1] = stackPointer + * args[2] = stackSize + * @return void + * @subscribe core/applicationState/add + */ + getPublisherSubscriber().subscribe('core/applicationState/add', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + if (args[2] > 1 && args[1] <= args[2]) { + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } else { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } + }); + + /* ********************************************************* + * Ajax + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = html + * @return void + * @subscribe core/ajax/saveFormDefinition/success + */ + getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/success', function(topic, args) { + getFormEditorApp().setUnsavedContent(false); + getViewModel().showSaveSuccessMessage(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = html + * args[1] = pageIndex + * @return void + * @subscribe core/ajax/renderFormDefinitionPage/success + */ + getPublisherSubscriber().subscribe('core/ajax/renderFormDefinitionPage/success', function(topic, args) { + getViewModel().renderPreviewStageArea(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = jqXHR + * args[1] = textStatus + * args[2] = errorThrown + * @return void + * @subscribe core/ajax/saveFormDefinition/error + */ + getPublisherSubscriber().subscribe('core/ajax/error', function(topic, args) { + if (args[0].status !== 0) { + getViewModel().showErrorFlashMessage(args[1], args[2]); + getViewModel().renderPreviewStageArea(args[0].responseText); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe ajax/beforeSend + */ + getPublisherSubscriber().subscribe('ajax/beforeSend', function(topic, args) { + getViewModel().showSaveButtonSpinnerIcon(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe ajax/complete + */ + getPublisherSubscriber().subscribe('ajax/complete', function(topic, args) { + getViewModel().showSaveButtonSaveIcon(); + }); + + /* ********************************************************* + * Header + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/header/button/save/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/save/clicked', function(topic, args) { + + if (getFormEditorApp().validationResultsHasErrors(getFormEditorApp().validateFormElementRecursive(getRootFormElement(), true))) { + getViewModel().showValidationErrorsModal(); + } else { + getFormEditorApp().saveFormDefinition(); + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/header/button/newPage/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/newPage/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertPagesModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/header/button/close/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/close/clicked', function(topic, args) { + getViewModel().showCloseConfirmationModal(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/undoButton/clicked + */ + getPublisherSubscriber().subscribe('view/undoButton/clicked', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + getFormEditorApp().undoApplicationState(); + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + getFormEditorApp().setUnsavedContent(true); + + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/redoButton/clicked + */ + getPublisherSubscriber().subscribe('view/redoButton/clicked', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + getFormEditorApp().redoApplicationState(); + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + getFormEditorApp().setUnsavedContent(true); + + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /* ********************************************************* + * Stage + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/stage/element/clicked + */ + getPublisherSubscriber().subscribe('view/stage/element/clicked', function(topic, args) { + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().refreshSelectedElementItemsBatch(); + getViewModel().addAbstractViewValidationResults(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/stage/abstract/elementToolbar/button/newElement/clicked + */ + getPublisherSubscriber().subscribe('view/stage/abstract/elementToolbar/button/newElement/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertElementsModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/newElementButton/clicked + */ + getPublisherSubscriber().subscribe('view/stage/abstract/button/newElement/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertElementsModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementDomElement + * args[1] = draggedFormPlaceholderDomElement + * @return void + * @subscribe view/stage/abstract/dnd/start + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/start', function(topic, args) { + getViewModel().onAbstractViewDndStartBatch(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementIdentifierPath + * @return void + * @subscribe view/stage/abstract/dnd/stop + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/stop', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().refreshSelectedElementItemsBatch(); + getViewModel().addAbstractViewValidationResults(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = placeholderDomElement + * args[1] = parentFormElementIdentifierPath + * args[2] = enclosingCompositeFormElement + * @return void + * @subscribe view/stage/abstract/dnd/change + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/change', function(topic, args) { + getViewModel().onAbstractViewDndChangeBatch(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedDomElement + * args[1] = movedFormElementIdentifierPath + * args[2] = previousFormElementIdentifierPath + * args[3] = nextFormElementIdentifierPath + * @return void + * @subscribe view/stage/abstract/dnd/update + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/update', function(topic, args) { + getViewModel().onAbstractViewDndUpdateBatch(args[0], args[1], args[2], args[3]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/viewModeButton/abstract/clicked + */ + getPublisherSubscriber().subscribe('view/viewModeButton/abstract/clicked', function(topic, args) { + if (getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(false); + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/viewModeButton/preview/clicked + */ + getPublisherSubscriber().subscribe('view/viewModeButton/preview/clicked', function(topic, args) { + if (!getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(true); + getFormEditorApp().renderCurrentFormPage(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/paginationPrevious/clicked + */ + getPublisherSubscriber().subscribe('view/paginationPrevious/clicked', function(topic, args) { + getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() - 1); + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/paginationNext/clicked + */ + getPublisherSubscriber().subscribe('view/paginationNext/clicked', function(topic, args) { + getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() + 1); + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/stage/abstract/render/postProcess + */ + getPublisherSubscriber().subscribe('view/stage/abstract/render/postProcess', function(topic, args) { + getViewModel().renderUndoRedo(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/stage/preview/render/postProcess + */ + getPublisherSubscriber().subscribe('view/stage/preview/render/postProcess', function(topic, args) { + getViewModel().renderUndoRedo(); + }); + + /* ********************************************************* + * Structure + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/tree/node/clicked + */ + getPublisherSubscriber().subscribe('view/tree/node/clicked', function(topic, args) { + var oldPageIndex; + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { + getViewModel().renderAbstractStageArea(); + } else { + getViewModel().renderAbstractStageArea(false); + } + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/structure/root/selected + */ + getPublisherSubscriber().subscribe('view/structure/root/selected', function(topic, args) { + if (!getFormEditorApp().isRootFormElementSelected()) { + getViewModel().addStructureRootElementSelection(); + getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement()); + getViewModel().renderAbstractStageArea(); + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/header/button/newPage/clicked + */ + getPublisherSubscriber().subscribe('view/structure/button/newPage/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertPagesModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementIdentifierPath + * @return void + * @subscribe view/tree/dnd/stop + */ + getPublisherSubscriber().subscribe('view/tree/dnd/stop', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = placeholderDomElement + * args[1] = parentFormElementIdentifierPath + * args[2] = enclosingCompositeFormElement + * @return void + * @subscribe view/tree/dnd/change + */ + getPublisherSubscriber().subscribe('view/tree/dnd/change', function(topic, args) { + getViewModel().onStructureDndChangeBatch(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedDomElement + * args[1] = movedFormElementIdentifierPath + * args[2] = previousFormElementIdentifierPath + * args[3] = nextFormElementIdentifierPath + * @return void + * @subscribe view/tree/dnd/update + */ + getPublisherSubscriber().subscribe('view/tree/dnd/update', function(topic, args) { + getViewModel().onStructureDndUpdateBatch(args[0], args[1], args[2], args[3]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/structure/renew/postProcess + */ + getPublisherSubscriber().subscribe('view/structure/renew/postProcess', function(topic, args) { + getViewModel().addStructureValidationResults(); + }); + + /* ********************************************************* + * Inspector + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/inspector/removeCollectionElement/perform + */ + getPublisherSubscriber().subscribe('view/inspector/removeCollectionElement/perform', function(topic, args) { + getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * @return void + * @subscribe view/inspector/collectionElement/selected + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElement/new/selected', function(topic, args) { + getViewModel().createAndAddPropertyCollectionElement(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * @return void + * @subscribe view/inspector/collectionElement/selected + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElement/existing/selected', function(topic, args) { + getViewModel().renderInspectorCollectionElementEditors(args[1], args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedCollectionElementIdentifier + * args[1] = previousCollectionElementIdentifier + * args[2] = nextCollectionElementIdentifier + * args[3] = collectionName + * @return void + * @subscribe view/inspector/collectionElements/dnd/update + * @throws 1477407673 + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElements/dnd/update', function(topic, args) { + if (args[2]) { + getViewModel().movePropertyCollectionElement(args[0], 'before', args[2], args[3]); + } else if (args[1]) { + getViewModel().movePropertyCollectionElement(args[0], 'after', args[1], args[3]); + } else { + assert(false, 'Next element or previous element need to be set.', 1477407673); + } + }); + + /* ********************************************************* + * Form element + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = propertyPath + * args[1] = value + * args[2] = oldValue + * args[3] = formElementIdentifierPath + * @return void + * @subscribe core/formElement/somePropertyChanged + */ + getPublisherSubscriber().subscribe('core/formElement/somePropertyChanged', function(topic, args) { + var hasError, validationElement, validationResults; + + validationResults = []; + if ('renderables' !== args[0]) { + if (!getFormEditorApp().isRootFormElementSelected() && 'label' === args[0]) { + getViewModel().getStructure().setTreeNodeTitle(); + getViewModel().setInspectorFormElementHeaderEditorContent(); + } else if (!getFormEditorApp().getUtility().isUndefinedOrNull(args[3]) && getRootFormElement().get('__identifierPath') === args[3]) { + getViewModel().setStructureRootElementTitle(); + getViewModel().setStageHeadline(); + getViewModel().setInspectorFormElementHeaderEditorContent(); + } + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(false, false); + } + getViewModel().addStructureValidationResults(); + } + + getFormEditorApp().setUnsavedContent(true); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = parentFormElement + * @return void + * @subscribe view/formElement/removed + */ + getPublisherSubscriber().subscribe('view/formElement/removed', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = newFormElement + * @return void + * @subscribe view/formElement/inserted + */ + getPublisherSubscriber().subscribe('view/formElement/inserted', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * args[3] = collectionElementConfiguration + * args[4] = referenceCollectionElementIdentifier + * @return void + * @subscribe view/collectionElement/new/added + */ + getPublisherSubscriber().subscribe('view/collectionElement/new/added', function(topic, args) { + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedCollectionElementIdentifier + * args[1] = previousCollectionElementIdentifier + * args[2] = nextCollectionElementIdentifier + * args[3] = collectionName + * @return void + * @subscribe view/collectionElement/moved + * @throws 1477407673 + */ + getPublisherSubscriber().subscribe('view/collectionElement/moved', function(topic, args) { + getViewModel().renderInspectorEditors(undefined, false); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/collectionElement/removed + */ + getPublisherSubscriber().subscribe('view/collectionElement/removed', function(topic, args) { + getViewModel().renderInspectorEditors(undefined, false); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/bottom + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/bottom', function(topic, args) { + var lastRenderable; + + lastRenderable = getFormEditorApp().getLastTopLevelElementOnCurrentPage(); + if (!lastRenderable) { + getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); + } else { + if ( + !getFormEditorApp().getFormElementDefinition(lastRenderable, '_isTopLevelFormElement') + && getFormEditorApp().getFormElementDefinition(lastRenderable, '_isCompositeFormElement') + ) { + getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); + } else { + getViewModel().createAndAddFormElement(args[0], lastRenderable); + } + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @publish view/formElement/inserted + * @subscribe view/insertElements/perform/after + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/after', function(topic, args) { + var newFormElement; + newFormElement = getViewModel().createAndAddFormElement(args[0], undefined, true); + newFormElement = getViewModel().moveFormElement(newFormElement, 'after', getFormEditorApp().getCurrentlySelectedFormElement()); + getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/inside + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/inside', function(topic, args) { + getViewModel().createAndAddFormElement(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/after + */ + getPublisherSubscriber().subscribe('view/insertPages/perform', function(topic, args) { + getViewModel().createAndAddFormElement(args[0]); + }); + + /* ********************************************************* + * Modals + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/modal/close/perform + */ + getPublisherSubscriber().subscribe('view/modal/close/perform', function(topic, args) { + getFormEditorApp().setUnsavedContent(false); + getViewModel().closeEditor(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElement + * @return void + * @subscribe view/modal/removeFormElement/perform + */ + getPublisherSubscriber().subscribe('view/modal/removeFormElement/perform', function(topic, args) { + getViewModel().removeFormElement(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/modal/removeCollectionElement/perform + */ + getPublisherSubscriber().subscribe('view/modal/removeCollectionElement/perform', function(topic, args) { + getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/modal/validationErrors/element/clicked + */ + getPublisherSubscriber().subscribe('view/modal/validationErrors/element/clicked', function(topic, args) { + var oldPageIndex; + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + + if (getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(false); + } + + if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { + getViewModel().renderAbstractStageArea(); + } else { + getViewModel().renderAbstractStageArea(false); + } + + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + }; + + /** + * @public + * + * @param object + * @param object + * @return void + */ + function bootstrap(formEditorApp, viewModel) { + _formEditorApp = formEditorApp; + _viewModel = viewModel; + _helperSetup(); + _subscribeEvents(); + }; + + /** + * Implements the "Revealing Module Pattern". + */ + return { + /** + * Publish the public methods. + */ + bootstrap: bootstrap + }; + })($, Helper); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..7f81a37fd0d6dd0ba5673712bd5e4a6d92481d91 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js @@ -0,0 +1,493 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Icons' + ], function($, Helper, Modal, Severity, Icons) { + 'use strict'; + + return (function($, Helper, Modal, Severity, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + buttonDefault: 'btn-default', + buttonInfo: 'btn-info', + buttonWarning: 'btn-warning' + }, + domElementDataAttributeNames: { + elementType: 'element-type' + }, + domElementDataAttributeValues: { + rowItem: 'rowItem', + rowLink: 'rowLink', + rowsContainer: 'rowsContainer', + templateInsertElements: 'Modal-InsertElements', + templateInsertPages: 'Modal-InsertPages', + templateValidationErrors: 'Modal-ValidationErrors' + } + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @public + * + * @param string publisherTopicName + * @param object publisherTopicArguments + * @return void + * @throws 1478889044 + * @throws 1478889049 + */ + function _showRemoveElementModal(publisherTopicName, publisherTopicArguments) { + var modalButtons = []; + + assert( + getUtility().isNonEmptyString(publisherTopicName), + 'Invalid parameter "publisherTopicName"', + 1478889049 + ); + assert( + 'array' === $.type(publisherTopicArguments), + 'Invalid parameter "formElement"', + 1478889044 + ); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementCancleButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'cancel', + trigger: function () { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonWarning'), + name: 'confirm', + trigger: function () { + getPublisherSubscriber().publish(publisherTopicName, publisherTopicArguments); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogTitle'), + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogMessage'), + Severity.warning, + modalButtons + ); + }; + + /** + * @private + * + * @param object modalContent + * @param string publisherTopicName + * @return void + * @publish mixed + * @throws 1478910954 + */ + function _insertElementsModalSetup(modalContent, publisherTopicName) { + assert( + getUtility().isNonEmptyString(publisherTopicName), + 'Invalid parameter "publisherTopicName"', + 1478910954 + ); + + $('a', modalContent).on("click", function(e) { + getPublisherSubscriber().publish(publisherTopicName, [$(this).data(getHelper().getDomElementDataAttribute('elementType'))]); + $('a', modalContent).off(); + Modal.currentModal.trigger('modal-dismiss'); + }); + }; + + /** + * @private + * + * @param object modalContent + * @param object validationResults + * @return void + * @publish view/modal/validationErrors/element/clicked + * @throws 1479161268 + */ + function _validationErrorsModalSetup(modalContent, validationResults) { + var formElement, newRowItem, rowItemTemplate; + + assert( + 'array' === $.type(validationResults), + 'Invalid parameter "validationResults"', + 1479161268 + ); + + rowItemTemplate = $( + getHelper().getDomElementDataIdentifierSelector('rowItem'), + modalContent + ).clone(); + + $(getHelper().getDomElementDataIdentifierSelector('rowItem'), modalContent).remove(); + + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + formElement = getFormEditorApp() + .getFormElementByIdentifierPath(validationResults[i]['formElementIdentifierPath']); + newRowItem = rowItemTemplate.clone(); + $(getHelper().getDomElementDataIdentifierSelector('rowLink'), newRowItem) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + validationResults[i]['formElementIdentifierPath'] + ) + .html(_buildTitleByFormElement(formElement)); + $(getHelper().getDomElementDataIdentifierSelector('rowsContainer'), modalContent) + .append(newRowItem); + } + } + + $('a', modalContent).on("click", function(e) { + getPublisherSubscriber().publish('view/modal/validationErrors/element/clicked', [ + $(this).attr(getHelper().getDomElementDataAttribute('elementIdentifier')) + ]); + $('a', modalContent).off(); + Modal.currentModal.trigger('modal-dismiss'); + }); + }; + + /** + * @private + * + * @param object + * @return object + * @throws 1479162557 + */ + function _buildTitleByFormElement(formElement) { + var label; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479162557); + + return $('<span></span>').text((formElement.get('label') + ? formElement.get('label') + : formElement.get('identifier'))); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @param object formElement + * @return void + * @publish view/modal/removeFormElement/perform + */ + function showRemoveFormElementModal(formElement) { + _showRemoveElementModal('view/modal/removeFormElement/perform', [formElement]); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return void + * @publish view/modal/removeCollectionElement/perform + * @throws 1478894420 + * @throws 1478894421 + */ + function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { + assert( + getUtility().isNonEmptyString(collectionElementIdentifier), + 'Invalid parameter "collectionElementIdentifier"', + 1478894420 + ); + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid parameter "collectionName"', + 1478894421 + ); + + _showRemoveElementModal('view/modal/removeCollectionElement/perform', [collectionElementIdentifier, collectionName, formElement]); + }; + + /** + * @public + * + * @return void + * @publish view/modal/close/perform + */ + function showCloseConfirmationModal() { + var modalButtons = []; + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalCloseCancleButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'cancel', + trigger: function () { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalCloseConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonWarning'), + name: 'confirm', + trigger: function () { + getPublisherSubscriber().publish('view/modal/close/perform', []); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'), + getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'), + Severity.warning, + modalButtons + ); + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function showInsertElementsModal(publisherTopicName) { + var html, template; + + template = getHelper().getTemplate('templateInsertElements'); + if (template.length > 0) { + html = $(template.html()); + _insertElementsModalSetup(html, publisherTopicName); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalInsertElementsDialogTitle'), + $(html), + Severity.info + ); + } + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function showInsertPagesModal(publisherTopicName) { + var html, template; + + template = getHelper().getTemplate('templateInsertPages'); + if (template.length > 0) { + html = $(template.html()); + _insertElementsModalSetup(html, publisherTopicName); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalInsertPagesDialogTitle'), + $(html), + Severity.info + ); + } + }; + + /** + * @public + * + * @param object + * @return void + */ + function showValidationErrorsModal(validationResults) { + var html, template, modalButtons = []; + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'confirm', + trigger: function () { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + template = getHelper().getTemplate('templateValidationErrors'); + if (template.length > 0) { + html = $(template.html()).clone(); + _validationErrorsModalSetup(html, validationResults); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsDialogTitle'), + html, + Severity.error, + modalButtons + ); + } + } + + /** + * @public + * + * @param object + * @param object + * @return this + */ + function bootstrap(formEditorApp, configuration) { + _formEditorApp = formEditorApp; + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + showCloseConfirmationModal: showCloseConfirmationModal, + showInsertElementsModal: showInsertElementsModal, + showInsertPagesModal: showInsertPagesModal, + showRemoveCollectionElementModal: showRemoveCollectionElementModal, + showRemoveFormElementModal: showRemoveFormElementModal, + showValidationErrorsModal: showValidationErrorsModal + }; + })($, Helper, Modal, Severity, Icons); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..f69b522f65ea16d17b6fd77756fa5a71dfd30327 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js @@ -0,0 +1,1119 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/StageComponent + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' + ], function($, Helper, Icons) { + 'use strict'; + + return (function($, Helper, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + formElementIsComposit: 't3-form-element-composit', + formElementIsTopLevel: 't3-form-element-toplevel', + noNesting: 'mjs-nestedSortable-no-nesting', + selected: 'selected', + sortable: 'sortable', + previewViewPreviewElement: 't3-form-element-preview' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type', + noSorting: 'data-no-sorting' + }, + domElementDataAttributeValues: { + abstractViewToolbar: 'elementToolbar', + abstractViewToolbarNewElement: 'stageElementToolbarNewElement', + abstractViewToolbarNewElementSplitButton: 'stageElementToolbarNewElementSplitButton', + abstractViewToolbarNewElementSplitButtonAfter: 'stageElementToolbarNewElementSplitButtonAfter', + abstractViewToolbarNewElementSplitButtonInside: 'stageElementToolbarNewElementSplitButtonInside', + abstractViewToolbarRemoveElement: 'stageElementToolbarRemoveElement', + buttonHeaderRedo: 'redoButton', + buttonHeaderUndo: 'undoButton', + buttonPaginationPrevious: 'buttonPaginationPrevious', + buttonPaginationNext: 'buttonPaginationNext', + 'FormElement-_ElementToolbar': 'FormElement-_ElementToolbar', + 'FormElement-_UnknownElement': 'FormElement-_UnknownElement', + 'FormElement-AdvancedPassword': 'FormElement-AdvancedPassword', + 'FormElement-Checkbox': 'FormElement-Checkbox', + 'FormElement-ContentElement': 'FormElement-ContentElement', + 'FormElement-DatePicker': 'FormElement-DatePicker', + 'FormElement-Fieldset': 'FormElement-Fieldset', + 'FormElement-FileUpload': 'FormElement-FileUpload', + 'FormElement-Hidden': 'FormElement-Hidden', + 'FormElement-ImageUpload': 'FormElement-ImageUpload', + 'FormElement-MultiCheckbox': 'FormElement-MultiCheckbox', + 'FormElement-MultiSelect': 'FormElement-MultiSelect', + 'FormElement-Page': 'FormElement-Page', + 'FormElement-Password': 'FormElement-Password', + 'FormElement-RadioButton': 'FormElement-RadioButton', + 'FormElement-SingleSelect': 'FormElement-SingleSelect', + 'FormElement-StaticText': 'FormElement-StaticText', + 'FormElement-SummaryPage': 'FormElement-SummaryPage', + 'FormElement-Text': 'FormElement-Text', + 'FormElement-Textarea': 'FormElement-Textarea', + formElementIcon: 'elementIcon', + iconValidator: 't3-form-icon-validator', + multiValueContainer: 'multiValueContainer', + paginationTitle: 'paginationTitle', + stageHeadline: 'formDefinitionLabel', + stagePanel: 'stagePanel', + validatorsContainer: 'validatorsContainer', + validatorIcon: 'validatorIcon' + }, + isSortable: true + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _stageDomElement = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return getFormEditorApp().getViewModel(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @return object + * @return string + * @return void + */ + function _setTemplateTextContent(domElement, content) { + if (getUtility().isNonEmptyString(content)) { + $(domElement).text(content); + } + } + + /** + * @private + * + * @param object + * @param object + * @return void + * @publish view/stage/abstract/render/template/perform + */ + function _renderTemplateDispatcher(formElement, template) { + switch (formElement.get('type')) { + case 'Checkbox': + renderCheckboxTemplate(formElement, template); + break; + case 'FileUpload': + case 'ImageUpload': + renderFileUploadTemplates(formElement, template); + break; + case 'SingleSelect': + case 'RadioButton': + case 'MultiSelect': + case 'MultiCheckbox': + renderSelectTemplates(formElement, template); + break; + case 'Textarea': + case 'AdvancedPassword': + case 'Password': + case 'Text': + renderSimpleTemplateWithValidators(formElement, template); + break; + case 'Fieldset': + case 'SummaryPage': + case 'Page': + case 'DatePicker': + case 'StaticText': + case 'Hidden': + case 'ContentElement': + renderSimpleTemplate(formElement, template); + break; + } + getPublisherSubscriber().publish('view/stage/abstract/render/template/perform', [formElement, template]); + }; + + /** + * @private + * + * @param object + * @return object + * @throws 1478987818 + */ + function _renderNestedSortableListItem(formElement) { + var childFormElements, childList, listItem, template; + + listItem = $('<li></li>'); + if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('noNesting')); + } + + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); + } + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('formElementIsComposit')); + } + + try { + template = getHelper().getTemplate('FormElement-' + formElement.get('type')).clone(); + } catch(error) { + template = getHelper().getTemplate('FormElement-_UnknownElement').clone(); + assert( + template.length, + 'No template found for element "' + formElement.get('__identifierPath') + '"', + 1478987818 + ); + } + + template = $('<div></div>') + .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) + .append($(template.html())); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); + } + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); + } + listItem.append(template); + + _renderTemplateDispatcher(formElement, template); + + childFormElements = formElement.get('renderables'); + childList = null; + if ('array' === $.type(childFormElements)) { + childList = $('<ol></ol>'); + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + childList.addClass(getHelper().getDomElementClassName('sortable')); + } + for (var i = 0, len = childFormElements.length; i < len; ++i) { + childList.append(_renderNestedSortableListItem(childFormElements[i])); + } + } + + if (childList) { + listItem.append(childList); + } + return listItem; + }; + + /** + * @private + * + * @return void + * @publish view/stage/abstract/dnd/start + * @publish view/stage/abstract/dnd/stop + * @publish view/stage/abstract/dnd/change + * @publish view/stage/abstract/dnd/update + */ + function _addSortableEvents() { + $('ol.' + getHelper().getDomElementClassName('sortable'), _stageDomElement).nestedSortable({ + forcePlaceholderSize: true, + handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + helper: 'clone', + items: 'li:not(' + getHelper().getDomElementDataAttribute('noSorting', 'bracesWithKey') + ')', + opacity: .6, + revert: 250, + delay: 200, + tolerance: 'pointer', + toleranceElement: '> div', + + start: function(e, o) { + getPublisherSubscriber().publish('view/stage/abstract/dnd/start', [$(o.item), $(o.placeholder)]); + }, + stop: function(e, o) { + getPublisherSubscriber().publish('view/stage/abstract/dnd/stop', [ + getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)) + ]); + }, + change: function(e, o) { + var enclosingCompositeFormElement, parentFormElementIdentifierPath; + + parentFormElementIdentifierPath = getAbstractViewParentFormElementIdentifierPathWithinDomElement($(o.placeholder)); + if (parentFormElementIdentifierPath) { + enclosingCompositeFormElement = getFormEditorApp() + .findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); + } + getPublisherSubscriber().publish('view/stage/abstract/dnd/change', [ + $(o.placeholder), + parentFormElementIdentifierPath, enclosingCompositeFormElement + ]); + }, + update: function(e, o) { + var nextFormElementIdentifierPath, movedFormElement, movedFormElementIdentifierPath, parentFormElementIdentifierPath, previousFormElementIdentifierPath; + + movedFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)); + previousFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'prev'); + nextFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'next'); + + getPublisherSubscriber().publish('view/stage/abstract/dnd/update', [ + $(o.item), + movedFormElementIdentifierPath, + previousFormElementIdentifierPath, + nextFormElementIdentifierPath + ]); + } + }); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStageDomElement() { + return _stageDomElement; + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1479037151 + */ + function buildTitleByFormElement(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getRootFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479037151); + + return $('<span></span>') + .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))); + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStageHeadline(title) { + if (getUtility().isUndefinedOrNull(title)) { + title = buildTitleByFormElement(); + } + + $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title); + }; + + /** + * @public + * + * @return object + */ + function getStagePanelDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('stagePanel')); + }; + + /** + * @public + * + * @return void + */ + function renderPagination() { + var pageCount; + + pageCount = getRootFormElement().get('renderables').length; + + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); + + if (getFormEditorApp().getCurrentlySelectedPageIndex() === 0) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); + } + + if (pageCount === 1 || getFormEditorApp().getCurrentlySelectedPageIndex() === (pageCount - 1)) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); + } + + $(getHelper().getDomElementDataIdentifierSelector('paginationTitle')).text( + getFormElementDefinition(getRootFormElement(), 'paginationTitle') + .replace('{0}', getFormEditorApp().getCurrentlySelectedPageIndex() + 1) + .replace('{1}', pageCount) + ); + }; + + /** + * @public + * + * @return void + */ + function renderUndoRedo() { + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + + if (getFormEditorApp().getCurrentApplicationStatePosition() + 1 >= getFormEditorApp().getCurrentApplicationStates()) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } + if (getFormEditorApp().getCurrentApplicationStatePosition() === 0) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + } + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAllFormElementDomElements() { + return $( getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + _stageDomElement + ); + }; + + /* ************************************************************* + * Abstract stage + * ************************************************************/ + + /** + * @public + * + * @param int + * @return object + * @throws 1478721208 + */ + function renderFormDefinitionPageAsSortableList(pageIndex) { + assert( + 'number' === $.type(pageIndex), + 'Invalid parameter "pageIndex"', + 1478721208 + ); + + return $('<ol></ol>') + .append(_renderNestedSortableListItem(getRootFormElement().get('renderables')[pageIndex])); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewParentFormElementWithinDomElement(element) { + return $(element) + .parent() + .closest('li') + .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewParentFormElementIdentifierPathWithinDomElement(element) { + return getAbstractViewParentFormElementWithinDomElement(element) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewFormElementWithinDomElement(element) { + return $(element) + .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewFormElementIdentifierPathWithinDomElement(element) { + return getAbstractViewFormElementWithinDomElement($(element)) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @private + * + * @param object + * @param string + * @return string + */ + function getAbstractViewSiblingFormElementIdentifierPathWithinDomElement(element, position) { + var formElementIdentifierPath; + + if (getUtility().isUndefinedOrNull(position)) { + position = 'prev'; + } + formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement(element); + element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); + return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) + .first() + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param string|object + * @return object + */ + function getAbstractViewFormElementDomElement(formElement) { + var formElementIdentifierPath; + + if ('string' === $.type(formElement)) { + formElementIdentifierPath = formElement; + } else { + if (getUtility().isUndefinedOrNull(formElement)) { + formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); + } else { + formElementIdentifierPath = formElement.get('__identifierPath'); + } + } + return $(getHelper() + .getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _stageDomElement); + }; + + /** + * @public + * + * @return void + */ + function removeAllStageToolbars() { + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), _stageDomElement).off().empty().remove(); + }; + + /** + * @public + * + * @param object + * @return object + * @publish view/insertElements/perform/after + * @publish view/insertElements/perform/inside + * @throws 1479035778 + */ + function createAbstractViewFormElementToolbar(formElement) { + var formElementTypeDefinition, template; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035778); + + formElementTypeDefinition = getFormElementDefinition(formElement); + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return $(); + } + + template = getHelper().getTemplate('FormElement-_ElementToolbar').clone(); + if (!template.length) { + return $(); + } + + template = $($(template.html())); + + getHelper().getTemplatePropertyDomElement('_type', template).text(formElement.get('type')); + getHelper().getTemplatePropertyDomElement('_identifier', template).text(formElement.get('identifier')); + + if (formElementTypeDefinition['_isCompositeFormElement']) { + getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template)); + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonAfter'), template).on('click', function(e) { + getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', ['view/insertElements/perform/after']); + }); + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) { + getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', ['view/insertElements/perform/inside']); + }); + } else { + getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template)); + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) { + getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', ['view/insertElements/perform/after']); + }); + } + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarRemoveElement'), template).on('click', function(e) { + getViewModel().showRemoveFormElementModal(); + }); + + return template; + }; + + /** + * @public + * + * @param object + * @param object + * @param bool + * @return void + */ + function createAndAddAbstractViewFormElementToolbar(selectedFormElementDomElement, formElement, useFadeEffect) { + var toolbar; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + if (useFadeEffect) { + createAbstractViewFormElementToolbar(formElement).fadeOut(0, function() { + selectedFormElementDomElement.prepend($(this)); + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), selectedFormElementDomElement).fadeIn('fast'); + }); + } else { + selectedFormElementDomElement.prepend(createAbstractViewFormElementToolbar(formElement)); + } + + }; + + /** + * @public + * + * @param int + * @param function + * @return void + * @publish view/stage/dnd/stop + * @publish view/stage/element/clicked + * @throws 1478169511 + */ + function renderAbstractStageArea(pageIndex, callback) { + if (getUtility().isUndefinedOrNull(pageIndex)) { + pageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + } + _stageDomElement.off().empty().append(renderFormDefinitionPageAsSortableList(pageIndex)); + + _stageDomElement.on("click", function(e) { + var formElementIdentifierPath; + + formElementIdentifierPath = $(e.target) + .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + if ( + getUtility().isUndefinedOrNull(formElementIdentifierPath) + || !getUtility().isNonEmptyString(formElementIdentifierPath) + ) { + return; + } + + getPublisherSubscriber().publish('view/stage/element/clicked', [formElementIdentifierPath]); + }); + + if (_configuration['isSortable']) { + _addSortableEvents(); + } + + if ('function' === $.type(callback)) { + callback(); + } + }; + + + /* ************************************************************* + * Preview stage + * ************************************************************/ + + /** + * @public + * + * @param string html + * @return void + * @throws 1475424409 + */ + function renderPreviewStageArea(html) { + assert(getUtility().isNonEmptyString(html), 'Invalid parameter "html"', 1475424409); + + _stageDomElement.off().empty().html(html); + + $(':input', _stageDomElement).prop('disabled', 'disabled').on('click dblclick select focus keydown keypress keyup mousedown mouseup', function(e) { + return e.preventDefault(); + }); + + $('form', _stageDomElement).submit(function(e) { + return e.preventDefault(); + }); + + getAllFormElementDomElements().each(function(i, element) { + var formElement, metaLabel; + + formElement = getFormEditorApp() + .getFormElementByIdentifierPath($(this).data('elementIdentifierPath')); + + if ( + !getFormElementDefinition(formElement, '_isTopLevelFormElement') + && getFormElementDefinition(formElement, '_isCompositeFormElement') + ) { + $(this).tooltip({ + title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', + placement : 'rigth' + }); + } else if ( + !getFormElementDefinition(formElement, '_isTopLevelFormElement') + && !getFormElementDefinition(formElement, '_isCompositeFormElement') + ) { + $(this).tooltip({ + title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', + placement : 'left' + }); + } + + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + $(this).addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); + } + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + $(this).addClass(getHelper().getDomElementClassName('formElementIsComposit')); + } + }); + + }; + + /* ************************************************************* + * Template rendering + * ************************************************************/ + + /** + * @public + * + * @param object + * @param template + * @param function + * @return void + */ + function eachTemplateProperty(formElement, template, callback) { + $(getHelper().getDomElementDataAttribute('templateProperty', 'bracesWithKey'), template).each(function(i, element) { + var propertyPath, propertyValue; + + propertyPath = $(element).attr(getHelper().getDomElementDataAttribute('templateProperty')); + propertyValue = formElement.get(propertyPath); + + if ('function' === $.type(callback)) { + callback(propertyPath, propertyValue, element); + } + }); + }; + + /** + * @private + * + * @return object + * @return object + * @return void + */ + function renderCheckboxTemplate(formElement, template) { + renderSimpleTemplateWithValidators(formElement, template); + + eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { + if ( + ('boolean' === $.type(propertyValue) && propertyValue) + || propertyValue === 'true' + || propertyValue === 1 + || propertyValue === "1" + ) { + $(domElement).addClass(getHelper().getDomElementClassName('noNesting')); + } + }); + }; + + /** + * @public + * + * @return object + * @return object + * @return void + * @throws 1479035696 + */ + function renderSimpleTemplate(formElement, template) { + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035696); + + eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { + _setTemplateTextContent(domElement, propertyValue); + }); + + Icons.getIcon( + getFormElementDefinition(formElement, 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + $(getHelper().getDomElementDataIdentifierSelector('formElementIcon'), template) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); + }); + + getHelper() + .getTemplatePropertyDomElement('_type', template) + .append(formElement.get('type')); + getHelper() + .getTemplatePropertyDomElement('_identifier', template) + .append(formElement.get('identifier')); + }; + + /** + * @public + * + * @return object + * @return object + * @return void + * @throws 1479035674 + */ + function renderSimpleTemplateWithValidators(formElement, template) { + var validators, validatorsCountWithoutRequired, validatorsTemplateContent; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035674); + + renderSimpleTemplate(formElement, template); + + validatorsTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), + $(template) + ).clone(); + + $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)).empty(); + validators = formElement.get('validators'); + + if ('array' === $.type(validators)) { + validatorsCountWithoutRequired = 0; + if (validators.length > 0) { + for (var i = 0, len = validators.length; i < len; ++i) { + var collectionElementConfiguration, rowTemplate; + + if ('NotEmpty' === validators[i]['identifier']) { + getHelper() + .getTemplatePropertyDomElement('_required', template) + .text('*'); + continue; + } + validatorsCountWithoutRequired++; + + collectionElementConfiguration = getFormEditorApp() + .getFormEditorDefinition('validators', validators[i]['identifier']); + rowTemplate = $($(validatorsTemplateContent).clone()); + + getHelper() + .getTemplatePropertyDomElement('_label', rowTemplate) + .append(collectionElementConfiguration['label']); + $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)) + .append(rowTemplate.html()); + } + + if (validatorsCountWithoutRequired > 0) { + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('iconValidator'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + $(getHelper().getDomElementDataIdentifierSelector('validatorIcon'), $(template)) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); + }); + } + } + } + }; + + /** + * @public + * + * @return object + * @return object + * @return void + */ + function renderSelectTemplates(formElement, template) { + var appendMultiValue, defaultValue, multiValueTemplateContent, propertyPath, propertyValue; + + multiValueTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), + $(template) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); + + renderSimpleTemplateWithValidators(formElement, template); + + propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .attr(getHelper().getDomElementDataAttribute('templateProperty')); + + propertyValue = formElement.get(propertyPath); + + appendMultiValue = function(label, value, defaultValue) { + var isPreselected, rowTemplate; + + isPreselected = false; + rowTemplate = $($(multiValueTemplateContent).clone()); + + for (var defaultValueKey in defaultValue) { + if (!defaultValue.hasOwnProperty(defaultValueKey)) { + continue; + } + if (defaultValue[defaultValueKey] === value) { + isPreselected = true; + break; + } + } + + getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label); + + if (isPreselected) { + getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass( + getHelper().getDomElementClassName('selected') + ); + } + + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .append(rowTemplate.html()); + }; + + defaultValue = formElement.get('defaultValue'); + + if (getFormEditorApp().getUtility().isUndefinedOrNull(defaultValue)) { + defaultValue = {}; + } else if ('string' === $.type(defaultValue)) { + defaultValue = {0: defaultValue}; + } + + if ('object' === $.type(propertyValue)) { + for (var propertyValueKey in propertyValue) { + if (!propertyValue.hasOwnProperty(propertyValueKey)) { + continue; + } + appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue); + } + } else if ('array' === $.type(propertyValue)) { + for (var i = 0, len = propertyValue.length; i < len; ++i) { + appendMultiValue(propertyValue[i]['_label'], propertyValue[i]['_value'], defaultValue); + } + } + }; + + /** + * @public + * + * @return object + * @return object + * @return void + */ + function renderFileUploadTemplates(formElement, template) { + var appendMultiValue, multiValueTemplateContent, propertyPath, propertyValue; + + multiValueTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), + $(template) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); + + renderSimpleTemplateWithValidators(formElement, template); + + propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .attr(getHelper().getDomElementDataAttribute('templateProperty')); + propertyValue = formElement.get(propertyPath); + + appendMultiValue = function(value) { + var rowTemplate; + + rowTemplate = $($(multiValueTemplateContent).clone()); + + getHelper().getTemplatePropertyDomElement('_value', rowTemplate).append(value); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .append(rowTemplate.html()); + }; + + if ('object' === $.type(propertyValue)) { + for (var propertyValueKey in propertyValue) { + if (!propertyValue.hasOwnProperty(propertyValueKey)) { + continue; + } + appendMultiValue(propertyValue[propertyValueKey]); + } + } else if ('array' === $.type(propertyValue)) { + for (var i = 0, len = propertyValue.length; i < len; ++i) { + appendMultiValue(propertyValue[i]); + } + } + }; + + /** + * @public + * + * @param object + * @param object + * @param object + * @return this + * @throws 1478992119 + */ + function bootstrap(formEditorApp, appendToDomElement, configuration) { + _formEditorApp = formEditorApp; + assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478992119); + + _stageDomElement = $(appendToDomElement); + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + createAndAddAbstractViewFormElementToolbar: createAndAddAbstractViewFormElementToolbar, + createAbstractViewFormElementToolbar: createAbstractViewFormElementToolbar, + eachTemplateProperty: eachTemplateProperty, + getAbstractViewFormElementDomElement: getAbstractViewFormElementDomElement, + getAbstractViewFormElementWithinDomElement: getAbstractViewFormElementWithinDomElement, + getAbstractViewFormElementIdentifierPathWithinDomElement: getAbstractViewFormElementIdentifierPathWithinDomElement, + getAbstractViewParentFormElementWithinDomElement: getAbstractViewParentFormElementWithinDomElement, + getAbstractViewParentFormElementIdentifierPathWithinDomElement: getAbstractViewParentFormElementIdentifierPathWithinDomElement, + getAbstractViewSiblingFormElementIdentifierPathWithinDomElement: getAbstractViewSiblingFormElementIdentifierPathWithinDomElement, + getAllFormElementDomElements: getAllFormElementDomElements, + getStageDomElement: getStageDomElement, + getStagePanelDomElement: getStagePanelDomElement, + removeAllStageToolbars: removeAllStageToolbars, + renderAbstractStageArea: renderAbstractStageArea, + renderCheckboxTemplate: renderCheckboxTemplate, + renderFileUploadTemplates: renderFileUploadTemplates, + renderFormDefinitionPageAsSortableList: renderFormDefinitionPageAsSortableList, + renderPagination: renderPagination, + renderPreviewStageArea: renderPreviewStageArea, + renderSelectTemplates: renderSelectTemplates, + renderSimpleTemplate: renderSimpleTemplate, + renderSimpleTemplateWithValidators: renderSimpleTemplateWithValidators, + renderUndoRedo: renderUndoRedo, + setStageHeadline: setStageHeadline + }; + })($, Helper, Icons); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..00d890ff3b5a432ee13372d1ee1645dbbca42248 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js @@ -0,0 +1,648 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/TreeComponent + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' + ], function($, Helper, Icons) { + 'use strict'; + + return (function($, Helper, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _expanderStates = {}; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + collapsed: 'mjs-nestedSortable-collapsed', + expanded: 'mjs-nestedSortable-expanded', + hasChildren: 't3-form-element-has-children', + sortable: 'sortable', + svgLinkWrapper: 'svg-wrapper', + noNesting: 'mjs-nestedSortable-no-nesting' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type' + }, + domElementDataAttributeValues: { + collapse: 'actions-pagetree-collapse', + expander: 'treeExpander', + title: 'treeTitle' + }, + isSortable: true, + svgLink: { + height: 15, + paths: { + angle: 'M0 0 V21 H15', + vertical: 'M0 0 V21 H0', + hidden: 'M0 0 V0 H0' + }, + width: 15 + } + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _treeDomElement = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @return object + */ + function _getLinkSvg(type) { + return $('<span class="' + getHelper().getDomElementClassName('svgLinkWrapper') + '">' + + '<svg version="1.1" width="' + _configuration['svgLink']['width'] + '" height="' + _configuration['svgLink']['height'] + '">' + + '<path class="link" d="' + _configuration['svgLink']['paths'][type] + '">' + + '</svg>' + + '</span>'); + }; + + /** + * @private + * + * @param object + * @return object + * @publish view/tree/render/listItemAdded + * @throws 1478715704 + */ + function _renderNestedSortableListItem(formElement) { + var childFormElements, childList, expanderItem, isLastFormElementWithinParentFormElement, listItem, listItemContent, searchElement; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478715704); + + isLastFormElementWithinParentFormElement = false; + if (formElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(formElement).get('__identifierPath')) { + isLastFormElementWithinParentFormElement = true; + } + + listItem = $('<li></li>'); + if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('noNesting')); + } + + listItemContent = $('<div></div>') + .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) + .append( + $('<span></span>') + .attr(getHelper().getDomElementDataAttribute('identifier'), getHelper().getDomElementDataAttributeValue('title')) + .html(buildTitleByFormElement(formElement)) + ); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); + } + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); + } + + expanderItem = $('<span></span>').attr('data-identifier', getHelper().getDomElementDataAttributeValue('expander')); + listItemContent.prepend(expanderItem); + + Icons.getIcon(getFormElementDefinition(formElement, 'iconIdentifier'), Icons.sizes.small, null, Icons.states.default).done(function(icon) { + expanderItem.after( + $(icon).addClass(getHelper().getDomElementClassName('icon')) + .tooltip({ + title: 'identifier: ' + formElement.get('identifier'), + placement: 'right' + }) + ); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + if (formElement.get('renderables') && formElement.get('renderables').length > 0) { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('collapse'), Icons.sizes.small).done(function(icon) { + expanderItem.before(_getLinkSvg('angle')).html($(icon)); + listItem.addClass(getHelper().getDomElementClassName('hasChildren')); + }); + } else { + expanderItem.before(_getLinkSvg('angle')).remove(); + } + } else { + listItemContent.prepend(_getLinkSvg('angle')); + expanderItem.remove(); + } + + searchElement = formElement.get('__parentRenderable'); + while (searchElement) { + if (searchElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { + break; + } + + if (searchElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(searchElement).get('__identifierPath')) { + listItemContent.prepend(_getLinkSvg('hidden')); + } else { + listItemContent.prepend(_getLinkSvg('vertical')); + } + searchElement = searchElement.get('__parentRenderable'); + } + }); + listItem.append(listItemContent); + + getPublisherSubscriber().publish('view/tree/render/listItemAdded', [listItem, formElement]); + childFormElements = formElement.get('renderables'); + childList = null; + if ('array' === $.type(childFormElements)) { + childList = $('<ol></ol>'); + for (var i = 0, len = childFormElements.length; i < len; ++i) { + childList.append(_renderNestedSortableListItem(childFormElements[i])); + } + } + + if (childList) { + listItem.append(childList); + } + return listItem; + }; + + /** + * @private + * + * @return void + * @publish view/tree/dnd/stop + * @publish view/tree/dnd/change + * @publish view/tree/dnd/update + */ + function _addSortableEvents() { + $('ol.' + getHelper().getDomElementClassName('sortable'), _treeDomElement).nestedSortable({ + forcePlaceholderSize: true, + protectRoot: true, + isTree: true, + handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + helper: 'clone', + items: 'li', + opacity: .6, + revert: 250, + delay: 200, + tolerance: 'pointer', + toleranceElement: '> div', + + stop: function(e, o) { + getPublisherSubscriber().publish('view/tree/dnd/stop', [getTreeNodeIdentifierPathWithinDomElement($(o.item))]); + }, + change: function(e, o) { + var enclosingCompositeFormElement, parentFormElementIdentifierPath; + + parentFormElementIdentifierPath = getParentTreeNodeIdentifierPathWithinDomElement($(o.placeholder)); + if (parentFormElementIdentifierPath) { + enclosingCompositeFormElement = getFormEditorApp().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); + } + getPublisherSubscriber().publish('view/tree/dnd/change', [$(o.placeholder), parentFormElementIdentifierPath, enclosingCompositeFormElement]); + }, + update: function(e, o) { + var nextFormElementIdentifierPath, movedFormElementIdentifierPath, previousFormElementIdentifierPath; + + movedFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(o.item)); + previousFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'prev'); + nextFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'next'); + + getPublisherSubscriber().publish('view/tree/dnd/update', [$(o.item), movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath]); + } + }); + }; + + /** + * @private + * + * @return void + */ + function _saveExpanderStates() { + var addStates; + + addStates = function(formElement) { + var childFormElements, treeNode; + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + treeNode = getTreeNode(formElement); + if (treeNode.length) { + if (treeNode.closest('li').hasClass(getHelper().getDomElementClassName('expanded'))) { + _expanderStates[formElement.get('__identifierPath')] = true; + } else { + _expanderStates[formElement.get('__identifierPath')] = false; + } + } + + if (getUtility().isUndefinedOrNull(_expanderStates[formElement.get('__identifierPath')])) { + _expanderStates[formElement.get('__identifierPath')] = true; + } + } + + childFormElements = formElement.get('renderables'); + if ('array' === $.type(childFormElements)) { + for (var i = 0, len = childFormElements.length; i < len; ++i) { + addStates(childFormElements[i]); + } + } + }; + addStates(getRootFormElement()); + + for (var identifierPath in _expanderStates) { + if (!_expanderStates.hasOwnProperty(identifierPath)) { + continue; + } + try { + getFormEditorApp().getFormElementByIdentifierPath(identifierPath); + } catch(error) { + delete _expanderStates[identifierPath]; + } + } + }; + + /** + * @private + * + * @return void + */ + function _loadExpanderStates() { + for (var identifierPath in _expanderStates) { + var treeNode; + + if (!_expanderStates.hasOwnProperty(identifierPath)) { + continue; + } + treeNode = getTreeNode(identifierPath); + if (treeNode.length) { + if (_expanderStates[identifierPath]) { + treeNode.closest('li') + .removeClass(getHelper().getDomElementClassName('collapsed')) + .addClass(getHelper().getDomElementClassName('expanded')); + } else { + treeNode.closest('li') + .addClass(getHelper().getDomElementClassName('collapsed')) + .removeClass(getHelper().getDomElementClassName('expanded')); + } + } + } + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @param object + * @return object + * @throws 1478721208 + */ + function renderCompositeFormElementChildsAsSortableList(formElement) { + var elementList; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478721208); + + elementList = $('<ol></ol>').addClass(getHelper().getDomElementClassName('sortable')); + if ('array' === $.type(formElement.get('renderables'))) { + for (var i = 0, len = formElement.get('renderables').length; i < len; ++i) { + elementList.append(_renderNestedSortableListItem(formElement.get('renderables')[i])); + } + } + return elementList; + }; + + /** + * @public + * + * @return void + * @param object + * @publish view/tree/node/clicked + */ + function renew(formElement) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(formElement)) { + formElement = getRootFormElement(); + } + _saveExpanderStates(); + _treeDomElement.off().empty().append(renderCompositeFormElementChildsAsSortableList(formElement)); + + _treeDomElement.on("click", function(e) { + var formElementIdentifierPath; + + formElementIdentifierPath = $(e.target) + .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + if (getUtility().isUndefinedOrNull(formElementIdentifierPath) || !getUtility().isNonEmptyString(formElementIdentifierPath)) { + return; + } + getPublisherSubscriber().publish('view/tree/node/clicked', [formElementIdentifierPath]); + }); + + $(getHelper().getDomElementDataIdentifierSelector('expander'), _treeDomElement).on('click', function() { + $(this).closest('li').toggleClass(getHelper().getDomElementClassName('collapsed')).toggleClass(getHelper().getDomElementClassName('expanded')); + }); + + if (_configuration['isSortable']) { + _addSortableEvents(); + } + _loadExpanderStates(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAllTreeNodes() { + return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), _treeDomElement); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getTreeNodeWithinDomElement(element) { + return $(element).find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getTreeNodeIdentifierPathWithinDomElement(element) { + return getTreeNodeWithinDomElement($(element)).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getParentTreeNodeWithinDomElement(element) { + return $(element).parent().closest('li').find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getParentTreeNodeIdentifierPathWithinDomElement(element) { + return getParentTreeNodeWithinDomElement(element).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @private + * + * @param object + * @param string + * @return string + */ + function getSiblingTreeNodeIdentifierPathWithinDomElement(element, position) { + var formElementIdentifierPath; + + if (getUtility().isUndefinedOrNull(position)) { + position = 'prev'; + } + formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement(element); + element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); + return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) + .first() + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param string + * @param object + * @return void + */ + function setTreeNodeTitle(title, formElement) { + if (getUtility().isUndefinedOrNull(title)) { + title = buildTitleByFormElement(formElement); + } + + $(getHelper().getDomElementDataIdentifierSelector('title'), getTreeNode(formElement)).html(title); + }; + + /** + * @public + * + * @param string|object + * @return object + */ + function getTreeNode(formElement) { + var formElementIdentifierPath; + + if ('string' === $.type(formElement)) { + formElementIdentifierPath = formElement; + } else { + if (getUtility().isUndefinedOrNull(formElement)) { + formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); + } else { + formElementIdentifierPath = formElement.get('__identifierPath'); + } + } + return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _treeDomElement); + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1478719287 + */ + function buildTitleByFormElement(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478719287); + + return $('<span></span>') + .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))) + .append($('<small></small>').text("(" + getFormElementDefinition(formElement, 'label') + ")")); + }; + + /** + * @public + * + * @return object + */ + function getTreeDomElement() { + return _treeDomElement; + }; + + /** + * @public + * + * @param object + * @param object + * @param object + * @return this + * @throws 1478714814 + */ + function bootstrap(formEditorApp, appendToDomElement, configuration) { + _formEditorApp = formEditorApp; + assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478714814); + + _treeDomElement = $(appendToDomElement); + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + getAllTreeNodes: getAllTreeNodes, + getParentTreeNodeWithinDomElement: getParentTreeNodeWithinDomElement, + getParentTreeNodeIdentifierPathWithinDomElement: getParentTreeNodeIdentifierPathWithinDomElement, + getSiblingTreeNodeIdentifierPathWithinDomElement: getSiblingTreeNodeIdentifierPathWithinDomElement, + getTreeDomElement: getTreeDomElement, + getTreeNode: getTreeNode, + getTreeNodeWithinDomElement: getTreeNodeWithinDomElement, + getTreeNodeIdentifierPathWithinDomElement: getTreeNodeIdentifierPathWithinDomElement, + renderCompositeFormElementChildsAsSortableList: renderCompositeFormElementChildsAsSortableList, + renew: renew, + setTreeNodeTitle: setTreeNodeTitle + }; + })($, Helper, Icons); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js new file mode 100644 index 0000000000000000000000000000000000000000..f4fd8e48209ad7c440f88153f02596689088a2ca --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js @@ -0,0 +1,1697 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormEditor/ViewModel + */ +define(['jquery', + 'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/StageComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification' + ], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { + 'use strict'; + + return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { + + /** + * @private + * + * @var object + */ + var _configuration = { + domElementClassNames: { + formElementIsComposit: 't3-form-element-composit', + formElementIsTopLevel: 't3-form-element-toplevel', + hasError: 'has-error', + headerButtonBar: 'module-docheader-bar-column-left', + selectedCompositFormElement: 't3-form-form-composit-element-selected', + selectedFormElement: 't3-form-form-element-selected', + selectedRootFormElement: 't3-form-root-element-selected', + selectedStagePanel: 't3-form-form-stage-selected', + sortableHover: 'sortable-hover', + stageViewModeAbstract: 't3-form-stage-viewmode-abstract', + stageViewModePreview: 't3-form-stage-viewmode-preview', + validationErrors: 't3-form-validation-errors', + validationChildHasErrors: 't3-form-validation-child-has-error' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type' + }, + domElementDataAttributeValues: { + buttonHeaderClose: 'closeButton', + buttonHeaderNewPage: 'headerNewPage', + buttonHeaderPaginationNext: 'buttonPaginationNext', + buttonHeaderPaginationPrevious: 'buttonPaginationPrevious', + buttonHeaderRedo: 'redoButton', + buttonHeaderSave: 'saveButton', + buttonHeaderUndo: 'undoButton', + buttonHeaderViewModeAbstract: 'buttonViewModeAbstract', + buttonHeaderViewModePreview: 'buttonViewModePreview', + buttonStageNewElementBottom: 'stageNewElementBottom', + buttonStructureNewPage: 'treeNewPageBottom', + iconMailform: 'content-elements-mailform', + iconSave: 'actions-document-save', + iconSaveSpinner: 'spinner-circle-dark', + inspectorSection: 'inspectorSection', + moduleLoadingIndicator: 'moduleLoadingIndicator', + moduleWrapper: 'moduleWrapper', + stageArea: 'stageArea', + stageContainer: 'stageContainer', + stageNewElementRow: 'stageNewElementRow', + stagePanelHeading: 'panelHeading', + stageSection: 'stageSection', + structure: 'structure-element', + structureSection: 'structureSection', + structureRootContainer: 'treeRootContainer', + structureRootElement: 'treeRootElement' + }, + panels: { + structure: { + width: 300 + }, + stage: { + marginLeft: 300, + marginRight: 325, + marginLeftCollapsed: 0, + marginRightCollapsed: -25 + }, + inspector: { + width: 350 + } + } + }; + + /** + * @private + * + * @var bool + */ + var _previewMode = false; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _structureComponent = null; + + /** + * @private + * + * @var object + */ + var _modalsComponent = null; + + /** + * @private + * + * @var object + */ + var _inspectorsComponent = null; + + /** + * @private + * + * @var object + */ + var _stageComponent = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @return void + */ + function _addPropertyValidators() { + getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) { + if (formElement.get(propertyPath) === '') { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) { + if (!$.isNumeric(formElement.get(propertyPath))) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) { + if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) { + if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) { + var match, regex; + regex = /\{([a-z0-9-_]+)?\}/gi; + match = regex.exec(formElement.get(propertyPath)); + if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) { + var match, regex; + regex = /^\{([a-z0-9-_]+)?\}$/i; + match = regex.exec(formElement.get(propertyPath)); + if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; + } + }); + }; + + /** + * @private + * + * @param object additionalViewModelModules + * @return void + * @publish view/ready + * @throws 1475425785 + */ + function _loadAdditionalModules(additionalViewModelModules) { + var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules; + + if ('array' !== $.type(additionalViewModelModules)) { + return; + } + additionalViewModelModulesLength = additionalViewModelModules.length; + + if (additionalViewModelModulesLength > 0) { + loadedAdditionalViewModelModules = 0; + for (var i = 0; i < additionalViewModelModulesLength; ++i) { + require([additionalViewModelModules[i]], function (additionalViewModelModule) { + assert( + 'function' === $.type(additionalViewModelModule.bootstrap), + 'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"', + 1475425785 + ); + additionalViewModelModule.bootstrap(getFormEditorApp()); + + loadedAdditionalViewModelModules++; + if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) { + getPublisherSubscriber().publish('view/ready'); + } + }); + } + } else { + getPublisherSubscriber().publish('view/ready'); + } + }; + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478268639 + */ + function _structureComponentSetup() { + assert( + 'function' === $.type(TreeComponent.bootstrap), + 'The structure component does not implement the method "bootstrap"', + 1478268639 + ); + + _structureComponent = TreeComponent.bootstrap( + getFormEditorApp(), + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structure') + ])) + ); + + $( getHelper().getDomElementDataIdentifierSelector('iconMailform'), + $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')) + ).tooltip({ + title: 'identifier: ' + getRootFormElement().get('identifier'), + placement: 'right' + }); + }; + + /** + * @private + * + * @return void + * @throws 1478895106 + */ + function _modalsComponentSetup() { + assert( + 'function' === $.type(ModalsComponent.bootstrap), + 'The modals component does not implement the method "bootstrap"', + 1478895106 + ); + _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478895106 + */ + function _inspectorsComponentSetup() { + assert( + 'function' === $.type(InspectorComponent.bootstrap), + 'The inspector component does not implement the method "bootstrap"', + 1478895106 + ); + _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478986610 + */ + function _stageComponentSetup() { + assert( + 'function' === $.type(InspectorComponent.bootstrap), + 'The stage component does not implement the method "bootstrap"', + 1478986610 + ); + _stageComponent = StageComponent.bootstrap( + getFormEditorApp(), + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('stageArea') + ])) + ); + + getStage().getStagePanelDomElement().on("click", function(e) { + if ( + $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stagePanelHeading') + || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageSection') + || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageArea') + ) { + selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex()); + } + getPublisherSubscriber().publish('view/stage/panel/clicked', []); + }); + }; + + /** + * @private + * + * @return void + * @publish view/header/button/save/clicked + * @publish view/stage/abstract/button/newElement/clicked + * @publish view/header/button/newPage/clicked + * @publish view/structure/button/newPage/clicked + * @publish view/header/button/close/clicked + */ + function _buttonsSetup() { + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) { + getPublisherSubscriber().publish('view/header/button/save/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) { + getPublisherSubscriber().publish('view/stage/abstract/button/newElement/clicked', ['view/insertElements/perform/bottom']); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) { + getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) { + getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) { + if (!getFormEditorApp().getUnsavedContent()) { + return; + } + e.preventDefault(); + getPublisherSubscriber().publish('view/header/button/close/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) { + getPublisherSubscriber().publish('view/undoButton/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) { + getPublisherSubscriber().publish('view/redoButton/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) { + getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) { + getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) { + getPublisherSubscriber().publish('view/structure/root/selected'); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) { + getPublisherSubscriber().publish('view/paginationNext/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) { + getPublisherSubscriber().publish('view/paginationPrevious/clicked', []); + }); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @public + * + * @param object formElement + * @param string formElementDefinitionKey + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @public + * + * @return object (derefernced) + */ + function getConfiguration() { + return $.extend(true, {}, _configuration); + }; + + /** + * @public + * + * @return int + */ + function getPreviewMode() { + return _previewMode; + }; + + /** + * @public + * + * @param bool + * @return void + */ + function setPreviewMode(previewMode) { + _previewMode = !!previewMode; + }; + + /* ************************************************************* + * Structure + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStructure() { + return _structureComponent; + }; + + /** + * @public + * + * @return void + * @publish view/structure/renew/postProcess + */ + function renewStructure() { + getStructure().renew(); + getPublisherSubscriber().publish('view/structure/renew/postProcess'); + }; + + /** + * @public + * + * @param object + * @return void + */ + function addStructureSelection(formElement) { + getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function removeStructureSelection(formElement) { + getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @return void + */ + function removeAllStructureSelections() { + $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement()) + .removeClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @return object + */ + function getStructureRootElement() { + return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootElement') + ])); + }; + + /** + * @public + * + * @return void + */ + function removeStructureRootElementSelection() { + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootContainer') + ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement')); + }; + + /** + * @public + * + * @return void + */ + function addStructureRootElementSelection() { + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootContainer') + ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement')); + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStructureRootElementTitle(title) { + if (getUtility().isUndefinedOrNull(title)) { + title = $('<span></span>') + .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier'))) + .html(); + } + getStructureRootElement().text(title); + }; + + /** + * @public + * + * @return void + */ + function addStructureValidationResults() { + var validationResults; + + getStructure().getAllTreeNodes() + .removeClass(getHelper().getDomElementClassName('validationErrors')) + .removeClass(getHelper().getDomElementClassName('validationChildHasErrors')); + + removeElementValidationErrorClass(getStructureRootElement()); + + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, pathParts, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + if (i === 0) { + setElementValidationErrorClass(getStructureRootElement()); + } else { + validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']); + setElementValidationErrorClass(validationElement); + + pathParts = validationResults[i]['formElementIdentifierPath'].split('/'); + while(pathParts.pop()) { + validationElement = getStructure().getTreeNode(pathParts.join('/')); + if ('object' === $.type(validationElement)) { + setElementValidationErrorClass(validationElement, 'validationChildHasErrors'); + } + } + } + } + } + }; + + /* ************************************************************* + * Modals + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getModals() { + return _modalsComponent + }; + + /** + * @public + * + * @param object formElement + * @return void + */ + function showRemoveFormElementModal(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getModals().showRemoveFormElementModal(formElement); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return void + */ + function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement); + }; + + /** + * @public + * + * @return void + */ + function showCloseConfirmationModal() { + getModals().showCloseConfirmationModal(); + }; + + /** + * @public + * + * @param string targetEvent + * @return void + */ + function showInsertElementsModal(targetEvent) { + getModals().showInsertElementsModal(targetEvent); + }; + + /** + * @public + * + * @param string targetEvent + * @return void + */ + function showInsertPagesModal(targetEvent) { + getModals().showInsertPagesModal(targetEvent); + }; + + /** + * @public + * + * @param bool + * @return void + */ + function showValidationErrorsModal() { + var validationResults; + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + + getModals().showValidationErrorsModal(validationResults); + }; + + /* ************************************************************* + * Inspector + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getInspector() { + return _inspectorsComponent + }; + + /** + * @public + * + * @param object + * @param bool + * @return void + */ + function renderInspectorEditors(formElement, useFadeEffect) { + var render; + if (getUtility().isUndefinedOrNull(useFadeEffect)) { + useFadeEffect = true; + } + + /** + * @private + * + * @param function + * @return void + */ + render = function(callback) { + getInspector().renderEditors(formElement, callback); + }; + + if (!!useFadeEffect) { + getInspector().getInspectorDomElement().fadeOut('fast', function() { + render(function() { + getInspector().getInspectorDomElement().fadeIn('fast'); + }); + }); + } else { + render(); + } + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) { + getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier); + }; + + /** + * @public + * + * @param string content + * @return void + */ + function setInspectorFormElementHeaderEditorContent(content) { + getInspector().setFormElementHeaderEditorContent(content); + }; + + /* ************************************************************* + * Stage + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStage() { + return _stageComponent; + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStageHeadline(title) { + getStage().setStageHeadline(title); + }; + + /** + * @public + * + * @return void + */ + function addStagePanelSelection() { + getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel')); + }; + + /** + * @public + * + * @return void + */ + function removeStagePanelSelection() { + getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel')); + }; + + /** + * @public + * + * @return void + */ + function renderPagination() { + getStage().renderPagination(); + }; + + /** + * @public + * + * @return void + */ + function renderUndoRedo() { + getStage().renderUndoRedo(); + }; + + /** + * @public + * + * @param bool + * @param bool + * @return void + * @publish view/stage/abstract/render/postProcess + * @publish view/stage/abstract/render/preProcess + */ + function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) { + var render, renderPostProcess; + + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .animate({ + 'left': '0px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .animate({ + 'right': '0px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .animate({ + 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' + }, 'slow'); + + if (getUtility().isUndefinedOrNull(useFadeEffect)) { + useFadeEffect = true; + } + + if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { + toolbarUseFadeEffect = true; + } + + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); + + /** + * @private + * + * @param function + * @return void + */ + render = function(callback) { + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .addClass(getHelper().getDomElementClassName('stageViewModeAbstract')) + .removeClass(getHelper().getDomElementClassName('stageViewModePreview')); + + getStage().renderAbstractStageArea(undefined, callback); + }; + + /** + * @private + * + * @return void + */ + renderPostProcess = function() { + var formElementTypeDefinition; + + formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); + getStage().getAllFormElementDomElements().hover(function() { + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + if ( + $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit')) + && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel')) + ) { + $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover')); + } + }); + + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + if ( + formElementTypeDefinition['_isTopLevelFormElement'] + && !formElementTypeDefinition['_isCompositeFormElement'] + && !getFormEditorApp().isRootFormElementSelected() + ) { + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + } else { + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + } + + refreshSelectedElementItemsBatch(toolbarUseFadeEffect); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }; + + if (useFadeEffect) { + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { + render(function() { + getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); + renderPostProcess(); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }); + }); + } else { + render(function() { + getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); + renderPostProcess(); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }); + } + }; + + /** + * @public + * + * @param string html + * @return void + * @publish view/stage/preview/render/postProcess + */ + function renderPreviewStageArea(html) { + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .animate({ + 'left': '-=' + _configuration['panels']['structure']['width'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .animate({ + 'right': '-=' + _configuration['panels']['inspector']['width'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .animate({ + 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px' + }, 'slow'); + + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); + removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .addClass(getHelper().getDomElementClassName('stageViewModePreview')) + .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract')); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + + getStage().renderPreviewStageArea(html); + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); + getPublisherSubscriber().publish('view/stage/preview/render/postProcess'); + }); + }; + + /** + * @public + * + * @return void + */ + function addAbstractViewValidationResults() { + var validationResults; + + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + if (i > 0) { + validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']); + setElementValidationErrorClass(validationElement); + } + } + } + }; + + /* ************************************************************* + * Form element methods + * ************************************************************/ + + /** + * @public + * + * @param string formElementType + * @param string|object referenceFormElement + * @param bool + * @return object + * @publish view/formElement/inserted + */ + function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { + var newFormElement; + + newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); + } + return newFormElement; + }; + + /** + * @public + * + * @param string|object formElementToMove + * @param string position + * @param string|object referenceFormElement + * @param bool + * @return object + * @publish view/formElement/moved + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + var movedFormElement; + + movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]); + } + return movedFormElement; + }; + + /** + * @public + * + * @param object formElement + * @param bool + * @return object + * @publish view/formElement/removed + */ + function removeFormElement(formElement, disablePublishersOnSet) { + var parentFormElement; + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + if ( + getFormElementDefinition(formElement, '_isTopLevelFormElement') + && getFormElementDefinition(formElement, '_isCompositeFormElement') + && getRootFormElement().get('renderables').length === 1 + ) { + Notification.error( + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'), + 2 + ); + } else { + parentFormElement = getFormEditorApp().removeFormElement(formElement, false); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]); + } + } + return parentFormElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param object collectionElementConfiguration + * @param string referenceCollectionElementIdentifier + * @param bool + * @return void + * @publish view/collectionElement/new/added + */ + function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) { + getFormEditorApp().createAndAddPropertyCollectionElement( + collectionElementIdentifier, + collectionName, + formElement, + collectionElementConfiguration, + referenceCollectionElementIdentifier + ); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/new/added', [ + collectionElementIdentifier, + collectionName, + formElement, + collectionElementConfiguration, + referenceCollectionElementIdentifier + ]); + } + }; + + /** + * @public + * + * @param string collectionElementToMove + * @param string position + * @param string referenceCollectionElement + * @param string collectionName + * @param object formElement + * @param bool + * @return void + */ + function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getFormEditorApp().movePropertyCollectionElement( + collectionElementToMove, + position, + referenceCollectionElement, + collectionName, + formElement, + false + ); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/moved', [ + collectionElementToMove, + position, + referenceCollectionElement, + collectionName, + formElement] + ); + } + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param bool + * @return void + * @publish view/collectionElement/removed + */ + function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/removed', [ + collectionElementIdentifier, + collectionName, + formElement] + ); + } + }; + + /* ************************************************************* + * Batch methodes + * ************************************************************/ + + /** + * @public + * + * @param bool + * @return void + */ + function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) { + var formElementTypeDefinition, selectedElement; + + if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { + toolbarUseFadeEffect = true; + } + + formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); + + getStage().removeAllStageToolbars(); + removeAllStageElementSelectionsBatch(); + removeAllStructureSelections(); + + if (!getFormEditorApp().isRootFormElementSelected()) { + removeStructureRootElementSelection(); + addStructureSelection(); + + selectedElement = getStage().getAbstractViewFormElementDomElement(); + + if (formElementTypeDefinition['_isTopLevelFormElement']) { + addStagePanelSelection(); + } else { + selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement')); + getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect); + } + + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement')); + if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { + selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement')); + } + } + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1478651732 + * @throws 1478651733 + * @throws 1478651734 + */ + function selectPageBatch(pageIndex) { + assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732); + assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733); + assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734); + + getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]); + renewStructure(); + renderPagination() + refreshSelectedElementItemsBatch(); + renderInspectorEditors(); + }; + + /** + * @public + * + * @return void + */ + function removeAllStageElementSelectionsBatch() { + getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement')); + removeStagePanelSelection(); + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + }; + + /** + * @public + * + * @return void + */ + function onViewReadyBatch() { + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .css({ + width: _configuration['panels']['structure']['width'] + 'px', + left: '-=' + _configuration['panels']['structure']['width'] + 'px' + }); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .css({ + width: _configuration['panels']['inspector']['width'] + 'px', + right: '-=' + _configuration['panels']['inspector']['width'] + 'px' + }); + + $(getHelper().getDomElementClassName('headerButtonBar', true)) + .css({ + 'margin-left': _configuration['panels']['structure']['width'] + 'px' + }); + + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .css({ + 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' + }); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + + setStageHeadline(); + setStructureRootElementTitle(); + renderAbstractStageArea(false); + renewStructure(); + addStructureRootElementSelection(); + renderInspectorEditors(); + renderPagination(); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + }; + + /** + * @public + * + * @param object + * @param object + * @return void + */ + function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) { + draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover')); + }; + + /** + * @public + * + * @param object + * @param string + * @param object + * @return void + */ + function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + if (enclosingCompositeFormElement) { + getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover')); + } + }; + + /** + * @public + * + * @param object + * @param string + * @param string + * @param string + * @return void + * @throws 1472502237 + */ + function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { + var movedFormElement, parentFormElementIdentifierPath; + if (nextFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); + } else if (previousFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); + } else { + parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement); + if (parentFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); + } else { + assert(false, 'Next element, previous or parent element need to be set.', 1472502237); + } + } + + getStage() + .getAbstractViewFormElementWithinDomElement(movedDomElement) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + movedFormElement.get('__identifierPath') + ); + }; + + /** + * @public + * + * @param object + * @param string + * @param object + * @return void + */ + function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { + getStructure() + .getAllTreeNodes() + .parent() + .removeClass(getHelper().getDomElementClassName('sortableHover')); + + getStage() + .getAllFormElementDomElements() + .parent() + .removeClass(getHelper().getDomElementClassName('sortableHover')); + + if (enclosingCompositeFormElement) { + getStructure() + .getParentTreeNodeWithinDomElement(placeholderDomElement) + .parent() + .addClass(getHelper().getDomElementClassName('sortableHover')); + + getStage() + .getAbstractViewFormElementDomElement(enclosingCompositeFormElement) + .parent() + .addClass(getHelper().getDomElementClassName('sortableHover')); + } + }; + + /** + * @public + * + * @param object + * @param string + * @param string + * @param string + * @return void + * @throws 1479048646 + */ + function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { + var movedFormElement, parentFormElementIdentifierPath; + if (nextFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); + } else if (previousFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); + } else { + parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement); + if (parentFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); + } else { + getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646); + } + } + + getStructure() + .getTreeNodeWithinDomElement(movedDomElement) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + movedFormElement.get('__identifierPath') + ); + }; + + /* ************************************************************* + * Misc + * ************************************************************/ + + /** + * @public + * + * @return void + */ + function closeEditor() { + document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href'); + }; + + /** + * @public + * + * @param object + * @param string + * @return void + */ + function setElementValidationErrorClass(element, classIdentifier) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { + element.addClass(getHelper().getDomElementClassName('validationErrors')); + } else { + element.addClass(getHelper().getDomElementClassName(classIdentifier)); + } + }; + + /** + * @public + * + * @param object + * @param string + * @return void + */ + function removeElementValidationErrorClass(element, classIdentifier) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { + element.removeClass(getHelper().getDomElementClassName('validationErrors')); + } else { + element.removeClass(getHelper().getDomElementClassName(classIdentifier)); + } + }; + + /** + * @public + * + * @param object + * @return void + */ + function showComponent(element) { + element.removeClass(getHelper().getDomElementClassName('hidden')).show(); + }; + + /** + * @public + * + * @param object + * @return void + */ + function hideComponent(element) { + element.addClass(getHelper().getDomElementClassName('hidden')).hide(); + }; + + /** + * @public + * + * @param object + * @return void + */ + function enableButton(buttonElement) { + buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function disableButton(buttonElement) { + buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function setButtonActive(buttonElement) { + buttonElement.addClass(getHelper().getDomElementClassName('active')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function removeButtonActive(buttonElement) { + buttonElement.removeClass(getHelper().getDomElementClassName('active')); + }; + + /** + * @public + * + * @return void + */ + function showSaveButtonSpinnerIcon() { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) { + $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup)); + }); + }; + + /** + * @public + * + * @return void + */ + function showSaveButtonSaveIcon() { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) { + $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup)); + }); + }; + + /** + * @public + * + * @return void + */ + function showSaveSuccessMessage() { + Notification.success( + getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'), + 2 + ); + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function showErrorFlashMessage(title, message) { + Notification.error(title, message, 2); + }; + + /** + * @public + * + * @param object formEditorApp + * @param object additionalViewModelModules + * @return void + */ + function bootstrap(formEditorApp, additionalViewModelModules) { + _formEditorApp = formEditorApp; + + _helperSetup(); + _structureComponentSetup(); + _modalsComponentSetup(); + _inspectorsComponentSetup(); + _stageComponentSetup(); + _buttonsSetup(); + _addPropertyValidators(); + _loadAdditionalModules(additionalViewModelModules); + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + addAbstractViewValidationResults: addAbstractViewValidationResults, + addStagePanelSelection: addStagePanelSelection, + addStructureRootElementSelection: addStructureRootElementSelection, + addStructureSelection: addStructureSelection, + addStructureValidationResults: addStructureValidationResults, + bootstrap: bootstrap, + closeEditor: closeEditor, + createAndAddFormElement: createAndAddFormElement, + createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, + disableButton: disableButton, + enableButton: enableButton, + getConfiguration: getConfiguration, + getFormEditorApp: getFormEditorApp, + getFormElementDefinition: getFormElementDefinition, + getHelper: getHelper, + getInspector: getInspector, + getModals: getModals, + getPreviewMode: getPreviewMode, + getStage: getStage, + getStructure: getStructure, + getStructureRootElement: getStructureRootElement, + hideComponent: hideComponent, + moveFormElement: moveFormElement, + movePropertyCollectionElement: movePropertyCollectionElement, + onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch, + onAbstractViewDndStartBatch: onAbstractViewDndStartBatch, + onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch, + onStructureDndChangeBatch: onStructureDndChangeBatch, + onStructureDndUpdateBatch: onStructureDndUpdateBatch, + onViewReadyBatch: onViewReadyBatch, + refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch, + removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch, + removeAllStructureSelections: removeAllStructureSelections, + removeButtonActive: removeButtonActive, + removeElementValidationErrorClass: removeElementValidationErrorClass, + removeFormElement: removeFormElement, + removePropertyCollectionElement: removePropertyCollectionElement, + removeStagePanelSelection: removeStagePanelSelection, + removeStructureRootElementSelection: removeStructureRootElementSelection, + removeStructureSelection: removeStructureSelection, + renderAbstractStageArea: renderAbstractStageArea, + renderInspectorEditors: renderInspectorEditors, + renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors, + renderPagination: renderPagination, + renderPreviewStageArea: renderPreviewStageArea, + renewStructure: renewStructure, + renderUndoRedo: renderUndoRedo, + selectPageBatch: selectPageBatch, + setButtonActive: setButtonActive, + setElementValidationErrorClass: setElementValidationErrorClass, + setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent, + setPreviewMode: setPreviewMode, + setStageHeadline: setStageHeadline, + setStructureRootElementTitle: setStructureRootElementTitle, + showCloseConfirmationModal: showCloseConfirmationModal, + showComponent: showComponent, + showErrorFlashMessage: showErrorFlashMessage, + showInsertElementsModal: showInsertElementsModal, + showInsertPagesModal: showInsertPagesModal, + showRemoveFormElementModal: showRemoveFormElementModal, + showRemoveCollectionElementModal: showRemoveCollectionElementModal, + showSaveButtonSaveIcon: showSaveButtonSaveIcon, + showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon, + showSaveSuccessMessage: showSaveSuccessMessage, + showValidationErrorsModal: showValidationErrorsModal + }; + })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js new file mode 100644 index 0000000000000000000000000000000000000000..26a70aa1941dd521be5e894be5344c2a42f82649 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js @@ -0,0 +1,240 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormManager + */ +define(['jquery'], function($) { + 'use strict'; + + /** + * Return a static method named "getInstance". + * Use this method to create the formmanager app. + */ + return (function() { + + /** + * @private + * + * Hold the instance (Singleton Pattern) + */ + var _formManagerInstance = null; + + /** + * @public + * + * @param object _configuration + * @param object _viewModel + * @return object + */ + function FormManager(_configuration, _viewModel) { + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + if ('function' === $.type(test)) { + test = (test() !== false); + } + if (!test) { + message = message || "Assertion failed"; + if (messageCode) { + message = message + ' (' + messageCode + ')'; + } + if ('undefined' !== typeof Error) { + throw new Error(message); + } + throw message; + } + }; + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @public + * + * @return object + */ + function getPrototypes() { + var prototypes = []; + + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { + for (var i = 0, len = _configuration['selectablePrototypesConfiguration'].length; i < len; ++i) { + prototypes.push({ + label: _configuration['selectablePrototypesConfiguration'][i]['label'], + value: _configuration['selectablePrototypesConfiguration'][i]['identifier'], + }); + } + } + return prototypes; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + */ + function getTemplatesForPrototype(prototypeName) { + var templates = []; + assert('string' === $.type(prototypeName), 'Invalid parameter "prototypeName"', 1475945286); + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { + for (var i = 0, len1 = _configuration['selectablePrototypesConfiguration'].length; i < len1; ++i) { + if (_configuration['selectablePrototypesConfiguration'][i]['identifier'] !== prototypeName) { + continue; + } + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'])) { + for (var j = 0, len2 = _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'].length; j < len2; ++j) { + templates.push({ + label: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['label'], + value: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['templatePath'], + }); + } + } + } + } + + return templates; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + */ + function getAccessibleFormStorageFolders() { + var folders = []; + + if ('array' === $.type(_configuration['accessibleFormStorageFolders'])) { + for (var i = 0, len1 = _configuration['accessibleFormStorageFolders'].length; i < len1; ++i) { + folders.push({ + label: _configuration['accessibleFormStorageFolders'][i]['label'], + value: _configuration['accessibleFormStorageFolders'][i]['value'], + }); + } + } + return folders; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + * @throws 1477506508 + */ + function getAjaxEndpoint(endpointName) { + var templates = []; + assert(typeof _configuration['endpoints'][endpointName] !== 'undefined', 'Endpoint ' + endpointName + ' does not exist', 1477506508); + + return _configuration['endpoints'][endpointName]; + }; + + /** + * @private + * + * @return void + * @throws 1475942906 + */ + function _viewSetup() { + assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475942906); + _viewModel.bootstrap(_formManagerInstance); + }; + + /** + * @private + * + * @return void + * @throws 1477506504 + */ + function _bootstrap() { + _configuration = _configuration || {}; + assert('object' === $.type(_configuration['endpoints']), 'Invalid parameter "endpoints"', 1477506504); + _viewSetup(); + }; + + /** + * @public + * + * @return TYPO3/CMS/Form/Backend/FormManager + * @throws 1475942618 + */ + function run() { + if (_isRunning) { + throw 'You can not run the app twice (1475942618)'; + } + + _bootstrap(); + _isRunning = true; + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getPrototypes: getPrototypes, + getTemplatesForPrototype: getTemplatesForPrototype, + getAccessibleFormStorageFolders: getAccessibleFormStorageFolders, + getAjaxEndpoint: getAjaxEndpoint, + + assert: assert, + run: run + }; + }; + + /** + * Emulation of static methods + */ + return { + /** + * @public + * @static + * + * Implement the "Singleton Pattern". + * + * Return a singleton instance of a + * "FormManager" object. + * + * @param object configuration + * @param object viewModel + * @return object + */ + getInstance: function(configuration, viewModel) { + if(_formManagerInstance === null) { + _formManagerInstance = new FormManager(configuration, viewModel); + } + return _formManagerInstance; + } + }; + })(); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js new file mode 100644 index 0000000000000000000000000000000000000000..d379fe6ecb0fed2880d45cff98163832a200ef27 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js @@ -0,0 +1,534 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Module: TYPO3/CMS/Form/Backend/FormManager/ViewModel + */ +define(['jquery', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Wizard', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification' + ], function($, Modal, Severity, Wizard, Icons, Notification) { + 'use strict'; + + return (function($, Modal, Severity, Wizard, Icons,Notification) { + + /** + * @private + * + * @var object + */ + var _formManagerApp = null; + + /** + * @private + * + * @var object + */ + var _domElementIdentifierCache = {}; + + /** + * @private + * + * @return void + */ + function _domElementIdentifierCacheSetup() { + _domElementIdentifierCache = { + newFormModalTrigger: { identifier: '[data-identifier="newForm"]' }, + duplicateFormModalTrigger: { identifier: '[data-identifier="duplicateForm"]' }, + removeFormModalTrigger: { identifier: '[data-identifier="removeForm"]' }, + + newFormName: { identifier: '[data-identifier="newFormName"]' }, + newFormSavePath: { identifier: '[data-identifier="newFormSavePath"]' }, + advancedWizard: { identifier: '[data-identifier="advancedWizard"]' }, + newFormPrototypeName: { identifier: '[data-identifier="newFormPrototypeName"]' }, + newFormTemplate: { identifier: '[data-identifier="newFormTemplate"]' }, + + duplicateFormName: { identifier: '[data-identifier="duplicateFormName"]' }, + duplicateFormSavePath: { identifier: '[data-identifier="duplicateFormSavePath"]' }, + + showReferences: { identifier: '[data-identifier="showReferences"]' }, + referenceLink: { identifier: '[data-identifier="referenceLink"]' }, + + tooltip: { identifier: '[data-toggle="tooltip"]' } + } + }; + + /** + * @private + * + * @return void + * @throws 1477506500 + * @throws 1477506501 + * @throws 1477506502 + */ + function _newFormSetup() { + $(getDomElementIdentifier('newFormModalTrigger')).on('click', function(e) { + e.preventDefault(); + + /** + * Wizard step 1 + */ + Wizard.addSlide('new-form-step-1', TYPO3.lang['formManager.newFormWizard.step1.title'], '', Severity.info, function(slide) { + var advandecWizardHasOptions, folders, html, modal, nextButton, prototypes, savePathSelect, templates; + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + folders = _formManagerApp.getAccessibleFormStorageFolders(); + _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477506500); + + Wizard.set('savePath', folders[0]['value']); + if (folders.length > 1) { + savePathSelect = $('<select class="new-form-save-path form-control" data-identifier="newFormSavePath" />'); + for (var i = 0, len = folders.length; i < len; ++i) { + var option = new Option(folders[i]['label'], folders[i]['value']); + $(savePathSelect).append(option); + } + } + + prototypes = _formManagerApp.getPrototypes(); + + _formManagerApp.assert(prototypes.length > 0, 'No prototypes available', 1477506501); + Wizard.set('prototypeName', prototypes[0]['value']); + + templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); + _formManagerApp.assert(templates.length > 0, 'No templates available', 1477506502); + Wizard.set('templatePath', templates[0]['value']); + + html = '<div class="new-form-modal">' + + '<div class="form-horizontal">' + + '<div>' + + '<label class="control-label">' + TYPO3.lang['formManager.form_name'] + '</label>' + + '<input class="new-form-name form-control has-error" data-identifier="newFormName" />'; + + if (savePathSelect) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; + } + + if (prototypes.length > 1 || templates.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.advanced'] + '</label>' + + '<div class="t3-form-controls"><input type="checkbox" class="new-form-advance-wizard" data-identifier="advancedWizard" /></div>'; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + $(getDomElementIdentifier('newFormName'), modal).focus(); + + $(getDomElementIdentifier('newFormName'), modal).on('keyup paste', function(e) { + if ($(this).val().length > 0) { + $(this).removeClass('has-error'); + Wizard.unlockNextStep(); + Wizard.set('formName', $(this).val()); + } else { + $(this).addClass('has-error'); + Wizard.lockNextStep(); + } + }); + + $(getDomElementIdentifier('newFormSavePath'), modal).on('change', function(e) { + Wizard.set('savePath', $(getDomElementIdentifier('newFormSavePath') + ' option:selected', modal).val()); + }); + + $(getDomElementIdentifier('advancedWizard'), modal).on('change', function(e) { + if ($(this).is(':checked')) { + Wizard.set('advancedWizard', true); + } else { + Wizard.set('advancedWizard', false); + } + }); + + nextButton.on('click', function() { + Wizard.setup.forceSelection = false; + Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { + slide.html($('<div />', {class: 'text-center'}).append(markup)); + }); + }); + }); + + /** + * Wizard step 2 + */ + Wizard.addSlide('new-form-step-2', TYPO3.lang['formManager.newFormWizard.step2.title'], '', Severity.info, function(slide, settings) { + var addOnTemplateChangeEvents, html, modal, nextButton, prototypes, prototypeNameSelect, templates, templateSelect; + + if (settings['advancedWizard'] !== true) { + Wizard.unlockNextStep().trigger('click'); + return; + } + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + prototypeNameSelect = $('<select class="new-form-prototype-name form-control" data-identifier="newFormPrototypeName" />'); + templateSelect = $('<select class="new-form-template form-control" data-identifier="newFormTemplate" />'); + + prototypes = _formManagerApp.getPrototypes(); + templates = {}; + if (prototypes.length > 0) { + for (var i = 0, len = prototypes.length; i < len; ++i) { + var option = new Option(prototypes[i]['label'], prototypes[i]['value']); + $(prototypeNameSelect).append(option); + } + + templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); + for (var i = 0, len = templates.length; i < len; ++i) { + var option = new Option(templates[i]['label'], templates[i]['value']); + $(templateSelect).append(option); + } + } + + html = '<div class="new-form-modal">' + + '<div class="form-horizontal">' + + '<div>'; + + if (prototypes.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_prototype'] + '</label>' + $(prototypeNameSelect)[0].outerHTML; + } + if (templates.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_template'] + '</label>' + $(templateSelect)[0].outerHTML; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + if (prototypes.length > 1) { + $(getDomElementIdentifier('newFormPrototypeName'), modal).focus(); + } else if (templates.length > 1) { + $(getDomElementIdentifier('newFormTemplate'), modal).focus(); + } + + addOnTemplateChangeEvents = function() { + $(getDomElementIdentifier('newFormTemplate'), modal).on('change', function(e) { + Wizard.set('templatePath', $(getDomElementIdentifier('newFormTemplate') + ' option:selected', modal).val()); + }); + }; + + $(getDomElementIdentifier('newFormPrototypeName'), modal).on('change', function(e) { + Wizard.set('prototypeName', $(this).val()); + templates = _formManagerApp.getTemplatesForPrototype($(this).val()); + $(getDomElementIdentifier('newFormTemplate'), modal).off().empty(); + for (var i = 0, len = templates.length; i < len; ++i) { + var option = new Option(templates[i]['label'], templates[i]['value']); + $(getDomElementIdentifier('newFormTemplate'), modal).append(option); + Wizard.set('templatePath', templates[0]['value']); + } + addOnTemplateChangeEvents(); + }); + + addOnTemplateChangeEvents(); + + nextButton.on('click', function() { + Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { + slide.html($('<div />', {class: 'text-center'}).append(markup)); + }); + }); + }); + + /** + * Wizard step 3 + */ + Wizard.addSlide('new-form-step-3', TYPO3.lang['formManager.newFormWizard.step3.title'], TYPO3.lang['formManager.newFormWizard.step3.message'], Severity.info); + + /** + * Wizard step 4 + */ + Wizard.addFinalProcessingSlide(function() { + $.post(_formManagerApp.getAjaxEndpoint('create'), { + tx_form_web_formformbuilder: { + formName: Wizard.setup.settings['formName'], + templatePath: Wizard.setup.settings['templatePath'], + prototypeName: Wizard.setup.settings['prototypeName'], + savePath: Wizard.setup.settings['savePath'] + } + }, function(data, textStatus, jqXHR) { + document.location = data; + Wizard.dismiss(); + }).fail(function(jqXHR, textStatus, errorThrown) { + Notification.error(textStatus, errorThrown, 2); + Wizard.dismiss(); + }); + }).done(function() { + Wizard.show(); + }); + }); + }; + + /** + * @private + * + * @return void + */ + function _removeFormSetup() { + $(getDomElementIdentifier('removeFormModalTrigger')).on('click', function(e) { + var modalButtons = [], that; + + e.preventDefault(); + that = $(this) + + modalButtons.push({ + text: TYPO3.lang['formManager.cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function () { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: TYPO3.lang['formManager.remove_form'], + active: true, + btnClass: 'btn-warning', + name: 'createform', + trigger: function () { + document.location = _formManagerApp.getAjaxEndpoint('delete') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + that.data('formPersistenceIdentifier'); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + TYPO3.lang['formManager.remove_form_title'], + TYPO3.lang['formManager.remove_form_message'], + Severity.warning, + modalButtons + ); + }); + }; + + /** + * @private + * + * @return void + * @throws 1477649539 + */ + function _duplicateFormSetup() { + $(getDomElementIdentifier('duplicateFormModalTrigger')).on('click', function(e) { + var that; + + e.preventDefault(); + that = $(this); + + /** + * Wizard step 1 + */ + Wizard.addSlide('duplicate-form-step-1', TYPO3.lang['formManager.duplicateFormWizard.step1.title'].replace('{0}', that.data('formName')), '', Severity.info, function(slide) { + var folders, html, modal, nextButton, savePathSelect; + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + folders = _formManagerApp.getAccessibleFormStorageFolders(); + _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477649539); + + Wizard.set('formPersistenceIdentifier', that.data('formPersistenceIdentifier')); + Wizard.set('savePath', folders[0]['value']); + if (folders.length > 1) { + savePathSelect = $('<select class="duplicate-form-save-path form-control" data-identifier="duplicateFormSavePath" />'); + for (var i = 0, len = folders.length; i < len; ++i) { + var option = new Option(folders[i]['label'], folders[i]['value']); + $(savePathSelect).append(option); + } + } + + html = '<div class="duplicate-form-modal">' + + '<div class="form-horizontal">' + + '<div>' + + '<label class="control-label">' + TYPO3.lang['formManager.new_form_name'] + '</label>' + + '<input class="duplicate-form-name form-control has-error" data-identifier="duplicateFormName" />'; + + if (savePathSelect) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + $(getDomElementIdentifier('duplicateFormName'), modal).focus(); + + $(getDomElementIdentifier('duplicateFormName'), modal).on('keyup paste', function(e) { + if ($(this).val().length > 0) { + $(this).removeClass('has-error'); + Wizard.unlockNextStep(); + Wizard.set('formName', $(this).val()); + } else { + $(this).addClass('has-error'); + Wizard.lockNextStep(); + } + }); + + $(getDomElementIdentifier('duplicateFormSavePath'), modal).on('change', function(e) { + Wizard.set('savePath', $(getDomElementIdentifier('duplicateFormSavePath') + ' option:selected', modal).val()); + }); + }); + + /** + * Wizard step 2 + */ + Wizard.addFinalProcessingSlide(function() { + $.post(_formManagerApp.getAjaxEndpoint('duplicate'), { + tx_form_web_formformbuilder: { + formName: Wizard.setup.settings['formName'], + formPersistenceIdentifier: Wizard.setup.settings['formPersistenceIdentifier'], + savePath: Wizard.setup.settings['savePath'] + } + }, function(data, textStatus, jqXHR) { + document.location = data; + Wizard.dismiss(); + }).fail(function(jqXHR, textStatus, errorThrown) { + Notification.error(textStatus, errorThrown, 2); + Wizard.dismiss(); + }); + }).done(function() { + Wizard.show(); + }); + }); + }; + + /** + * @private + * + * @return void + */ + function _showReferencesSetup() { + $(getDomElementIdentifier('showReferences')).on('click', function(e) { + var that, url; + + e.preventDefault(); + that = this; + url = _formManagerApp.getAjaxEndpoint('references') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + $(this).data('formPersistenceIdentifier'); + + $.get(url, function(data, textStatus, jqXHR) { + var html, modalButtons = [], referencesLength; + + modalButtons.push({ + text: TYPO3.lang['formManager.cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function () { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + referencesLength = data['references'].length; + if (referencesLength > 0) { + html = '<div>' + + '<h3>' + TYPO3.lang['formManager.references.headline'].replace('{0}', $(that).data('formName')) + '</h3>' + + '</div>' + + '<div class="table-fit">' + + '<table id="forms" class="table table-striped table-condensed">' + + '<thead>' + + '<tr>' + + '<th>' + TYPO3.lang['formManager.page'] + '</th>' + + '<th>' + TYPO3.lang['formManager.record'] + '</th>' + + '</tr>' + + '</thead>' + + '<tbody>'; + + for (var i = 0, len = data['references'].length; i < len; ++i) { + html += '<tr>' + + '<td>' + data['references'][i]['recordPageTitle'] + '</td>' + + '<td>' + + data['references'][i]['recordIcon'] + + '<a href="' + data['references'][i]['recordEditUrl'] + '" data-identifier="referenceLink">' + + data['references'][i]['recordTitle'] + ' (uid: ' + data['references'][i]['recordUid'] + ')' + + '</a>' + + '</td>' + + '</tr>'; + } + + html += '</tbody>' + + '</table>' + + '</div>'; + } else { + html = '<div>' + + '<h1>' + TYPO3.lang['formManager.references.title'].replace('{0}', data['formPersistenceIdentifier']) + '</h1>' + + '</div>' + + '<div>' + TYPO3.lang['formManager.no_references'] + '</div>'; + } + + html = $(html); + $(getDomElementIdentifier('referenceLink'), html).on('click', function(e) { + e.preventDefault(); + Modal.currentModal.trigger('modal-dismiss'); + document.location = $(this).prop('href'); + }); + + Modal.show( + TYPO3.lang['formManager.references.title'], + html, + Severity.info, + modalButtons + ); + }).fail(function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status !== 0) { + Notification.error(textStatus, errorThrown, 2); + } + }); + }); + }; + + /** + * @public + * + * @param string elementIdentifier + * @param string type + * @return mixed|undefined + * @throws 1477506413 + * @throws 1477506414 + */ + function getDomElementIdentifier(elementIdentifier, type) { + _formManagerApp.assert(elementIdentifier.length > 0, 'Invalid parameter "elementIdentifier"', 1477506413); + _formManagerApp.assert(typeof _domElementIdentifierCache[elementIdentifier] !== "undefined", 'elementIdentifier "' + elementIdentifier + '" does not exist', 1477506414); + if (typeof type === "undefined") { + type = 'identifier'; + } + + return _domElementIdentifierCache[elementIdentifier][type] || undefined; + }; + + /** + * @public + * + * @param object formManagerApp + * @return void + */ + function bootstrap(formManagerApp) { + _formManagerApp = formManagerApp; + _domElementIdentifierCacheSetup(); + _removeFormSetup(); + _newFormSetup(); + _duplicateFormSetup(); + _showReferencesSetup(); + $(getDomElementIdentifier('tooltip')).tooltip(); + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + }; + })($, Modal, Severity, Wizard, Icons, Notification); +}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js new file mode 100644 index 0000000000000000000000000000000000000000..38bf5f7eb0d75d61a528f9c9b0ee7c269a6adf82 --- /dev/null +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js @@ -0,0 +1,907 @@ +/* + * jQuery UI Nested Sortable + * v 2.1a / 2016-02-04 + * https://github.com/ilikenwf/nestedSortable + * + * Depends on: + * jquery.ui.sortable.js 1.10+ + * + * Copyright (c) 2010-2016 Manuele J Sarfatti and contributors + * Licensed under the MIT License + * http://www.opensource.org/licenses/mit-license.php + */ +(function( factory ) { + "use strict"; + + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ + "jquery", + "jquery-ui/sortable" + ], factory ); + } else { + + // Browser globals + factory( window.jQuery ); + } +}(function($) { + "use strict"; + + function isOverAxis( x, reference, size ) { + return ( x > reference ) && ( x < ( reference + size ) ); + } + + $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, { + + options: { + disableParentChange: false, + doNotClear: false, + expandOnHover: 700, + isAllowed: function() { return true; }, + isTree: false, + listType: "ol", + maxLevels: 0, + protectRoot: false, + rootID: null, + rtl: false, + startCollapsed: false, + tabSize: 20, + + branchClass: "mjs-nestedSortable-branch", + collapsedClass: "mjs-nestedSortable-collapsed", + disableNestingClass: "mjs-nestedSortable-no-nesting", + errorClass: "mjs-nestedSortable-error", + expandedClass: "mjs-nestedSortable-expanded", + hoveringClass: "mjs-nestedSortable-hovering", + leafClass: "mjs-nestedSortable-leaf", + disabledClass: "mjs-nestedSortable-disabled" + }, + + _create: function() { + var self = this, + err; + + this.element.data("ui-sortable", this.element.data("mjs-nestedSortable")); + + // mjs - prevent browser from freezing if the HTML is not correct + if (!this.element.is(this.options.listType)) { + err = "nestedSortable: " + + "Please check that the listType option is set to your actual list type"; + + throw new Error(err); + } + + // if we have a tree with expanding/collapsing functionality, + // force 'intersect' tolerance method + if (this.options.isTree && this.options.expandOnHover) { + this.options.tolerance = "intersect"; + } + + $.ui.sortable.prototype._create.apply(this, arguments); + + // prepare the tree by applying the right classes + // (the CSS is responsible for actual hide/show functionality) + if (this.options.isTree) { + $(this.items).each(function() { + var $li = this.item, + hasCollapsedClass = $li.hasClass(self.options.collapsedClass), + hasExpandedClass = $li.hasClass(self.options.expandedClass); + + if ($li.children(self.options.listType).length) { + $li.addClass(self.options.branchClass); + // expand/collapse class only if they have children + + if ( !hasCollapsedClass && !hasExpandedClass ) { + if (self.options.startCollapsed) { + $li.addClass(self.options.collapsedClass); + } else { + $li.addClass(self.options.expandedClass); + } + } + } else { + $li.addClass(self.options.leafClass); + } + }); + } + }, + + _destroy: function() { + this.element + .removeData("mjs-nestedSortable") + .removeData("ui-sortable"); + return $.ui.sortable.prototype._destroy.apply(this, arguments); + }, + + _mouseDrag: function(event) { + var i, + item, + itemElement, + intersection, + self = this, + o = this.options, + scrolled = false, + $document = $(document), + previousTopOffset, + parentItem, + level, + childLevels, + itemAfter, + itemBefore, + newList, + method, + a, + previousItem, + nextItem, + helperIsNotSibling; + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if (this.options.scroll) { + if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + + if ( + ( + this.overflowOffset.top + + this.scrollParent[0].offsetHeight + ) - + event.pageY < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollTop() + o.scrollSpeed; + this.scrollParent.scrollTop(scrolled); + } else if ( + event.pageY - + this.overflowOffset.top < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollTop() - o.scrollSpeed; + this.scrollParent.scrollTop(scrolled); + } + + if ( + ( + this.overflowOffset.left + + this.scrollParent[0].offsetWidth + ) - + event.pageX < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed; + this.scrollParent.scrollLeft(scrolled); + } else if ( + event.pageX - + this.overflowOffset.left < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed; + this.scrollParent.scrollLeft(scrolled); + } + + } else { + + if ( + event.pageY - + $document.scrollTop() < + o.scrollSensitivity + ) { + scrolled = $document.scrollTop() - o.scrollSpeed; + $document.scrollTop(scrolled); + } else if ( + $(window).height() - + ( + event.pageY - + $document.scrollTop() + ) < + o.scrollSensitivity + ) { + scrolled = $document.scrollTop() + o.scrollSpeed; + $document.scrollTop(scrolled); + } + + if ( + event.pageX - + $document.scrollLeft() < + o.scrollSensitivity + ) { + scrolled = $document.scrollLeft() - o.scrollSpeed; + $document.scrollLeft(scrolled); + } else if ( + $(window).width() - + ( + event.pageX - + $document.scrollLeft() + ) < + o.scrollSensitivity + ) { + scrolled = $document.scrollLeft() + o.scrollSpeed; + $document.scrollLeft(scrolled); + } + + } + + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(this, event); + } + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + // mjs - find the top offset before rearrangement, + previousTopOffset = this.placeholder.offset().top; + + //Set the helper position + if (!this.options.axis || this.options.axis !== "y") { + this.helper[0].style.left = this.position.left + "px"; + } + if (!this.options.axis || this.options.axis !== "x") { + this.helper[0].style.top = (this.position.top) + "px"; + } + + // mjs - check and reset hovering state at each cycle + this.hovering = this.hovering ? this.hovering : null; + this.mouseentered = this.mouseentered ? this.mouseentered : false; + + // mjs - let's start caching some variables + (function() { + var _parentItem = this.placeholder.parent().parent(); + if (_parentItem && _parentItem.closest(".ui-sortable").length) { + parentItem = _parentItem; + } + }.call(this)); + + level = this._getLevel(this.placeholder); + childLevels = this._getChildLevels(this.helper); + newList = document.createElement(o.listType); + + //Rearrange + for (i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + item = this.items[i]; + itemElement = item.item[0]; + intersection = this._intersectsWithPointer(item); + if (!intersection) { + continue; + } + + // Only put the placeholder inside the current Container, skip all + // items form other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this moving items in "sub-sortables" can cause the placeholder to jitter + // beetween the outer and inner container. + if (item.instance !== this.currentContainer) { + continue; + } + + // No action if intersected item is disabled + // and the element above or below in the direction we're going is also disabled + if (itemElement.className.indexOf(o.disabledClass) !== -1) { + // Note: intersection hardcoded direction values from + // jquery.ui.sortable.js:_intersectsWithPointer + if (intersection === 2) { + // Going down + itemAfter = this.items[i + 1]; + if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) { + continue; + } + + } else if (intersection === 1) { + // Going up + itemBefore = this.items[i - 1]; + if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) { + continue; + } + } + } + + method = intersection === 1 ? "next" : "prev"; + + // cannot intersect with itself + // no useless actions that have been done before + // no action if the item moved is the parent of the item checked + if (itemElement !== this.currentItem[0] && + this.placeholder[method]()[0] !== itemElement && + !$.contains(this.placeholder[0], itemElement) && + ( + this.options.type === "semi-dynamic" ? + !$.contains(this.element[0], itemElement) : + true + ) + ) { + + // mjs - we are intersecting an element: + // trigger the mouseenter event and store this state + if (!this.mouseentered) { + $(itemElement).mouseenter(); + this.mouseentered = true; + } + + // mjs - if the element has children and they are hidden, + // show them after a delay (CSS responsible) + if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) { + if (!this.hovering) { + $(itemElement).addClass(o.hoveringClass); + this.hovering = window.setTimeout(function() { + $(itemElement) + .removeClass(o.collapsedClass) + .addClass(o.expandedClass); + + self.refreshPositions(); + self._trigger("expand", event, self._uiHash()); + }, o.expandOnHover); + } + } + + this.direction = intersection === 1 ? "down" : "up"; + + // mjs - rearrange the elements and reset timeouts and hovering state + if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { + $(itemElement).mouseleave(); + this.mouseentered = false; + $(itemElement).removeClass(o.hoveringClass); + if (this.hovering) { + window.clearTimeout(this.hovering); + } + this.hovering = null; + + // mjs - do not switch container if + // it's a root item and 'protectRoot' is true + // or if it's not a root item but we are trying to make it root + if (o.protectRoot && + !( + this.currentItem[0].parentNode === this.element[0] && + // it's a root item + itemElement.parentNode !== this.element[0] + // it's intersecting a non-root item + ) + ) { + if (this.currentItem[0].parentNode !== this.element[0] && + itemElement.parentNode === this.element[0] + ) { + + if ( !$(itemElement).children(o.listType).length) { + itemElement.appendChild(newList); + if (o.isTree) { + $(itemElement) + .removeClass(o.leafClass) + .addClass(o.branchClass + " " + o.expandedClass); + } + } + + if (this.direction === "down") { + a = $(itemElement).prev().children(o.listType); + } else { + a = $(itemElement).children(o.listType); + } + + if (a[0] !== undefined) { + this._rearrange(event, null, a); + } + + } else { + this._rearrange(event, item); + } + } else if (!o.protectRoot) { + this._rearrange(event, item); + } + } else { + break; + } + + // Clear emtpy ul's/ol's + this._clearEmpty(itemElement); + + this._trigger("change", event, this._uiHash()); + break; + } + } + + // mjs - to find the previous sibling in the list, + // keep backtracking until we hit a valid list item. + (function() { + var _previousItem = this.placeholder.prev(); + if (_previousItem.length) { + previousItem = _previousItem; + } else { + previousItem = null; + } + }.call(this)); + + if (previousItem != null) { + while ( + previousItem[0].nodeName.toLowerCase() !== "li" || + previousItem[0].className.indexOf(o.disabledClass) !== -1 || + previousItem[0] === this.currentItem[0] || + previousItem[0] === this.helper[0] + ) { + if (previousItem[0].previousSibling) { + previousItem = $(previousItem[0].previousSibling); + } else { + previousItem = null; + break; + } + } + } + + // mjs - to find the next sibling in the list, + // keep stepping forward until we hit a valid list item. + (function() { + var _nextItem = this.placeholder.next(); + if (_nextItem.length) { + nextItem = _nextItem; + } else { + nextItem = null; + } + }.call(this)); + + if (nextItem != null) { + while ( + nextItem[0].nodeName.toLowerCase() !== "li" || + nextItem[0].className.indexOf(o.disabledClass) !== -1 || + nextItem[0] === this.currentItem[0] || + nextItem[0] === this.helper[0] + ) { + if (nextItem[0].nextSibling) { + nextItem = $(nextItem[0].nextSibling); + } else { + nextItem = null; + break; + } + } + } + + this.beyondMaxLevels = 0; + + // mjs - if the item is moved to the left, send it one level up + // but only if it's at the bottom of the list + if (parentItem != null && + nextItem == null && + !(o.protectRoot && parentItem[0].parentNode == this.element[0]) && + ( + o.rtl && + ( + this.positionAbs.left + + this.helper.outerWidth() > parentItem.offset().left + + parentItem.outerWidth() + ) || + !o.rtl && (this.positionAbs.left < parentItem.offset().left) + ) + ) { + + parentItem.after(this.placeholder[0]); + helperIsNotSibling = !parentItem + .children(o.listItem) + .children("li:visible:not(.ui-sortable-helper)") + .length; + if (o.isTree && helperIsNotSibling) { + parentItem + .removeClass(this.options.branchClass + " " + this.options.expandedClass) + .addClass(this.options.leafClass); + } + if(typeof parentItem !== 'undefined') + this._clearEmpty(parentItem[0]); + this._trigger("change", event, this._uiHash()); + // mjs - if the item is below a sibling and is moved to the right, + // make it a child of that sibling + } else if (previousItem != null && + !previousItem.hasClass(o.disableNestingClass) && + ( + previousItem.children(o.listType).length && + previousItem.children(o.listType).is(":visible") || + !previousItem.children(o.listType).length + ) && + !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) && + ( + o.rtl && + ( + this.positionAbs.left + + this.helper.outerWidth() < + previousItem.offset().left + + previousItem.outerWidth() - + o.tabSize + ) || + !o.rtl && + (this.positionAbs.left > previousItem.offset().left + o.tabSize) + ) + ) { + + this._isAllowed(previousItem, level, level + childLevels + 1); + + if (!previousItem.children(o.listType).length) { + previousItem[0].appendChild(newList); + if (o.isTree) { + previousItem + .removeClass(o.leafClass) + .addClass(o.branchClass + " " + o.expandedClass); + } + } + + // mjs - if this item is being moved from the top, add it to the top of the list. + if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) { + previousItem.children(o.listType).prepend(this.placeholder); + } else { + // mjs - otherwise, add it to the bottom of the list. + previousItem.children(o.listType)[0].appendChild(this.placeholder[0]); + } + if(typeof parentItem !== 'undefined') + this._clearEmpty(parentItem[0]); + this._trigger("change", event, this._uiHash()); + } else { + this._isAllowed(parentItem, level, level + childLevels); + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if ($.ui.ddmanager) { + $.ui.ddmanager.drag(this, event); + } + + //Call callbacks + this._trigger("sort", event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event) { + // mjs - if the item is in a position not allowed, send it back + if (this.beyondMaxLevels) { + + this.placeholder.removeClass(this.options.errorClass); + + if (this.domPosition.prev) { + $(this.domPosition.prev).after(this.placeholder); + } else { + $(this.domPosition.parent).prepend(this.placeholder); + } + + this._trigger("revert", event, this._uiHash()); + + } + + // mjs - clear the hovering timeout, just to be sure + $("." + this.options.hoveringClass) + .mouseleave() + .removeClass(this.options.hoveringClass); + + this.mouseentered = false; + if (this.hovering) { + window.clearTimeout(this.hovering); + } + this.hovering = null; + + this._relocate_event = event; + this._pid_current = $(this.domPosition.parent).parent().attr("id"); + this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0; + $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event. + }, + + // mjs - this function is slightly modified + // to make it easier to hover over a collapsed element and have it expand + _intersectsWithSides: function(item) { + + var half = this.options.isTree ? .8 : .5, + isOverBottomHalf = isOverAxis( + this.positionAbs.top + this.offset.click.top, + item.top + (item.height * half), + item.height + ), + isOverTopHalf = isOverAxis( + this.positionAbs.top + this.offset.click.top, + item.top - (item.height * half), + item.height + ), + isOverRightHalf = isOverAxis( + this.positionAbs.left + this.offset.click.left, + item.left + (item.width / 2), + item.width + ), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ( + (horizontalDirection === "right" && isOverRightHalf) || + (horizontalDirection === "left" && !isOverRightHalf) + ); + } else { + return verticalDirection && ( + (verticalDirection === "down" && isOverBottomHalf) || + (verticalDirection === "up" && isOverTopHalf) + ); + } + + }, + + _contactContainers: function() { + + if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) { + return; + } + + $.ui.sortable.prototype._contactContainers.apply(this, arguments); + + }, + + _clear: function() { + var i, + item; + + $.ui.sortable.prototype._clear.apply(this, arguments); + + //relocate event + if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") && + this._sort_current === this._uiHash().item.index())) { + this._trigger("relocate", this._relocate_event, this._uiHash()); + } + + // mjs - clean last empty ul/ol + for (i = this.items.length - 1; i >= 0; i--) { + item = this.items[i].item[0]; + this._clearEmpty(item); + } + + }, + + serialize: function(options) { + + var o = $.extend({}, this.options, options), + items = this._getItemsAsjQuery(o && o.connected), + str = []; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || "id") || "") + .match(o.expression || (/(.+)[-=_](.+)/)), + pid = ($(o.item || this).parent(o.listType) + .parent(o.items) + .attr(o.attribute || "id") || "") + .match(o.expression || (/(.+)[-=_](.+)/)); + + if (res) { + str.push( + ( + (o.key || res[1]) + + "[" + + (o.key && o.expression ? res[1] : res[2]) + "]" + ) + + "=" + + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID)); + } + }); + + if (!str.length && o.key) { + str.push(o.key + "="); + } + + return str.join("&"); + + }, + + toHierarchy: function(options) { + + var o = $.extend({}, this.options, options), + ret = []; + + $(this.element).children(o.items).each(function() { + var level = _recursiveItems(this); + ret.push(level); + }); + + return ret; + + function _recursiveItems(item) { + var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)), + currentItem; + + var data = $(item).data(); + if (data.nestedSortableItem) { + delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data + } + + if (id) { + currentItem = { + "id": id[2] + }; + + currentItem = $.extend({}, currentItem, data); // Combine the two objects + + if ($(item).children(o.listType).children(o.items).length > 0) { + currentItem.children = []; + $(item).children(o.listType).children(o.items).each(function() { + var level = _recursiveItems(this); + currentItem.children.push(level); + }); + } + return currentItem; + } + } + }, + + toArray: function(options) { + + var o = $.extend({}, this.options, options), + sDepth = o.startDepthCount || 0, + ret = [], + left = 1; + + if (!o.excludeRoot) { + ret.push({ + "item_id": o.rootID, + "parent_id": null, + "depth": sDepth, + "left": left, + "right": ($(o.items, this.element).length + 1) * 2 + }); + left++; + } + + $(this.element).children(o.items).each(function() { + left = _recursiveArray(this, sDepth, left); + }); + + ret = ret.sort(function(a, b) { return (a.left - b.left); }); + + return ret; + + function _recursiveArray(item, depth, _left) { + + var right = _left + 1, + id, + pid, + parentItem; + + if ($(item).children(o.listType).children(o.items).length > 0) { + depth++; + $(item).children(o.listType).children(o.items).each(function() { + right = _recursiveArray($(this), depth, right); + }); + depth--; + } + + id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)); + + if (depth === sDepth) { + pid = o.rootID; + } else { + parentItem = ($(item).parent(o.listType) + .parent(o.items) + .attr(o.attribute || "id")) + .match(o.expression || (/(.+)[-=_](.+)/)); + pid = parentItem[2]; + } + + if (id) { + var data = $(item).children('div').data(); + var itemObj = $.extend( data, { + "id":id[2], + "parent_id":pid, + "depth":depth, + "left":_left, + "right":right + } ); + ret.push( itemObj ); + } + + _left = right + 1; + return _left; + } + + }, + + _clearEmpty: function (item) { + function replaceClass(elem, search, replace, swap) { + if (swap) { + search = [replace, replace = search][0]; + } + + $(elem).removeClass(search).addClass(replace); + } + + var o = this.options, + childrenList = $(item).children(o.listType), + hasChildren = childrenList.has('li').length; + + var doNotClear = + o.doNotClear || + hasChildren || + o.protectRoot && $(item)[0] === this.element[0]; + + if (o.isTree) { + replaceClass(item, o.branchClass, o.leafClass, doNotClear); + } + + if (!doNotClear) { + childrenList.parent().removeClass(o.expandedClass); + childrenList.remove(); + } + }, + + _getLevel: function(item) { + + var level = 1, + list; + + if (this.options.listType) { + list = item.closest(this.options.listType); + while (list && list.length > 0 && !list.is(".ui-sortable")) { + level++; + list = list.parent().closest(this.options.listType); + } + } + + return level; + }, + + _getChildLevels: function(parent, depth) { + var self = this, + o = this.options, + result = 0; + depth = depth || 0; + + $(parent).children(o.listType).children(o.items).each(function(index, child) { + result = Math.max(self._getChildLevels(child, depth + 1), result); + }); + + return depth ? result + 1 : result; + }, + + _isAllowed: function(parentItem, level, levels) { + var o = this.options, + // this takes into account the maxLevels set to the recipient list + maxLevels = this + .placeholder + .closest(".ui-sortable") + .nestedSortable("option", "maxLevels"), + + // Check if the parent has changed to prevent it, when o.disableParentChange is true + oldParent = this.currentItem.parent().parent(), + disabledByParentchange = o.disableParentChange && ( + //From somewhere to somewhere else, except the root + typeof parentItem !== 'undefined' && !oldParent.is(parentItem) || + typeof parentItem === 'undefined' && oldParent.is("li") //From somewhere to the root + ); + // mjs - is the root protected? + // mjs - are we nesting too deep? + if ( + disabledByParentchange || + !o.isAllowed(this.placeholder, parentItem, this.currentItem) + ) { + this.placeholder.addClass(o.errorClass); + if (maxLevels < levels && maxLevels !== 0) { + this.beyondMaxLevels = levels - maxLevels; + } else { + this.beyondMaxLevels = 1; + } + } else { + if (maxLevels < levels && maxLevels !== 0) { + this.placeholder.addClass(o.errorClass); + this.beyondMaxLevels = levels - maxLevels; + } else { + this.placeholder.removeClass(o.errorClass); + this.beyondMaxLevels = 0; + } + } + } + + })); + + $.mjs.nestedSortable.prototype.options = $.extend( + {}, + $.ui.sortable.prototype.options, + $.mjs.nestedSortable.prototype.options + ); +})); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard.js deleted file mode 100644 index 3be1fa180bd786263880d058275922b40289badb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard.js +++ /dev/null @@ -1,276 +0,0 @@ -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -function configureWizardApplication() { - var basicdeps = [ - //'TYPO3', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/ButtonGroup', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Button', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Checkbox', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Fieldset', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Fileupload', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Hidden', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Password', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Radio', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Reset', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Select', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Submit', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Textarea', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Textline' - ]; - requirejs.config({shim: { - //'extjs': {exports: 'Ext'}, - //'TYPO3': {exports: 'TYPO3'}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.isemptyobject': {exports: 'Ext.isemptyobject', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.merge': {exports: 'Ext.merge', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.spinner': {exports: 'Ext.ux.Spinner', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.textfieldsubmit': {exports: 'Ext.ux.form.textfieldsubmit', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.spinnerfield': {exports: 'Ext.ux.form.SpinnerField', deps: ['TYPO3/CMS/Form/Wizard/Ux/Ext.ux.spinner']}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel': {exports: 'Ext.ux.form.FakeFormPanel', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.ValueCheckbox': {exports: 'Ext.ux.form.ValueCheckbox', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.CheckColumn': {exports: 'Ext.ux.grid.CheckColumn', deps: []}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.SingleSelectCheckColumn': {exports: 'Ext.ux.grid.SingleSelectCheckColumn', deps: ['TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.CheckColumn']}, - 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.ItemDeleter': {exports: 'Ext.ux.grid.ItemDeleter', deps: []}, - 'TYPO3/CMS/Form/Wizard/Settings': {exports: 'TYPO3.Form.Wizard.Settings', deps: []}, // defined during require callback - 'TYPO3/CMS/Form/Wizard/Helpers/History': {exports: 'TYPO3.Form.Wizard.Helpers.History', deps: []}, - 'TYPO3/CMS/Form/Wizard/Helpers/Element': {exports: 'TYPO3.Form.Wizard.Helpers.Element', deps: []}, - 'TYPO3/CMS/Form/Wizard/Elements/Dummy': {exports: 'TYPO3.Form.Wizard.Elements.Dummy', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/ButtonGroup': {exports: 'TYPO3.Form.Wizard.ButtonGroup', deps: []}, - 'TYPO3/CMS/Form/Wizard/Elements/Container': {exports: 'TYPO3.Form.Wizard.Container', deps: ['TYPO3/CMS/Form/Wizard/Elements/Dummy', 'TYPO3/CMS/Form/Wizard/Elements/Content/Header', 'TYPO3/CMS/Form/Wizard/Elements/Predefined/RadioGroup', 'TYPO3/CMS/Form/Wizard/Elements/Predefined/Email', 'TYPO3/CMS/Form/Wizard/Elements/Predefined/CheckboxGroup', 'TYPO3/CMS/Form/Wizard/Elements/Predefined/Name']}, - 'TYPO3/CMS/Form/Wizard/Elements/Elements': {exports: 'TYPO3.Form.Wizard.Elements', deps: ['TYPO3/CMS/Form/Wizard/Helpers/Element', 'TYPO3/CMS/Form/Wizard/Helpers/History', 'TYPO3/CMS/Form/Wizard/Elements/ButtonGroup']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Form': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Form', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements', 'TYPO3/CMS/Form/Wizard/Elements/Container']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Right': {exports: 'TYPO3.Form.Wizard.Viewport.Right', deps: ['TYPO3/CMS/Form/Wizard/Viewport', 'TYPO3/CMS/Form/Wizard/Elements/Basic/Form']}, - 'TYPO3/CMS/Form/Wizard/Elements/Content/Header': {exports: 'TYPO3.Form.Wizard.Elements.Content.Header', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Content/Textblock': {exports: 'TYPO3.Form.Wizard.Elements.Content.Textblock', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Content': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Elements.Content', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/ButtonGroup', 'TYPO3/CMS/Form/Wizard/Elements/Content/Header', 'TYPO3/CMS/Form/Wizard/Elements/Content/Textblock']}, - 'TYPO3/CMS/Form/Wizard/Elements/Predefined/Email': {exports: 'TYPO3.Form.Wizard.Elements.Predefined.Email', deps: ['TYPO3/CMS/Form/Wizard/Elements/Basic/Textline']}, - 'TYPO3/CMS/Form/Wizard/Elements/Predefined/CheckboxGroup': {exports: 'TYPO3.Form.Wizard.Elements.Predefined.CheckboxGroup', deps: ['TYPO3/CMS/Form/Wizard/Elements/Basic/Fieldset', 'TYPO3/CMS/Form/Wizard/Elements/Basic/Checkbox']}, - 'TYPO3/CMS/Form/Wizard/Elements/Predefined/Name': {exports: 'TYPO3.Form.Wizard.Elements.Predefined.Name', deps: ['TYPO3/CMS/Form/Wizard/Elements/Basic/Fieldset', 'TYPO3/CMS/Form/Wizard/Elements/Basic/Textline']}, - 'TYPO3/CMS/Form/Wizard/Elements/Predefined/RadioGroup': {exports: 'TYPO3.Form.Wizard.Elements.Predefined.RadioGroup', deps: ['TYPO3/CMS/Form/Wizard/Elements/Basic/Fieldset', 'TYPO3/CMS/Form/Wizard/Elements/Basic/Radio', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.merge']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Predefined': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Elements.Predefined', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/ButtonGroup']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Textline': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Textline', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Textarea': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Textarea', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Submit': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Submit', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Select': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Select', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Reset': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Reset', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Radio': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Radio', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Password': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Password', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Hidden': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Hidden', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Fileupload': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Fileupload', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Fieldset': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Fieldset', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Checkbox': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Checkbox', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Button': {exports: 'TYPO3.Form.Wizard.Elements.Basic.Button', deps: ['TYPO3/CMS/Form/Wizard/Elements/Elements']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Basic': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Elements.Basic', deps: basicdeps}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/ButtonGroup': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Elements']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Elements', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Options': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Options', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.SingleSelectCheckColumn', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.grid.ItemDeleter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Label': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Label', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Dummy': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Dummy', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Alphabetic': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphabetic', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Alphanumeric': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphanumeric', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Currency': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Currency', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Digit': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Digit', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Integer': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Integer', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/LowerCase': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.LowerCase', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/RegExp': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.RegExp', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/StripNewLines': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.StripNewLines', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/TitleCase': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.TitleCase', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Trim': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Trim', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/UpperCase': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.UpperCase', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Filter']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Dummy']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Legend': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Legend', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Required': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Required', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Dummy': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Dummy', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Alphabetic': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphabetic', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Alphanumeric': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphanumeric', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Between': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Between', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Date': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Date', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Digit': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Digit', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Email': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Equals': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Equals', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileAllowedTypes': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileAllowedTypes', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileMaximumSize': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMaximumSize', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileMinimumSize': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMinimumSize', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Float': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Float', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/GreaterThan': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.GreaterThan', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/InArray': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.InArray', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Integer': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Integer', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Ip': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Ip', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Length': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Length', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/LessThan': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.LessThan', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/RegExp': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.RegExp', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Uri': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Uri', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Rule']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Dummy']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Various': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Attributes': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.ValueCheckbox', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.spinnerfield']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Panel': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Panel', deps: [ - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Legend', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Label', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Alphabetic', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Alphanumeric', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Currency', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Digit', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Integer', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/LowerCase', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/RegExp', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/StripNewLines', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/TitleCase', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/Trim', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters/UpperCase', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Filters', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Various', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Alphabetic', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Alphanumeric', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Between', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Date', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Digit', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Email', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Equals', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileAllowedTypes', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileMaximumSize', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/FileMinimumSize', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Float', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/GreaterThan', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/InArray', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Integer', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Ip', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Length', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/LessThan', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/RegExp', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Required', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation/Uri', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Validation', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Options' - ]}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Dummy': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options.Dummy', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Options', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Dummy': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Dummy', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Mail': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Mail', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Redirect': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Redirect', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessor': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessor', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.isemptyobject', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Dummy', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Mail', 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessors/Redirect']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Attributes': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.Attributes', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Attributes']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Prefix': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.Prefix', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.textfieldsubmit', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Behaviour': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left/Form', 'TYPO3/CMS/Form/Wizard/Ux/Ext.ux.form.FakeFormPanel']}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form': {exports: 'TYPO3.Form.Wizard.Viewport.Left.Form', deps: ['TYPO3/CMS/Form/Wizard/Viewport/Left'/*, 'TYPO3/CMS/Form/Wizard/Settings'*/]}, - 'TYPO3/CMS/Form/Wizard/Viewport/Left': {exports: 'TYPO3.Form.Wizard.Viewport.Left', deps: ['TYPO3/CMS/Form/Wizard/Viewport'/*, 'TYPO3/CMS/Form/Wizard/Settings'*/]}, - 'TYPO3/CMS/Form/Wizard/Viewport': {exports: 'TYPO3.Form.Wizard.Viewport', deps: []} - }}); -} -configureWizardApplication(); - -/** - * Initialization script of TYPO3 form Wizard - */ -define('TYPO3/CMS/Form/Wizard', [ - //'extjs', - //'TYPO3', - 'TYPO3/CMS/Backend/SplitButtons', - 'TYPO3/CMS/Form/Wizard/Settings', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Content', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Predefined', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements/Basic', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Elements', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Forms/Options', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Panel', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options/Dummy', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Options', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/PostProcessor', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Attributes', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Prefix', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form/Behaviour', - 'TYPO3/CMS/Form/Wizard/Viewport/Left/Form', - 'TYPO3/CMS/Form/Wizard/Viewport/Left', - 'TYPO3/CMS/Form/Wizard/Elements/Basic/Form', - 'TYPO3/CMS/Form/Wizard/Viewport/Right', - 'TYPO3/CMS/Form/Wizard/Viewport' -], function (//Ext, - //TYPO3, - SplitButtons, - TYPO3_CMS_Form_Wizard_Settings, - TYPO3_CMS_Form_Wizard_Viewport_Left_Elements_Content, - TYPO3_CMS_Form_Wizard_Viewport_Left_Elements_Predefined, - TYPO3_CMS_Form_Wizard_Viewport_Left_Elements_Basic, - TYPO3_CMS_Form_Wizard_Viewport_Left_Elements, - TYPO3_CMS_Form_Wizard_Viewport_Left_Options_Forms_Options, - TYPO3_CMS_Form_Wizard_Viewport_Left_Options_Panel, - TYPO3_CMS_Form_Wizard_Viewport_Left_Options_Dummy, - TYPO3_CMS_Form_Wizard_Viewport_Left_Options, - TYPO3_CMS_Form_Wizard_Viewport_Left_Form_PostProcessor, - TYPO3_CMS_Form_Wizard_Viewport_Left_Form_Attributes, - TYPO3_CMS_Form_Wizard_Viewport_Left_Form_Prefix, - TYPO3_CMS_Form_Wizard_Viewport_Left_Form_Behaviour, - TYPO3_CMS_Form_Wizard_Viewport_Left_Form, - TYPO3_CMS_Form_Wizard_Viewport_Left, - TYPO3_CMS_Form_Wizard_Elements_Basic_Form, - TYPO3_CMS_Form_Wizard_Viewport_Right, - TYPO3_CMS_Form_Wizard_Viewport -) { - /** - * called when built as Object with "new" - * - * @constructor - */ - var Wizard = function() { - this.initialize(); - }; - - Wizard.prototype.initialize = function() { - Ext.onReady(function() { - var transportElId = Ext.get('form-wizard-element-container').dom.getAttribute('rel'); - var transportEl = Ext.get(transportElId).dom; - var viewport = new TYPO3.Form.Wizard.Viewport({ - renderTo: 'form-wizard-element', - transportEl: transportEl, - splitButtons: SplitButtons - }); - // When the window is resized, the viewport has to be resized as well - Ext.EventManager.onWindowResize(viewport.doLayout, viewport); - var relayoutFunction = function(ev) { - // bootstrap tab handling - var controlsId = ev.target.getAttribute('aria-controls'); - if(controlsId) { - var wizardEl = ev.target.parentNode.parentNode.parentNode.querySelector('#' + controlsId + ' ' + '#form-wizard-element'); - if(wizardEl) { - // we are earlier then bootstrap tab - setTimeout(function(){ - viewport.doLayout(); - }, 200); - } - } - }; - - // register tab change events - /** @var tabsLinks {NodeList} */ - var tabsLinks = document.querySelectorAll('a[data-toggle="tab"]'); - /** @see https://code.google.com/p/v8/issues/detail?id=3953 */ - for(var i = 0; i < tabsLinks.length; i++) { - var e = tabsLinks[i]; - // event not called, maybe jQuery only - //e.addEventListener('shown.bs.tab', relayoutFunction, false); - e.addEventListener('click', relayoutFunction, false); - } - }); - }; - - /** - * executed when module required, return value will be 'this' - * @return Wizard - */ - return function() { - return new Wizard(); - }(); -}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Button.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Button.js deleted file mode 100644 index bfb59a933013734c5420942582db5edba08aa882..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Button.js +++ /dev/null @@ -1,107 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The BUTTON element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Button - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Button = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'button', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'disabled': '', - 'name': '', - 'type': 'button', - 'value': TYPO3.l10n.localize('tx_form_domain_model_element_button.value') - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Button.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-button', TYPO3.Form.Wizard.Elements.Basic.Button); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Checkbox.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Checkbox.js deleted file mode 100644 index 5091d747a03876bcae21b59c907787132addde3e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Checkbox.js +++ /dev/null @@ -1,110 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The CHECKBOX element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Checkbox - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Checkbox = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'x-checkbox', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'checked': '', - 'disabled': '', - 'name': '', - 'readonly': '', - 'required': '', - 'type': 'checkbox', - 'value': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'back', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Checkbox.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-checkbox', TYPO3.Form.Wizard.Elements.Basic.Checkbox); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fieldset.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fieldset.js deleted file mode 100644 index d8558e68f1fe95fcf9a07f13ebea2c6b1a2d2179..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fieldset.js +++ /dev/null @@ -1,130 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The FIELDSET element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Fieldset - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Fieldset = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'fieldset', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div>', - '<fieldset {[this.getAttributes(values.attributes)]}>', - '<tpl for="legend">', - '<tpl if="value">', - '<legend>{value}</legend>', - '</tpl>', - '</tpl>', - '<ol></ol>', - '</fieldset>', - '</div>', - { - compiled: true, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * @cfg {Array} elementContainer - * Configuration for the containerComponent - */ - elementContainer: { - hasDragAndDrop: true - }, - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - "class": '', - dir: '', - id: '', - lang: '', - style: '' - }, - legend: { - value: TYPO3.l10n.localize('elements_legend') - } - } - }); - - TYPO3.Form.Wizard.Elements.Basic.Fieldset.superclass.constructor.apply(this, arguments); - }, - - /** - * Constructor - */ - initComponent: function() { - var config = {}; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // Initialize the container component - this.containerComponent = new TYPO3.Form.Wizard.Container(this.elementContainer); - - // call parent - TYPO3.Form.Wizard.Elements.Basic.Fieldset.superclass.initComponent.apply(this, arguments); - - // Initialize events after rendering - this.on('afterrender', this.afterRender, this); - }, - - /** - * Called by the 'afterrender' event. - * - * Add the container component to this component - */ - afterRender: function() { - this.addContainerAfterRender(); - - // Call parent - TYPO3.Form.Wizard.Elements.Basic.Form.superclass.afterRender.call(this); - }, - - /** - * Add the container component to this component - * - * Because we are using a XTemplate for rendering this component, we can - * only add the container after rendering, because the <ol> tag needs to be - * replaced with this container. - * - * The container needs to be rerendered when a configuration parameter - * (legend or attributes) of the ownerCt, for instance fieldset, has changed - * otherwise it will not show up - */ - addContainerAfterRender: function() { - this.containerComponent.applyToMarkup(this.getEl().child('ol')); - this.containerComponent.rendered = false; - this.containerComponent.render(); - this.containerComponent.doLayout(); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-fieldset', TYPO3.Form.Wizard.Elements.Basic.Fieldset); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fileupload.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fileupload.js deleted file mode 100644 index 9c65d00e1167e5e0d59045e601c30820b5ac968d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Fileupload.js +++ /dev/null @@ -1,111 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The FILEUPLOAD element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Fileupload - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Fileupload = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'fileupload', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'accept': '', - 'autofocus': '', - 'disabled': '', - 'multiple': '', - 'name': '', - 'readonly': '', - 'required': '', - 'type': 'file', - 'value': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Fileupload.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-fileupload', TYPO3.Form.Wizard.Elements.Basic.Fileupload); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Form.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Form.js deleted file mode 100644 index d14d96e50e7713b1efc702a88bc21e9e6124c77b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Form.js +++ /dev/null @@ -1,176 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The FORM element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Form - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Form = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {Mixed} autoEl - * A tag name or DomHelper spec used to create the Element which will - * encapsulate this Component. - */ - autoEl: 'li', - - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'form', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - * - * Adding novalidate attribute avoids HTML5 validation of elements. - */ - tpl: new Ext.XTemplate( - '<div id="fake-form" {[this.getAttributes(values.attributes)]} novalidate="novalidate">', - '<ol></ol>', - '</div>', - { - compiled: true, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * @cfg {Boolean} isEditable - * Defines whether the element is editable. If the item is editable, - * a button group with remove and edit buttons will be added to this element - * and when the the element is clicked, an event is triggered to edit the - * element. Some elements, like the dummy, don't need this. - */ - isEditable: false, - - /** - * @cfg {Array} elementContainer - * Configuration for the containerComponent - */ - elementContainer: { - hasDragAndDrop: true - }, - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'accept': '', - 'accept-charset': '', - 'action': '', - 'autocomplete': '', - 'enctype': 'application/x-www-form-urlencoded', - 'method': 'post', - 'novalidate': '' - }, - prefix: 'tx_form', - confirmation: true, - postProcessor: { - mail: { - recipientEmail: '', - senderEmail: '' - }, - redirect: { - destination: '' - } - } - } - }); - TYPO3.Form.Wizard.Elements.Basic.Form.superclass.constructor.apply(this, arguments); - }, - - /** - * Constructor - */ - initComponent: function() { - var config = {}; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // Initialize the container component - this.containerComponent = new TYPO3.Form.Wizard.Container(this.elementContainer); - - // Call parent - TYPO3.Form.Wizard.Elements.Basic.Form.superclass.initComponent.apply(this, arguments); - - // Initialize events after rendering - this.on('afterrender', this.afterRender, this); - }, - - /** - * Called by the 'afterrender' event. - * - * Add the container component to this component - * Stop the submit event of the form, because this form does not need to be - * submitted - */ - afterRender: function() { - this.addContainerAfterRender(); - - // Call parent - TYPO3.Form.Wizard.Elements.Basic.Form.superclass.afterRender.call(this); - }, - - /** - * Add the container component to this component - * - * Because we are using a XTemplate for rendering this component, we can - * only add the container after rendering, because the <ol> tag needs to be - * replaced with this container. - */ - addContainerAfterRender: function() { - this.containerComponent.applyToMarkup(this.getEl().child('ol')); - this.containerComponent.rendered = false; - this.containerComponent.render(); - this.containerComponent.doLayout(); - }, - - /** - * Remove a post processor from this element - * - * @param type - */ - removePostProcessor: function(type) { - if (this.configuration.postProcessor[type]) { - delete this.configuration.postProcessor[type]; - TYPO3.Form.Wizard.Helpers.History.setHistory(); - } - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-form', TYPO3.Form.Wizard.Elements.Basic.Form); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Hidden.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Hidden.js deleted file mode 100644 index abd6067af5507407380f2fa527ce668088717fdf..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Hidden.js +++ /dev/null @@ -1,88 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The HIDDEN element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Hidden - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Hidden = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'hidden-element', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<p class="hidden-dummy-element">{[this.getAttributes(values.attributes, \'name\')]}</p>', - '<input {[this.getAttributes(values.attributes)]} />', - '</div>', - { - compiled: true, - getAttributes: function(attributes, filterBy) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (typeof filterBy != 'undefined') { - if (key == filterBy) { - attributesHtml = value; - return; - } else { - return; - } - } - - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'name': '', - 'type': 'hidden', - 'value': '' - }, - filters: {}, - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Hidden.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-hidden', TYPO3.Form.Wizard.Elements.Basic.Hidden); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Password.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Password.js deleted file mode 100644 index 60d2ac8c66bd286169541635ecc48f61bebb8786..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Password.js +++ /dev/null @@ -1,115 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The PASSWORD element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Password - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Password = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'password', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autocomplete': '', - 'autofocus': '', - 'disabled': '', - 'maxlength': '', - 'minlength': '', - 'name': '', - 'pattern': '', - 'placeholder': '', - 'readonly': '', - 'required': '', - 'size': '', - 'type': 'password', - 'value': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Password.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-password', TYPO3.Form.Wizard.Elements.Basic.Password); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Radio.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Radio.js deleted file mode 100644 index b5cf1d6711fc9a6ba17e33328b80dcc50e4091d0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Radio.js +++ /dev/null @@ -1,110 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The RADIO element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Radio - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Radio = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'x-radio', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'checked': '', - 'disabled': '', - 'name': '', - 'readonly': '', - 'required': '', - 'type': 'radio', - 'value': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'back', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Radio.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-radio', TYPO3.Form.Wizard.Elements.Basic.Radio); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Reset.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Reset.js deleted file mode 100644 index 9893aa7d5dcb00a7b02cce78f6096fc60f162f8f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Reset.js +++ /dev/null @@ -1,137 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The RESET element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Reset - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Reset = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'reset', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - */ - initComponent: function() { - - // call parent - TYPO3.Form.Wizard.Elements.Basic.Reset.superclass.initComponent.apply(this, arguments); - - // Initialize events after rendering - this.on('afterrender', this.afterRender, this); - }, - - /** - * Called by the 'afterrender' event. - * - * Stop click propagation - */ - afterRender: function() { - this.getEl().addListener('click', function(e) { - if(e.type == 'click') { - e.stopEvent(); - } - }); - - // Call parent - TYPO3.Form.Wizard.Elements.Basic.Reset.superclass.afterRender.call(this); - }, - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'checked': '', - 'disabled': '', - 'name': '', - 'required': '', - 'type': 'reset', - 'value': TYPO3.l10n.localize('tx_form_domain_model_element_reset.value') - }, - filters: {}, - label: { - value: '' - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Reset.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-reset', TYPO3.Form.Wizard.Elements.Basic.Reset); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Select.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Select.js deleted file mode 100644 index f8e1560606821b44f357121ed6792e6cd06c5434..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Select.js +++ /dev/null @@ -1,130 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The SELECT element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Select - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Select = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'select', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<select {[this.getAttributes(values.attributes)]}>', - '<tpl for="options">', - '<option {[this.getAttributes(values.attributes)]}>{text}</option>', - '</tpl>', - '</select>', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'disabled': '', - 'multiple': '', - 'name': '', - 'required': '', - 'size': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - options: [ - { - text: TYPO3.l10n.localize('elements_option_1'), - attributes: { - value: TYPO3.l10n.localize('elements_value_1') - } - }, { - text: TYPO3.l10n.localize('elements_option_2'), - attributes: { - value: TYPO3.l10n.localize('elements_value_2') - } - }, { - text: TYPO3.l10n.localize('elements_option_3'), - attributes: { - value: TYPO3.l10n.localize('elements_value_3') - } - } - ], - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Select.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-select', TYPO3.Form.Wizard.Elements.Basic.Select); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Submit.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Submit.js deleted file mode 100644 index 7e683baba6685ece03a061325b61be0e9d6f320a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Submit.js +++ /dev/null @@ -1,135 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The SUBMIT element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Submit - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Submit = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'submit', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - */ - initComponent: function() { - - // call parent - TYPO3.Form.Wizard.Elements.Basic.Submit.superclass.initComponent.apply(this, arguments); - - // Initialize events after rendering - this.on('afterrender', this.afterRender, this); - }, - - /** - * Called by the 'afterrender' event. - * - * Stop click propagation - */ - afterRender: function() { - this.getEl().addListener('click', function(e) { - if(e.type == 'click') { - e.stopEvent(); - } - }); - - // Call parent - TYPO3.Form.Wizard.Elements.Basic.Submit.superclass.afterRender.call(this); - }, - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'disabled': '', - 'name': '', - 'type': 'submit', - 'value': TYPO3.l10n.localize('tx_form_domain_model_element_submit.value') - }, - filters: {}, - label: { - value: '' - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Submit.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-submit', TYPO3.Form.Wizard.Elements.Basic.Submit); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textarea.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textarea.js deleted file mode 100644 index 267391c6ae9499ad688a96e7314942f05ab005d4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textarea.js +++ /dev/null @@ -1,118 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The TEXTAREA element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Textarea - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Textarea = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'textarea', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<textarea {[this.getAttributes(values.attributes)]}>{values.attributes.text}</textarea>', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autofocus': '', - 'cols': '40', - 'disabled': '', - 'inputmode': '', - 'maxlength': '', - 'minlength': '', - 'name': '', - 'placeholder': '', - 'readonly': '', - 'required': '', - 'rows': '5', - 'selectionDirection': '', - 'selectionEnd': '', - 'selectionStart': '', - 'text': '', - 'wrap': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Textarea.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-textarea', TYPO3.Form.Wizard.Elements.Basic.Textarea); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textline.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textline.js deleted file mode 100644 index 523f040be5cc61e1aea45fc15664411d86bdcd8e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Basic/Textline.js +++ /dev/null @@ -1,117 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Basic'); - -/** - * The TEXTLINE element - * - * @class TYPO3.Form.Wizard.Elements.Basic.Textline - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Basic.Textline = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'textline', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'front\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '<input {[this.getAttributes(values.attributes)]} />', - '<tpl for="label">', - '<tpl if="value && parent.layout == \'back\'">', - '<label for="">{value}{[this.getMessage(parent.validation)]}</label>', - '</tpl>', - '</tpl>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - 'accesskey': '', - 'class': '', - 'contenteditable': '', - 'contextmenu': '', - 'dir': '', - 'draggable': '', - 'dropzone': '', - 'hidden': '', - 'id': '', - 'lang': '', - 'spellcheck': '', - 'style': '', - 'tabindex': '', - 'title': '', - 'translate': '', - - 'autocomplete': '', - 'autofocus': '', - 'disabled': '', - 'inputmode': '', - 'list': '', - 'maxlength': '', - 'minlength': '', - 'name': '', - 'pattern': '', - 'placeholder': '', - 'readonly': '', - 'required': '', - 'size': '', - 'type': 'text', - 'value': '' - }, - filters: {}, - label: { - value: TYPO3.l10n.localize('elements_label') - }, - layout: 'front', - validation: {} - } - }); - TYPO3.Form.Wizard.Elements.Basic.Textline.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-basic-textline', TYPO3.Form.Wizard.Elements.Basic.Textline); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/ButtonGroup.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/ButtonGroup.js deleted file mode 100644 index 434f558a74e2ca259d8f43ad56aa61bfc20832e0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/ButtonGroup.js +++ /dev/null @@ -1,89 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard'); - -/** - * Button group to show on top of the form elements - * - * Most elements contain buttons to delete or edit the item. These buttons are - * grouped in this component - * - * @class TYPO3.Form.Wizard.ButtonGroup - * @extends Ext.Container - */ -TYPO3.Form.Wizard.ButtonGroup = Ext.extend(Ext.Container, { - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'buttongroup', - - /** - * @cfg {Object|Function} defaults - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - xtype: 'button', - template: new Ext.Template( - '<span id="{4}"><button type="{0}" class="{3}"></button></span>' - ), - tooltipType: 'title' - }, - - /** @cfg {Boolean} forceLayout - * If true the container will force a layout initially even if hidden or - * collapsed. This option is useful for forcing forms to render in collapsed - * or hidden containers. (defaults to false). - */ - forceLayout: true, - - /** - * Constructor - */ - initComponent: function() { - var config = { - items: [ - { - iconCls: 't3-icon t3-icon-actions t3-icon-actions-edit t3-icon-edit-delete', - tooltip: TYPO3.l10n.localize('elements_button_delete'), - handler: this.removeElement, - scope: this - }, { - iconCls: 't3-icon t3-icon-actions t3-icon-actions-document t3-icon-document-open', - tooltip: TYPO3.l10n.localize('elements_button_edit'), - handler: this.setActive, - scope: this - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.ButtonGroup.superclass.initComponent.apply(this, arguments); - }, - - /** - * Called by the click event of the remove button - * - * When clicking the remove button a confirmation will be asked by the - * container this button group is in. - */ - removeElement: function(button, event) { - event.stopPropagation(); - this.ownerCt.confirmDeleteElement(); - }, - - /** - * Called by the click event of the edit button - * - * Tells the element helper that this component is set as the active one - */ - setActive: function(button, event) { - this.ownerCt.setActive(event, event.getTarget()); - } -}); - -Ext.reg('typo3-form-wizard-buttongroup', TYPO3.Form.Wizard.ButtonGroup); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Container.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Container.js deleted file mode 100644 index 1c2080e7931b6b0000f1c37f0ede076a1a57a5ba..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Container.js +++ /dev/null @@ -1,569 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard'); - -/** - * Container abstract - * - * There are only two containers in a form, the form itself and fieldsets. - * - * @class TYPO3.Form.Wizard.Elements.Container - * @extends Ext.Container - */ -TYPO3.Form.Wizard.Container = Ext.extend(Ext.Container, { - /** - * @cfg {Mixed} autoEl - * A tag name or DomHelper spec used to create the Element which will - * encapsulate this Component. - */ - autoEl: 'ol', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'formwizard-container', - - /** - * @cfg {Object|Function} defaults - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - autoHeight: true - }, - - /** - * Constructor - * - * Add the dummy to the container - */ - constructor: function(config) { - Ext.apply(this, { - items: [ - { - xtype: 'typo3-form-wizard-elements-dummy' - } - ] - }); - TYPO3.Form.Wizard.Container.superclass.constructor.apply(this, arguments); - }, - - - /** - * Constructor - */ - initComponent: function() { - var config = {}; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Container.superclass.initComponent.apply(this, arguments); - - // Initialize the drag and drop zone after rendering - if (this.hasDragAndDrop) { - this.on('render', this.initializeDragAndDrop, this); - } - - this.on('render', this.checkOnEmpty, this); - - // Initialize the remove event, which will be fired when a component is removed from this container - this.on('remove', this.checkOnEmpty, this); - }, - - /** - * Initialize the drag and drop zones - * - * @param container - */ - initializeDragAndDrop: function(container) { - /** - * Initialize the drag zone - * - * A container can contain elements which can be moved within this and - * other (nested) containers. - */ - container.dragZone = new Ext.dd.DragZone(container.getEl(), { - /** - * Called when a mousedown occurs in this container. Looks in Ext.dd.Registry - * for a valid target to drag based on the mouse down. Override this method - * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned - * object has a "ddel" attribute (with an HTML Element) for other functions to work. - * @param {EventObject} element The mouse down event element - * @return {Object} The dragData - */ - getDragData: function(element) { - var sourceElement = element.getTarget('.formwizard-element'); - var sourceComponent = Ext.getCmp(sourceElement.id); - if (sourceElement && sourceComponent.isEditable) { - clonedElement = sourceElement.cloneNode(true); - clonedElement.id = Ext.id(); - return container.dragData = { - sourceEl: sourceElement, - repairXY: Ext.fly(sourceElement).getXY(), - ddel: clonedElement - }; - } - }, - - onStartDrag: function(x, y) { - Ext.getCmp('formwizard').addClass('hover-move'); - }, - - endDrag: function(event) { - Ext.getCmp('formwizard').removeClass('hover-move'); - }, - - /** - * Called before a repair of an invalid drop to get the XY to animate to. - * By default returns the XY of this.dragData.ddel - * @param {EventObject} e The mouse up event - * @return {Array} The xy location (e.g. [100, 200]) - */ - getRepairXY: function(e) { - return container.dragData.repairXY; - } - }); - - /** - * Initialize the drop zone - * - * A container can receive other form elements or other (nested) containers. - */ - container.dropZone = new Ext.dd.DropZone(container.getEl(), { - /** - * Returns a custom data object associated with the DOM node that is the target of the event. By default - * this looks up the event target in the Ext.dd.Registry, although you can override this method to - * provide your own custom lookup. - * - * The override has been done here to define if we are having this event on the container or a form element. - * - * @param {Event} e The event - * @return {Object} data The custom data - */ - getTargetFromEvent: function(event) { - - var containerElement = container.getEl(); - var formElementTarget = event.getTarget('.formwizard-element', 10, true); - var formContainerTarget = event.getTarget('.formwizard-container', 10, true); - var placeholderTarget = event.getTarget('#element-placeholder', 10, false); - - if (placeholderTarget) { - formElementTarget = Ext.DomQuery.selectNode('.target-hover'); - } - - if ( - container.hasDragAndDrop && - formContainerTarget && - formElementTarget && - formContainerTarget.findParentNode('li', 10, true) == formElementTarget && - formContainerTarget == containerElement - ) { - return null; - // We are having this event on a form element - } else if ( - container.hasDragAndDrop && - formElementTarget - ) { - if (placeholderTarget) { - return formElementTarget; - } - return event.getTarget('.formwizard-element'); - // We are having this event on a container - } else { - return null; - } - }, - - /** - * Called while the DropZone determines that a Ext.dd.DragSource is being dragged over it, - * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so - * it should be overridden to provide the proper feedback if necessary. - * - * And so we did ;-) We are not using containers which can receive different elements, so we always return - * Ext.dd.DropZone.prototype.dropAllowed CSS class. - * - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - * @return {String} status The CSS class that communicates the drop status back to the source so that the - * underlying Ext.dd.StatusProxy can be updated - */ - onContainerOver: function(dd, e, data) { - if (Ext.get('element-placeholder')) { - Ext.get('element-placeholder').remove(); - } - return Ext.dd.DropZone.prototype.dropAllowed; - }, - - /** - * Called when the DropZone determines that a Ext.dd.DragSource has been dropped on it, - * but not on any of its registered drop nodes. The default implementation returns false, so it should be - * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to - * be able to accept drops. It should return true when valid so that the drag source's repair action does not run. - * - * This is a tricky part. Because we are using multiple dropzones which are on top of each other, the event will - * be called multiple times, for each group one time. We cannot prevent this by disabling event bubbling and we - * dont't want to override the core of ExtJS. To prevent multiple creation of the same object, we add the variable - * 'processed' to the 'data' object. If it has been processed on drop, it will not be done a second time. - * - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - * @return {Boolean} True if the drop was valid, else false - */ - onContainerDrop: function(dd, e, data) { - if ( - container.hasDragAndDrop && - !data.processed - ) { - var dropComponent = Ext.getCmp(data.sourceEl.id); - container.dropElement(dropComponent, 'container'); - data.processed = true; - } - return true; - }, - - /** - * Called when the DropZone determines that a Ext.dd.DragSource has entered a drop node - * that has either been registered or detected by a configured implementation of getTargetFromEvent. - * This method has no default implementation and should be overridden to provide - * node-specific processing if necessary. - * - * Our implementation adds a dummy placeholder before or after the element the user is hovering over. - * This placeholder will show the user where the dragged element will be dropped in the form. - * - * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from - * getTargetFromEvent for this node) - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - */ - onNodeEnter : function(target, dd, e, data) { - if ( - Ext.get(data.sourceEl).hasClass('formwizard-element') && - target.id != data.sourceEl.id - ) { - var dropPosition = this.getDropPosition(target, dd); - if (dropPosition == 'above') { - Ext.DomHelper.insertBefore(target, { - tag: 'li', - id: 'element-placeholder', - html: ' ' - }); - } else { - Ext.DomHelper.insertAfter(target, { - tag: 'li', - id: 'element-placeholder', - html: ' ' - }); - } - Ext.fly(target).addClass('target-hover'); - } - }, - - /** - * Called when the DropZone determines that a Ext.dd.DragSource has been dragged out of - * the drop node without dropping. This method has no default implementation and should be overridden to provide - * node-specific processing if necessary. - * - * Removes the temporary placeholder and the hover class from the element - * - * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from - * getTargetFromEvent for this node) - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - */ - onNodeOut : function(target, dd, e, data) { - if ( - Ext.get(data.sourceEl).hasClass('formwizard-element') && - target.id != data.sourceEl.id - ) { - if (e.type != 'mouseup') { - if (Ext.get('element-placeholder')) { - Ext.get('element-placeholder').remove(); - } - Ext.fly(target).removeClass('target-hover'); - } - } - }, - - /** - * Called while the DropZone determines that a Ext.dd.DragSource is over a drop node - * that has either been registered or detected by a configured implementation of getTargetFromEvent. - * The default implementation returns this.dropNotAllowed, so it should be - * overridden to provide the proper feedback. - * - * Based on the cursor position on the node we are hovering over, the temporary placeholder will be put - * above or below this node. If the position changes, the placeholder will be removed and put at the - * right spot. - * - * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from - * getTargetFromEvent for this node) - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - * @return {String} status The CSS class that communicates the drop status back to the source so that the - * underlying Ext.dd.StatusProxy can be updated - */ - onNodeOver: function(target, dd, e, data) { - if ( - Ext.get(data.sourceEl).hasClass('formwizard-element') && - target.id != data.sourceEl.id - ) { - var dropPosition = this.getDropPosition(target, dd); - // The position of the target moved to the top - if ( - dropPosition == 'above' && - target.nextElementSibling && - target.nextElementSibling.id == 'element-placeholder' - ) { - Ext.get('element-placeholder').remove(); - Ext.DomHelper.insertBefore(target, { - tag: 'li', - id: 'element-placeholder', - html: ' ' - }); - } else if ( - dropPosition == 'below' && - target.previousElementSibling && - target.previousElementSibling.id == 'element-placeholder' - ) { - Ext.get('element-placeholder').remove(); - Ext.DomHelper.insertAfter(target, { - tag: 'li', - id: 'element-placeholder', - html: ' ' - }); - } - return Ext.dd.DropZone.prototype.dropAllowed; - } else { - return Ext.dd.DropZone.prototype.dropNotAllowed; - } - }, - - /** - * Called when the DropZone determines that a Ext.dd.DragSource has been dropped onto - * the drop node. The default implementation returns false, so it should be overridden to provide the - * appropriate processing of the drop event and return true so that the drag source's repair action does not run. - * - * Like onContainerDrop this is a tricky part. Because we are using multiple dropzones which are on top of each other, the event will - * be called multiple times, for each group one time. We cannot prevent this by disabling event bubbling and we - * dont't want to override the core of ExtJS. To prevent multiple creation of the same object, we add the variable - * 'processed' to the 'data' object. If it has been processed on drop, it will not be done a second time. - * - * - * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from - * getTargetFromEvent for this node) - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @param {Event} e The event - * @param {Object} data An object containing arbitrary data supplied by the drag source - * @return {Boolean} True if the drop was valid, else false - */ - onNodeDrop : function(target, dd, e, data) { - if ( - Ext.get(data.sourceEl).hasClass('formwizard-element') && - target.id != data.sourceEl.id && - !data.processed - ) { - - var dropPosition = this.getDropPosition(target, dd); - var dropComponent = Ext.getCmp(data.sourceEl.id); - container.dropElement(dropComponent, dropPosition, target); - data.processed = true; - return true; - } - }, - /** - * Defines whether we are hovering at the top or bottom half of a node - * - * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from - * getTargetFromEvent for this node) - * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone - * @return {String} above when hovering over the top half, below if at the bottom half. - */ - getDropPosition: function(target, dd) { - var top = Ext.lib.Dom.getY(target); - var bottom = top + target.offsetHeight; - var center = ((bottom - top) / 2) + top; - var yPosition = dd.lastPageY + dd.deltaY; - if (yPosition < center) { - return 'above'; - } else if (yPosition >= center) { - return 'below'; - } - } - }); - }, - - /** - * Called by the dropzones onContainerDrop or onNodeDrop. - * Adds the component to the container. - * - * This function will look if it is a new element from the left buttons, if - * it is an existing element which is moved within this or from another - * container. It also decides if it is dropped within an empty container or - * if it needs a position within the existing elements of this container. - * - * @param component - * @param position - * @param target - */ - dropElement: function(component, position, target) { - // Check if there are errors in the current active element - var optionsTabIsValid = Ext.getCmp('formwizard-left-options').tabIsValid(); - - var id = component.id; - var droppedElement = {}; - - if (Ext.get('element-placeholder')) { - Ext.get('element-placeholder').remove(); - } - // Only add or move an element when there is no error in the current active element - if (optionsTabIsValid) { - // New element in container - if (position == 'container') { - // Check if the dummy is present, which means there are no elements - var dummy = this.findById('dummy'); - if (dummy) { - this.remove(dummy, true); - } - // Add the new element to the container - if (component.xtype != 'button') { - droppedElement = this.add( - component - ); - } else { - droppedElement = this.add({ - xtype: 'typo3-form-wizard-elements-' + id - }); - } - - // Moved an element within this container - } else if (this.findById(id)) { - droppedElement = this.findById(id); - var movedElementIndex = 0; - var targetIndex = this.items.findIndex('id', target.id); - - if (position == 'above') { - movedElementIndex = targetIndex; - } else { - movedElementIndex = targetIndex + 1; - } - - // Tricky part, because this.remove does not remove the DOM element - // See http://www.sencha.com/forum/showthread.php?102190 - // 1. remove component from container w/o destroying (2nd argument false) - // 2. remove component's element from container and append it to body - // 3. add/insert the component to the correct place back in the container - // 4. call doLayout() on the container - this.remove(droppedElement, false); - var element = Ext.get(droppedElement.id); - element.appendTo(Ext.getBody()); - - this.insert( - movedElementIndex, - droppedElement - ); - - // New element for this container coming from another one - } else { - var index = 0; - var targetIndex = this.items.findIndex('id', target.id); - - if (position == 'above') { - index = targetIndex; - } else { - index = targetIndex + 1; - } - - // Element moved - if (component.xtype != 'button') { - droppedElement = this.insert( - index, - component - ); - // Coming from buttons - } else { - droppedElement = this.insert( - index, - { - xtype: 'typo3-form-wizard-elements-' + id - } - ); - } - } - this.doLayout(); - TYPO3.Form.Wizard.Helpers.History.setHistory(); - TYPO3.Form.Wizard.Helpers.Element.setActive(droppedElement); - - // The current active element has errors, show it! - } else { - Ext.MessageBox.show({ - title: TYPO3.l10n.localize('options_error'), - msg: TYPO3.l10n.localize('options_error_message'), - icon: Ext.MessageBox.ERROR, - buttons: Ext.MessageBox.OK - }); - } - }, - - /** - * Remove the element from this container - * - * @param element - */ - removeElement: function(element) { - this.remove(element); - TYPO3.Form.Wizard.Helpers.History.setHistory(); - }, - - /** - * Called by the 'remove' event of this container. - * - * If an item has been removed from this container, except for the dummy - * element, it will look if there are other items existing. If not, it will - * put the dummy in this container to tell the user the container needs items. - * - * @param container - * @param component - */ - checkOnEmpty: function(container, component) { - if (component && component.id != 'dummy' || !component) { - if (this.items.getCount() == 0) { - this.add({ - xtype: 'typo3-form-wizard-elements-dummy' - }); - this.doLayout(); - } - } - }, - - /** - * Called by the parent of this component when a change has been made in the - * form. - * - * Constructs an array out of this component and the children to add it to - * the history or to use when saving the form - * - * @returns {Array} - */ - getConfiguration: function() { - var historyConfiguration = { - hasDragAndDrop: this.hasDragAndDrop - }; - - if (this.items) { - historyConfiguration.items = []; - this.items.each(function(item, index, length) { - historyConfiguration.items.push(item.getConfiguration()); - }, this); - } - return historyConfiguration; - } -}); - -Ext.reg('typo3-form-wizard-container', TYPO3.Form.Wizard.Container); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Header.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Header.js deleted file mode 100644 index 3713f8506983842d95e1e5a7e39d9d6f0ead39a6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Header.js +++ /dev/null @@ -1,71 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Content'); - -/** - * The content HEADER element - * - * @class TYPO3.Form.Wizard.Elements.Content.Header - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Content.Header = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'header', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="various">', - '<{headingSize} {[this.getAttributes(parent.attributes)]}>', - '{content}', - '</{type}>', - '</tpl>', - '</div>', - { - compiled: true, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - "class": 'content-header', - dir: '', - id: '', - lang: '', - style: '', - title: '' - }, - various: { - headingSize: 'h1', - content: TYPO3.l10n.localize('elements_header_content') - } - } - }); - TYPO3.Form.Wizard.Elements.Content.Header.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-content-header', TYPO3.Form.Wizard.Elements.Content.Header); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js deleted file mode 100644 index 01f5ee01763c888b893c2229c4827e8d32ef4c3f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Content/Textblock.js +++ /dev/null @@ -1,70 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Content'); - -/** - * The content HEADER element - * - * @class TYPO3.Form.Wizard.Elements.Content.Header - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Content.Textblock = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} elementClass - * An extra CSS class that will be added to this component's Element - */ - elementClass: 'textblock', - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<tpl for="various">', - '<div {[this.getAttributes(parent.attributes)]}>', - '{text:nl2br}', - '</{type}>', - '</tpl>', - '</div>', - { - compiled: true, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - attributes: { - "class": '', - dir: '', - id: '', - lang: '', - style: '', - title: '' - }, - various: { - text: TYPO3.l10n.localize('elements_textblock_content') - } - } - }); - TYPO3.Form.Wizard.Elements.Content.Textblock.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-content-textblock', TYPO3.Form.Wizard.Elements.Content.Textblock); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Dummy.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Dummy.js deleted file mode 100644 index b7ec2e97868abe1f69b6e2b66657fd7068b4f62e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Dummy.js +++ /dev/null @@ -1,69 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements'); - -/** - * The dummy element - * - * This type will be shown when there is no element in a container which will be - * form or fieldset and will be removed when there is an element added. - * - * @class TYPO3.Form.Wizard.Elements.Dummy - * @extends TYPO3.Form.Wizard.Elements - */ -TYPO3.Form.Wizard.Elements.Dummy = Ext.extend(TYPO3.Form.Wizard.Elements, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'dummy', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'dummy typo3-message message-information', - - /** - * @cfg {Object} configuration - * The configuration of this element. - * This object contains the configuration of this component. It will be - * copied to the 'data' variable before rendering. 'data' is deleted after - * rendering the xtemplate, so we need a copy. - */ - configuration: { - title: TYPO3.l10n.localize('elements_dummy_title'), - description: TYPO3.l10n.localize('elements_dummy_description') - }, - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<p><strong>{title}</strong></p>', - '<p>{description}</p>' - ), - - /** - * @cfg {Boolean} isEditable - * Defines whether the element is editable. If the item is editable, - * a button group with remove and edit buttons will be added to this element - * and when the the element is clicked, an event is triggered to edit the - * element. Some elements, like the dummy, don't need this. - */ - isEditable: false -}); - -Ext.reg('typo3-form-wizard-elements-dummy', TYPO3.Form.Wizard.Elements.Dummy); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Elements.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Elements.js deleted file mode 100644 index d20e373721462d0455954b17f4324ef8a4de7250..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Elements.js +++ /dev/null @@ -1,301 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements'); - -/** - * Elements abstract - * - * @class TYPO3.Form.Wizard.Elements - * @extends Ext.Container - */ -TYPO3.Form.Wizard.Elements = Ext.extend(Ext.Container, { - /** - * @cfg {Mixed} autoEl - * A tag name or DomHelper spec used to create the Element which will - * encapsulate this Component. - */ - autoEl: 'li', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'formwizard-element', - - /** - * @cfg {Object} buttonGroup - * Reference to the button group - */ - buttonGroup: null, - - /** - * @cfg {Boolean} isEditable - * Defines whether the element is editable. If the item is editable, - * a button group with remove and edit buttons will be added to this element - * and when the the element is clicked, an event is triggered to edit the - * element. Some elements, like the dummy, don't need this. - */ - isEditable: true, - - /** - * @cfg {Object} configuration - * The configuration of this element. - * This object contains the configuration of this component. It will be - * copied to the 'data' variable before rendering. 'data' is deleted after - * rendering the xtemplate, so we need a copy. - */ - configuration: {}, - - /** - * Constructor - */ - initComponent: function() { - this.addEvents({ - 'configurationChange': true - }); - - var config = {}; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Elements.superclass.initComponent.apply(this, arguments); - - // Add the elementClass to the component - this.addClass(this.elementClass); - - // Add the listener setactive for the element helper - TYPO3.Form.Wizard.Helpers.Element.on('setactive', this.toggleActive, this); - - // Set the data before rendering - this.on('beforerender', this.beforeRender, this); - - // Initialize events after rendering - this.on('afterrender', this.makeEditable, this); - - // Remove event listeners after the detruction of this component - this.on('destroy', this.onDestroy, this); - }, - - /** - * Copy this.configuration to this.data before rendering - * - * When using tpl together with data, the data variable will be deleted - * after rendering the component. We do not want to lose this data, so we - * store it in a different variable 'configuration' which will be copied to - * data just before rendering - * - * All strings within the configuration object are HTML encoded first before - * displaying - * - * @param component This component - */ - beforeRender: function(component) { - this.data = this.encodeConfiguration(this.configuration); - }, - - /** - * Html encode all strings in the configuration of an element - * - * @param unencodedData The configuration object - * @returns {Object} - */ - encodeConfiguration: function(unencodedData) { - var encodedData = {}; - - Ext.iterate(unencodedData, function (key, value, object) { - if (Ext.isString(value)) { - encodedData[key] = Ext.util.Format.htmlEncode(value); - } else if (Ext.isObject(value)) { - encodedData[key] = this.encodeConfiguration(value); - } else { - encodedData[key] = value; - } - }, this); - - return encodedData; - }, - - /** - * Add the buttongroup and a click event listener to this component when the - * component is editable. - */ - makeEditable: function() { - if (this.isEditable) { - if (!this.buttonGroup) { - this.add({ - xtype: 'typo3-form-wizard-buttongroup', - ref: 'buttonGroup' - }); - } - this.el.un('click', this.setActive, this); - this.el.on('click', this.setActive, this); - // Add hover class. Normally this would be done with overCls, - // but this does not take bubbling (propagation) into account - this.el.hover( - function(){ - Ext.fly(this).addClass('hover'); - }, - function(){ - Ext.fly(this).removeClass('hover'); - }, - this.el, - { - stopPropagation: true - } - ); - } - }, - - /** - * Called on a click event of this component or when the element is added - * - * Tells the element helper that this component is set as the active one and - * swallows the click event to prevent bubbling - * - * @param event - * @param target - * @param object - */ - setActive: function(event, target, object) { - TYPO3.Form.Wizard.Helpers.Element.setActive(this); - event.stopPropagation(); - }, - - /** - * Called when the element helper is firing the setactive event - * - * Adds an extra class 'active' to the element when the current component is - * the active one, otherwise removes the class 'active' when this component - * has this class - * @param component - */ - toggleActive: function(component) { - if (this.isEditable) { - var element = this.getEl(); - - if (component && component.getId() == this.getId()) { - if (!element.hasClass('active')) { - element.addClass('active'); - } - } else if (element.hasClass('active')) { - element.removeClass('active'); - } - } - }, - - /** - * Display a confirmation box when the delete button has been pressed. - * - * @param event - * @param target - * @param object - */ - confirmDeleteElement: function(event, target, object) { - Ext.MessageBox.confirm( - TYPO3.l10n.localize('elements_confirm_delete_title'), - TYPO3.l10n.localize('elements_confirm_delete_description'), - this.deleteElement, - this - ); - }, - - /** - * Delete the component when the yes button of the confirmation box has been - * pressed. - * - * @param button The button which has been pressed (yes / no) - */ - deleteElement: function(button) { - if (button == 'yes') { - this.ownerCt.removeElement(this); - } - }, - - /** - * Called by the parent of this component when a change has been made in the - * form. - * - * Constructs an array out of this component and the children to add it to - * the history or to use when saving the form - * - * @returns {Array} - */ - getConfiguration: function() { - var historyConfiguration = { - configuration: this.configuration, - isEditable: this.isEditable, - xtype: this.xtype - }; - - if (this.containerComponent) { - historyConfiguration.elementContainer = this.containerComponent.getConfiguration(); - } - return historyConfiguration; - }, - - /** - * Called when a configuration property has changed in the options tab - * - * Overwrites the configuration with the configuration from the form, - * adds a new snapshot to the history and renders this component again. - * @param formConfiguration - */ - setConfigurationValue: function(formConfiguration) { - Ext.merge(this.configuration, formConfiguration); - TYPO3.Form.Wizard.Helpers.History.setHistory(); - this.rendered = false; - this.render(); - this.doLayout(); - this.fireEvent('configurationChange', this); - }, - - /** - * Remove a validation rule from this element - * - * @param type - */ - removeValidationRule: function(type) { - if (this.configuration.validation[type]) { - delete this.configuration.validation[type]; - TYPO3.Form.Wizard.Helpers.History.setHistory(); - if (this.xtype != 'typo3-form-wizard-elements-basic-form') { - this.rendered = false; - this.render(); - this.doLayout(); - } - } - }, - - /** - * Remove a filter from this element - * - * @param type - */ - removeFilter: function(type) { - if (this.configuration.filters[type]) { - delete this.configuration.filters[type]; - TYPO3.Form.Wizard.Helpers.History.setHistory(); - if (this.xtype != 'typo3-form-wizard-elements-basic-form') { - this.rendered = false; - this.render(); - this.doLayout(); - } - } - }, - - /** - * Fires after the component is destroyed. - * - * Removes the listener for the 'setactive' event of the element helper. - * Tells the element helper this element is destroyed and if set active, - * it should be unset as active. - */ - onDestroy: function() { - TYPO3.Form.Wizard.Helpers.Element.un('setactive', this.toggleActive, this); - TYPO3.Form.Wizard.Helpers.Element.unsetActive(this); - } -}); - -Ext.reg('typo3-form-wizard-elements',TYPO3.Form.Wizard.Elements); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/CheckboxGroup.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/CheckboxGroup.js deleted file mode 100644 index eb7bb3d25105a41d03b1ffe004a439dc7e468d40..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/CheckboxGroup.js +++ /dev/null @@ -1,154 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Predefined'); - -/** - * The predefined CHECKBOX GROUP element - * - * @class TYPO3.Form.Wizard.Elements.Predefined.CheckboxGroup - * @extends TYPO3.Form.Wizard.Elements.Basic.Fieldset - */ -TYPO3.Form.Wizard.Elements.Predefined.CheckboxGroup = Ext.extend(TYPO3.Form.Wizard.Elements.Basic.Fieldset, { - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<fieldset {[this.getAttributes(values.attributes)]}>', - '<tpl for="legend">', - '<tpl if="value">', - '<legend>{value}{[this.getMessage(parent.validation)]}</legend>', - '</tpl>', - '</tpl>', - '<ol></ol>', - '</fieldset>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Initialize the component - */ - initComponent: function() { - var config = { - elementContainer: { - hasDragAndDrop: false - }, - configuration: { - attributes: { - "class": 'fieldset-subgroup', - dir: '', - id: '', - lang: '', - style: '' - }, - legend: { - value: TYPO3.l10n.localize('elements_legend') - }, - options: [ - { - text: TYPO3.l10n.localize('elements_option_1'), - attributes: { - value: TYPO3.l10n.localize('elements_value_1') - } - },{ - text: TYPO3.l10n.localize('elements_option_2'), - attributes: { - value: TYPO3.l10n.localize('elements_value_2') - } - },{ - text: TYPO3.l10n.localize('elements_option_3'), - attributes: { - value: TYPO3.l10n.localize('elements_value_3') - } - } - ], - various: { - name: '' - }, - validation: {} - } - }; - - // apply config - Ext.apply(this, Ext.apply(config, this.initialConfig)); - - // call parent - TYPO3.Form.Wizard.Elements.Predefined.CheckboxGroup.superclass.initComponent.apply(this, arguments); - - this.on('configurationChange', this.rebuild, this); - - this.on('afterrender', this.rebuild, this); - }, - - /** - * Add the radio buttons to the containerComponent of this fieldset, - * according to the configuration options. - * - * @param component - */ - rebuild: function(component) { - this.containerComponent.removeAll(); - if (this.configuration.options.length > 0) { - var dummy = this.containerComponent.findById('dummy'); - if (dummy) { - this.containerComponent.remove(dummy, true); - } - Ext.each(this.configuration.options, function(option, index, length) { - var checkbox = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-checkbox', - isEditable: false, - cls: '' - }); - var optionValue = ''; - if (option.attributes && option.attributes.value) { - optionValue = option.attributes.value; - } - var checkboxConfiguration = { - label: { - value: option.text - }, - attributes: { - value: optionValue - } - }; - if ( - option.attributes && - option.attributes.selected && - option.attributes.selected == 'selected' - ) { - checkboxConfiguration.attributes.checked = 'checked'; - } - Ext.merge(checkbox.configuration, checkboxConfiguration); - }, this); - this.containerComponent.doLayout(); - } - } -}); - -Ext.reg('typo3-form-wizard-elements-predefined-checkboxgroup', TYPO3.Form.Wizard.Elements.Predefined.CheckboxGroup); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Email.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Email.js deleted file mode 100644 index 84eb97adfc56040705c53585de83740f03b2278b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Email.js +++ /dev/null @@ -1,46 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Predefined'); - -/** - * The predefined EMAIL element - * - * @class TYPO3.Form.Wizard.Elements.Predefined.Email - * @extends TYPO3.Form.Wizard.Elements.Basic.Textline - */ -TYPO3.Form.Wizard.Elements.Predefined.Email = Ext.extend(TYPO3.Form.Wizard.Elements.Basic.Textline, { - /** - * Initialize the component - */ - initComponent: function() { - var config = { - configuration: { - attributes: { - name: 'email', - type: 'email' - }, - label: { - value: TYPO3.l10n.localize('elements_label_email') - }, - validation: { - required: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_required.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_required.error') - }, - email: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_email.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_email.error') - } - } - } - }; - - // MERGE config - Ext.merge(this, config); - - // call parent - TYPO3.Form.Wizard.Elements.Predefined.Email.superclass.initComponent.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-elements-predefined-email', TYPO3.Form.Wizard.Elements.Predefined.Email); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Name.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Name.js deleted file mode 100644 index 8cc1437d3b3d636f72f6f1da9c6c7c45be7ad954..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/Name.js +++ /dev/null @@ -1,156 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Predefined'); - -/** - * The predefined NAME element - * - * @class TYPO3.Form.Wizard.Elements.Predefined.Name - * @extends TYPO3.Form.Wizard.Elements.Basic.Fieldset - */ -TYPO3.Form.Wizard.Elements.Predefined.Name = Ext.extend(TYPO3.Form.Wizard.Elements.Basic.Fieldset, { - /** - * Initialize the component - */ - initComponent: function() { - var config = { - configuration: { - attributes: { - "class": 'predefined-name fieldset-subgroup fieldset-horizontal label-below', - dir: '', - id: '', - lang: '', - style: '' - }, - legend: { - value: TYPO3.l10n.localize('elements_legend_name') - }, - various: { - prefix: true, - suffix: true, - middleName: true - } - } - }; - - // apply config - Ext.apply(this, Ext.apply(config, this.initialConfig)); - - // call parent - TYPO3.Form.Wizard.Elements.Predefined.Name.superclass.initComponent.apply(this, arguments); - - this.on('configurationChange', this.rebuild, this); - - this.on('afterrender', this.rebuild, this); - }, - - /** - * Add the fields to the containerComponent of this fieldset, - * according to the configuration options. - * - * @param component - */ - rebuild: function(component) { - this.containerComponent.removeAll(); - var dummy = this.containerComponent.findById('dummy'); - if (dummy) { - this.containerComponent.remove(dummy, true); - } - if (this.configuration.various.prefix) { - var prefix = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-textline', - isEditable: false, - cls: '', - configuration: { - label: { - value: TYPO3.l10n.localize('elements_label_prefix') - }, - attributes: { - name: 'prefix', - size: 4 - }, - layout: 'back' - } - }); - } - var firstName = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-textline', - isEditable: false, - cls: '', - configuration: { - label: { - value: TYPO3.l10n.localize('elements_label_firstname') - }, - attributes: { - name: 'firstName', - size: 10 - }, - layout: 'back', - validation: { - required: { - showMessage: true, - message: '*', - error: 'Required' - } - } - } - }); - if (this.configuration.various.middleName) { - var middleName = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-textline', - isEditable: false, - cls: '', - configuration: { - label: { - value: TYPO3.l10n.localize('elements_label_middlename') - }, - attributes: { - name: 'middleName', - size: 6 - }, - layout: 'back' - } - }); - } - var lastName = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-textline', - isEditable: false, - cls: '', - configuration: { - label: { - value: TYPO3.l10n.localize('elements_label_lastname') - }, - attributes: { - name: 'lastName', - size: 15 - }, - layout: 'back', - validation: { - required: { - showMessage: true, - message: '*', - error: 'Required' - } - } - } - }); - if (this.configuration.various.suffix) { - var suffix = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-textline', - isEditable: false, - cls: '', - configuration: { - label: { - value: TYPO3.l10n.localize('elements_label_suffix') - }, - attributes: { - name: 'suffix', - size: 4 - }, - layout: 'back' - } - }); - } - this.containerComponent.doLayout(); - } -}); - -Ext.reg('typo3-form-wizard-elements-predefined-name', TYPO3.Form.Wizard.Elements.Predefined.Name); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/RadioGroup.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/RadioGroup.js deleted file mode 100644 index f93d1470fdc8120d5dea68c221bb6154415dd079..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Elements/Predefined/RadioGroup.js +++ /dev/null @@ -1,154 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Elements.Predefined'); - -/** - * The predefined RADIO GROUP element - * - * @class TYPO3.Form.Wizard.Elements.Predefined.RadioGroup - * @extends TYPO3.Form.Wizard.Elements.Basic.Fieldset - */ -TYPO3.Form.Wizard.Elements.Predefined.RadioGroup = Ext.extend(TYPO3.Form.Wizard.Elements.Basic.Fieldset, { - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<div class="overflow-hidden">', - '<fieldset {[this.getAttributes(values.attributes)]}>', - '<tpl for="legend">', - '<tpl if="value">', - '<legend>{value}{[this.getMessage(parent.validation)]}</legend>', - '</tpl>', - '</tpl>', - '<ol></ol>', - '</fieldset>', - '</div>', - { - compiled: true, - getMessage: function(rules) { - var messageHtml = ''; - var messages = []; - Ext.iterate(rules, function(rule, configuration) { - if (configuration.showMessage) { - messages.push(configuration.message); - } - }, this); - - messageHtml = ' <em>' + messages.join(', ') + '</em>'; - return messageHtml; - - }, - getAttributes: function(attributes) { - var attributesHtml = ''; - Ext.iterate(attributes, function(key, value) { - if (value) { - attributesHtml += key + '="' + value + '" '; - } - }, this); - return attributesHtml; - } - } - ), - - /** - * Initialize the component - */ - initComponent: function() { - var config = { - elementContainer: { - hasDragAndDrop: false - }, - configuration: { - attributes: { - "class": 'fieldset-subgroup', - dir: '', - id: '', - lang: '', - style: '' - }, - legend: { - value: TYPO3.l10n.localize('elements_legend') - }, - options: [ - { - text: TYPO3.l10n.localize('elements_option_1'), - attributes: { - value: TYPO3.l10n.localize('elements_value_1') - } - },{ - text: TYPO3.l10n.localize('elements_option_2'), - attributes: { - value: TYPO3.l10n.localize('elements_value_2') - } - },{ - text: TYPO3.l10n.localize('elements_option_3'), - attributes: { - value: TYPO3.l10n.localize('elements_value_3') - } - } - ], - various: { - name: '' - }, - validation: {} - } - }; - - // apply config - Ext.apply(this, Ext.apply(config, this.initialConfig)); - - // call parent - TYPO3.Form.Wizard.Elements.Predefined.RadioGroup.superclass.initComponent.apply(this, arguments); - - this.on('configurationChange', this.rebuild, this); - - this.on('afterrender', this.rebuild, this); - }, - - /** - * Add the radio buttons to the containerComponent of this fieldset, - * according to the configuration options. - * - * @param component - */ - rebuild: function(component) { - this.containerComponent.removeAll(); - if (this.configuration.options.length > 0) { - var dummy = this.containerComponent.findById('dummy'); - if (dummy) { - this.containerComponent.remove(dummy, true); - } - Ext.each(this.configuration.options, function(option, index, length) { - var radio = this.containerComponent.add({ - xtype: 'typo3-form-wizard-elements-basic-radio', - isEditable: false, - cls: '' - }); - var optionValue = ''; - if (option.attributes && option.attributes.value) { - optionValue = option.attributes.value; - } - var radioConfiguration = { - label: { - value: option.text - }, - attributes: { - value: optionValue - } - }; - if ( - option.attributes && - option.attributes.selected && - option.attributes.selected == 'selected' - ) { - radioConfiguration.attributes.checked = 'checked'; - } - Ext.merge(radio.configuration, radioConfiguration); - }, this); - this.containerComponent.doLayout(); - } - } -}); - -Ext.reg('typo3-form-wizard-elements-predefined-radiogroup', TYPO3.Form.Wizard.Elements.Predefined.RadioGroup); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/Element.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/Element.js deleted file mode 100644 index 2b38ef26f9632f36a5282170eb5e704007cafbaf..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/Element.js +++ /dev/null @@ -1,71 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Helpers'); - -TYPO3.Form.Wizard.Helpers.Element = Ext.extend(Ext.util.Observable, { - /** - * @cfg {Object} active - * The current active form element - */ - active: null, - - /** - * Constructor - * - * @param config - */ - constructor: function(config){ - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'setactive': true - }); - - // Call our superclass constructor to complete construction process. - TYPO3.Form.Wizard.Helpers.Element.superclass.constructor.call(this, config); - }, - - /** - * Fires the setactive event when a component is set as active - * - * @param component - */ - setActive: function(component) { - var optionsTabIsValid = Ext.getCmp('formwizard-left-options').tabIsValid(); - - if (optionsTabIsValid) { - if (component == this.active) { - this.active = null; - } else { - this.active = component; - } - this.fireEvent('setactive', this.active); - } else { - Ext.MessageBox.show({ - title: TYPO3.l10n.localize('options_error'), - msg: TYPO3.l10n.localize('options_error_message'), - icon: Ext.MessageBox.ERROR, - buttons: Ext.MessageBox.OK - }); - } - }, - - /** - * Fires the setactive event when a component is unset. - * - * This means when the element is destroyed or when the form is reloaded - * using undo or redo - * - * @param component - */ - unsetActive: function(component) { - if ( - this.active && ( - (component && component.getId() == this.active.getId()) || - !component - ) - ){ - this.active = null; - this.fireEvent('setactive'); - } - } -}); - -TYPO3.Form.Wizard.Helpers.Element = new TYPO3.Form.Wizard.Helpers.Element(); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/History.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/History.js deleted file mode 100644 index a92be63cc7e88fa8b5715d020917654f822c099f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Helpers/History.js +++ /dev/null @@ -1,139 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Helpers'); - -TYPO3.Form.Wizard.Helpers.History = Ext.extend(Ext.util.Observable, { - /** - * @cfg {Integer} maximum - * Maximum steps to go back or forward in history - */ - maximum: 20, - - /** - * @cfg {Integer} marker - * The current step in the history - */ - marker: 0, - - /** - * @cfg {Array} history - * Holds the configuration for each step in history - */ - history: [], - - /** - * #cfg {String} undoButtonId - * The id of the undo button - */ - undoButtonId: 'formwizard-history-undo', - - /** - * #cfg {String} redoButtonId - * The id of the redo button - */ - redoButtonId: 'formwizard-history-redo', - - /** - * Constructor - * - * @param config - */ - constructor: function(config){ - // Call our superclass constructor to complete construction process. - TYPO3.Form.Wizard.Helpers.History.superclass.constructor.call(this, config); - }, - - /** - * Called when a component is added to a container or there was a change in - * one of the form components - * - * Gets the configuration of all (nested) components, starting at - * viewport-right, and adds this configuration to the history - * - * @returns {void} - */ - setHistory: function() { - var configuration = Ext.getCmp('formwizard-right').getConfiguration(); - this.addToHistory(configuration); - }, - - /** - * Add a snapshot to the history - * - * @param {Object} configuration The form configuration snapshot - * @return {void} - */ - addToHistory: function(configuration) { - while (this.history.length > this.marker) { - this.history.pop(); - } - this.history.push(Ext.encode(configuration)); - while (this.history.length > this.maximum) { - this.history.shift(); - } - this.marker = this.history.length; - }, - - /** - * Get the current snapshot from the history - * - * @return {Object} The current snapshot - */ - refresh: function() { - var refreshObject = Ext.decode(this.history[this.marker-1]); - Ext.getCmp('formwizard-right').loadConfiguration(refreshObject); - }, - - /** - * Get the previous snapshot from the history if available - * - * Unsets the active element, because this element will not be available anymore - * - * @return {Object} The previous snapshot - */ - undo: function() { - if (this.marker >= 1) { - this.marker--; - var undoObject = Ext.decode(this.history[this.marker-1]); - Ext.getCmp('formwizard-right').loadConfiguration(undoObject); - TYPO3.Form.Wizard.Helpers.Element.unsetActive(); - } - }, - - /** - * Get the next snapshot from the history if available - * - * Unsets the active element, because this element will not be available anymore - * - * @return {Object} The next snapshot - */ - redo: function() { - if (this.history.length > this.marker) { - this.marker++; - var redoObject = Ext.decode(this.history[this.marker-1]); - Ext.getCmp('formwizard-right').loadConfiguration(redoObject); - TYPO3.Form.Wizard.Helpers.Element.unsetActive(); - } - }, - - /** - * Turn the undo/redo buttons on or off - * according to marker in the history - * - * @return {void} - */ - buttons: function() { - var undoButton = Ext.get(this.undoButtonId); - var redoButton = Ext.get(this.redoButtonId); - if (this.marker > 1) { - undoButton.show(); - } else { - undoButton.hide(); - } - if (this.history.length > this.marker) { - redoButton.show(); - } else { - redoButton.hide(); - } - } -}); - -TYPO3.Form.Wizard.Helpers.History = new TYPO3.Form.Wizard.Helpers.History(); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.FakeFormPanel.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.FakeFormPanel.js deleted file mode 100644 index dbbc63aed3583bd0e92c959d85c783872e4b4c43..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.FakeFormPanel.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.FakeFormPanel - * @extends Ext.form.FormPanel - * - * @xtype typo3-form-wizard-fakeformpanel - */ -Ext.ux.form.FakeFormPanel = Ext.extend(Ext.form.FormPanel, { - - initComponent : function(){ - this.form = this.createForm(); - Ext.FormPanel.superclass.initComponent.call(this); - - this.bodyCfg = { - tag: 'div', - cls: this.baseCls + '-body', - method : this.method || 'POST', - id : this.formId || Ext.id() - }; - if(this.fileUpload) { - this.bodyCfg.enctype = 'multipart/form-data'; - } - this.initItems(); - - this.addEvents( - 'clientvalidation' - ); - - this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']); - } - -}); - -Ext.reg('typo3-form-wizard-fakeformpanel', Ext.ux.form.FakeFormPanel); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.ValueCheckbox.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.ValueCheckbox.js deleted file mode 100644 index b40f821dc30b2baa5f9034260ffa273d0ea508d8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.ValueCheckbox.js +++ /dev/null @@ -1,21 +0,0 @@ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.ValueCheckbox - * @extends Ext.form.Checkbox - * getValue returns inputValue when checked - * - * @see TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes.initComponent - * @xtype typo3-form-wizard-valuecheckbox - */ -Ext.ux.form.ValueCheckbox = Ext.extend(Ext.form.Checkbox, { - - getValue : function(){ - var checked = Ext.ux.form.ValueCheckbox.superclass.getValue.call(this); - if(this.inputValue !== undefined && checked) - return this.inputValue; - return checked; - } -}); - -Ext.reg('typo3-form-wizard-valuecheckbox', Ext.ux.form.ValueCheckbox); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.spinnerfield.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.spinnerfield.js deleted file mode 100644 index 92765c60c004a6006bc724e92660b7e2b082cdb5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.spinnerfield.js +++ /dev/null @@ -1,62 +0,0 @@ -/*! - * Ext JS Library 3.3.1 - * Copyright(c) 2006-2010 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.SpinnerField - * @extends Ext.form.NumberField - * Creates a field utilizing Ext.ux.Spinner - * @xtype spinnerfield - */ -Ext.ux.form.SpinnerField = Ext.extend(Ext.form.NumberField, { - actionMode: 'wrap', - deferHeight: true, - autoSize: Ext.emptyFn, - // onBlur function shall use the inherited handler function - // onBlur: Ext.emptyFn, - adjustSize: Ext.BoxComponent.prototype.adjustSize, - - constructor: function(config) { - var spinnerConfig = Ext.copyTo({}, config, 'incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass'); - - var spl = this.spinner = new Ext.ux.Spinner(spinnerConfig); - - var plugins = config.plugins - ? (Ext.isArray(config.plugins) - ? config.plugins.push(spl) - : [config.plugins, spl]) - : spl; - - Ext.ux.form.SpinnerField.superclass.constructor.call(this, Ext.apply(config, {plugins: plugins})); - }, - - // private - getResizeEl: function(){ - return this.wrap; - }, - - // private - getPositionEl: function(){ - return this.wrap; - }, - - // private - alignErrorIcon: function(){ - if (this.wrap) { - this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]); - } - }, - - validateBlur: function(){ - return true; - } -}); - -Ext.reg('spinnerfield', Ext.ux.form.SpinnerField); - -//backwards compat -Ext.form.SpinnerField = Ext.ux.form.SpinnerField; diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.textfieldsubmit.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.textfieldsubmit.js deleted file mode 100644 index 8c22516c7af4bf558da2ee94f13c4bbeaf2c0ddb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.form.textfieldsubmit.js +++ /dev/null @@ -1,52 +0,0 @@ -/*! - * Ext JS Library 3.3.1 - * Copyright(c) 2006-2010 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -Ext.ns('Ext.ux.form'); - -/** - * @class Ext.ux.form.TextFieldSubmit - * @extends Ext.form.TriggerField - * Creates a text field with a submit trigger button - * @xtype textfieldsubmit - */ -Ext.ux.form.TextFieldSubmit = Ext.extend(Ext.form.TriggerField, { - hideTrigger: true, - - triggerClass: 'x-form-submit-trigger', - - enableKeyEvents: true, - - onTriggerClick: function() { - this.setHideTrigger(true); - if (this.isValid()) { - this.fireEvent('triggerclick', this); - } else { - this.setValue(this.startValue); - } - }, - - initEvents: function() { - Ext.ux.form.TextFieldSubmit.superclass.initEvents.call(this); - this.on('keyup', function(field, event) { - if (event.getKey() != event.ENTER && this.isValid()) { - this.setHideTrigger(false); - } else { - this.setHideTrigger(true); - } - }); - this.on('keypress', function(field, event) { - if (event.getKey() == event.ENTER) { - event.stopEvent(); - this.onTriggerClick(); - } - }, this); - } -}); - -Ext.reg('textfieldsubmit', Ext.ux.form.TextFieldSubmit); - -//backwards compat -Ext.form.TextFieldSubmit = Ext.ux.form.TextFieldSubmit; diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.CheckColumn.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.CheckColumn.js deleted file mode 100644 index 806364d47a23addc640a04b2e0a1c44dd11915af..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.CheckColumn.js +++ /dev/null @@ -1,84 +0,0 @@ -/*! - * Ext JS Library 3.1.1 - * Copyright(c) 2006-2010 Ext JS, LLC - * licensing@extjs.com - * http://www.extjs.com/license - */ -Ext.ns('Ext.ux.grid'); - -/** - * @class Ext.ux.grid.CheckColumn - * @extends Object - * GridPanel plugin to add a column with check boxes to a grid. - * <p>Example usage:</p> - * <pre><code> -// create the column -var checkColumn = new Ext.grid.CheckColumn({ - header: 'Indoor?', - dataIndex: 'indoor', - id: 'check', - width: 55 -}); - -// add the column to the column model -var cm = new Ext.grid.ColumnModel([{ - header: 'Foo', - ... - }, - checkColumn -]); - -// create the grid -var grid = new Ext.grid.EditorGridPanel({ - ... - cm: cm, - plugins: [checkColumn], // include plugin - ... -}); - * </code></pre> - * In addition to storing a Boolean value within the record data, this - * class toggles a css class between <tt>'x-grid3-check-col'</tt> and - * <tt>'x-grid3-check-col-on'</tt> to alter the background image used for - * a column. - */ -Ext.ux.grid.CheckColumn = function(config){ - Ext.apply(this, config); - if(!this.id){ - this.id = Ext.id(); - } - this.renderer = this.renderer.createDelegate(this); -}; - -Ext.ux.grid.CheckColumn.prototype ={ - init : function(grid){ - this.grid = grid; - this.grid.on('render', function(){ - var view = this.grid.getView(); - view.mainBody.on('mousedown', this.onMouseDown, this); - }, this); - }, - - onMouseDown : function(e, t){ - if(Ext.fly(t).hasClass(this.createId())){ - e.stopEvent(); - var index = this.grid.getView().findRowIndex(t); - var record = this.grid.store.getAt(index); - record.set(this.dataIndex, !record.data[this.dataIndex]); - } - }, - - renderer : function(v, p, record){ - p.css += ' x-grid3-check-col-td'; - return String.format('<div class="x-grid3-check-col{0} {1}"> </div>', v ? '-on' : '', this.createId()); - }, - - createId : function(){ - return 'x-grid3-cc-' + this.id; - } -}; - -// register ptype -Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn); - -// backwards compat -Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn; \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.ItemDeleter.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.ItemDeleter.js deleted file mode 100644 index bbc94fe92a4381006e2d8848092ff72df4aae656..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.ItemDeleter.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - */ -Ext.ns('Ext.ux.grid'); - -Ext.ux.grid.ItemDeleter = Ext.extend(Ext.grid.RowSelectionModel, { - width: 25, - sortable: false, - dataIndex: 0, // this is needed, otherwise there will be an error - - menuDisabled: true, - fixed: true, - id: 'deleter', - header: TYPO3.l10n.localize('fieldoptions_delete'), - - initEvents: function(){ - Ext.ux.grid.ItemDeleter.superclass.initEvents.call(this); - this.grid.on('cellclick', function(grid, rowIndex, columnIndex, e){ - if(columnIndex==grid.getColumnModel().getIndexById('deleter')) { - var record = grid.getStore().getAt(rowIndex); - grid.getStore().remove(record); - grid.getView().refresh(); - } - }); - }, - - renderer: function(v, p, record, rowIndex){ - return '<div class="remove"> </div>'; - } -}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.SingleSelectCheckColumn.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.SingleSelectCheckColumn.js deleted file mode 100644 index 6292fe6fae949bbbda313e149ee491808f090ba1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.grid.SingleSelectCheckColumn.js +++ /dev/null @@ -1,15 +0,0 @@ -Ext.ux.grid.SingleSelectCheckColumn = Ext.extend(Ext.ux.grid.CheckColumn, { - onMouseDown : function(e, t){ - if(Ext.fly(t).hasClass('x-grid3-cc-'+this.id)){ - e.stopEvent(); - var index = this.grid.getView().findRowIndex(t), - dataIndex = this.dataIndex; - this.grid.store.each(function(record, i){ - var value = (i == index && record.get(dataIndex) != true); - if(value != record.get(dataIndex)){ - record.set(dataIndex, value); - } - }); - } - } -}); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.isemptyobject.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.isemptyobject.js deleted file mode 100644 index 12235642ce3a9956648121372677c1168feb08f2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.isemptyobject.js +++ /dev/null @@ -1,8 +0,0 @@ -Ext.apply(Ext, { - isEmptyObject: function(o) { - for(var p in o) { - return false; - }; - return true; - } -}); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.merge.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.merge.js deleted file mode 100644 index 70b66c201d8e2da025853517712256ec0ce85ae5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.merge.js +++ /dev/null @@ -1,26 +0,0 @@ -Ext.apply(Ext, { - merge: function(o, c) { - if (o && c && typeof c == 'object') { - for (var p in c){ - if ((typeof o[p] == 'object') && (typeof c[p] == 'object')) { - Ext.merge(o[p], c[p]); - } else { - o[p] = c[p]; - } - } - } - return o; - }, - mergeIf: function(o, c) { - if (o && c && typeof c == 'object') { - for (var p in c){ - if ((typeof o[p] == 'object') && (typeof c[p] == 'object')) { - Ext.mergeIf(o[p], c[p]); - } else if (typeof o[p] == 'undefined') { - o[p] = c[p]; - } - } - } - return o; - } -}); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.spinner.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.spinner.js deleted file mode 100644 index edd7d1efd1a57e1fa09e9239c133a24f43c073be..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Ux/Ext.ux.spinner.js +++ /dev/null @@ -1,443 +0,0 @@ -/*! - * Ext JS Library 3.3.1 - * Copyright(c) 2006-2010 Sencha Inc. - * licensing@sencha.com - * http://www.sencha.com/license - */ -/** - * @class Ext.ux.Spinner - * @extends Ext.util.Observable - * Creates a Spinner control utilized by Ext.ux.form.SpinnerField - */ -Ext.ux.Spinner = Ext.extend(Ext.util.Observable, { - incrementValue: 1, - alternateIncrementValue: 5, - triggerClass: 'x-form-spinner-trigger', - splitterClass: 'x-form-spinner-splitter', - alternateKey: Ext.EventObject.shiftKey, - defaultValue: 0, - accelerate: false, - - constructor: function(config){ - Ext.ux.Spinner.superclass.constructor.call(this, config); - Ext.apply(this, config); - this.mimicing = false; - }, - - init: function(field){ - this.field = field; - - field.afterMethod('onRender', this.doRender, this); - field.afterMethod('onEnable', this.doEnable, this); - field.afterMethod('onDisable', this.doDisable, this); - field.afterMethod('afterRender', this.doAfterRender, this); - field.afterMethod('onResize', this.doResize, this); - field.afterMethod('onFocus', this.doFocus, this); - field.beforeMethod('onDestroy', this.doDestroy, this); - }, - - doRender: function(ct, position){ - var el = this.el = this.field.getEl(); - var f = this.field; - - if (!f.wrap) { - f.wrap = this.wrap = el.wrap({ - cls: "x-form-field-wrap" - }); - } - else { - this.wrap = f.wrap.addClass('x-form-field-wrap'); - } - - this.trigger = this.wrap.createChild({ - tag: "img", - src: Ext.BLANK_IMAGE_URL, - cls: "x-form-trigger " + this.triggerClass - }); - - if (!f.width) { - this.wrap.setWidth(el.getWidth() + this.trigger.getWidth()); - } - - this.splitter = this.wrap.createChild({ - tag: 'div', - cls: this.splitterClass, - style: 'width:13px; height:2px;' - }); - this.splitter.setRight((Ext.isIE) ? 1 : 2).setTop(10).show(); - - this.proxy = this.trigger.createProxy('', this.splitter, true); - this.proxy.addClass("x-form-spinner-proxy"); - this.proxy.setStyle('left', '0px'); - this.proxy.setSize(14, 1); - this.proxy.hide(); - this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", { - dragElId: this.proxy.id - }); - - this.initTrigger(); - this.initSpinner(); - }, - - doAfterRender: function(){ - var y; - if (Ext.isIE && this.el.getY() != (y = this.trigger.getY())) { - this.el.position(); - this.el.setY(y); - } - }, - - doEnable: function(){ - if (this.wrap) { - this.disabled = false; - this.wrap.removeClass(this.field.disabledClass); - } - }, - - doDisable: function(){ - if (this.wrap) { - this.disabled = true; - this.wrap.addClass(this.field.disabledClass); - this.el.removeClass(this.field.disabledClass); - } - }, - - doResize: function(w, h){ - if (typeof w == 'number') { - this.el.setWidth(w - this.trigger.getWidth()); - } - this.wrap.setWidth(this.el.getWidth() + this.trigger.getWidth()); - }, - - doFocus: function(){ - if (!this.mimicing) { - this.wrap.addClass('x-trigger-wrap-focus'); - this.mimicing = true; - Ext.get(Ext.isIE ? document.body : document).on("mousedown", this.mimicBlur, this, { - delay: 10 - }); - this.el.on('keydown', this.checkTab, this); - } - }, - - // private - checkTab: function(e){ - if (e.getKey() == e.TAB) { - this.triggerBlur(); - } - }, - - // private - mimicBlur: function(e){ - if (!this.wrap.contains(e.target) && this.field.validateBlur(e)) { - this.triggerBlur(); - } - }, - - // private - triggerBlur: function(){ - this.mimicing = false; - Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this); - this.el.un("keydown", this.checkTab, this); - this.field.beforeBlur(); - this.wrap.removeClass('x-trigger-wrap-focus'); - this.field.onBlur.call(this.field); - }, - - initTrigger: function(){ - this.trigger.addClassOnOver('x-form-trigger-over'); - this.trigger.addClassOnClick('x-form-trigger-click'); - }, - - initSpinner: function(){ - this.field.addEvents({ - 'spin': true, - 'spinup': true, - 'spindown': true - }); - - this.keyNav = new Ext.KeyNav(this.el, { - "up": function(e){ - e.preventDefault(); - this.onSpinUp(); - }, - - "down": function(e){ - e.preventDefault(); - this.onSpinDown(); - }, - - "pageUp": function(e){ - e.preventDefault(); - this.onSpinUpAlternate(); - }, - - "pageDown": function(e){ - e.preventDefault(); - this.onSpinDownAlternate(); - }, - - scope: this - }); - - this.repeater = new Ext.util.ClickRepeater(this.trigger, { - accelerate: this.accelerate - }); - this.field.mon(this.repeater, "click", this.onTriggerClick, this, { - preventDefault: true - }); - - this.field.mon(this.trigger, { - mouseover: this.onMouseOver, - mouseout: this.onMouseOut, - mousemove: this.onMouseMove, - mousedown: this.onMouseDown, - mouseup: this.onMouseUp, - scope: this, - preventDefault: true - }); - - this.field.mon(this.wrap, "mousewheel", this.handleMouseWheel, this); - - this.dd.setXConstraint(0, 0, 10); - this.dd.setYConstraint(1500, 1500, 10); - this.dd.endDrag = this.endDrag.createDelegate(this); - this.dd.startDrag = this.startDrag.createDelegate(this); - this.dd.onDrag = this.onDrag.createDelegate(this); - }, - - onMouseOver: function(){ - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - this.tmpHoverClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown'; - this.trigger.addClass(this.tmpHoverClass); - }, - - //private - onMouseOut: function(){ - this.trigger.removeClass(this.tmpHoverClass); - }, - - //private - onMouseMove: function(){ - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - if (((Ext.EventObject.getPageY() > middle) && this.tmpHoverClass == "x-form-spinner-overup") || - ((Ext.EventObject.getPageY() < middle) && this.tmpHoverClass == "x-form-spinner-overdown")) { - } - }, - - //private - onMouseDown: function(){ - if (this.disabled) { - return; - } - var middle = this.getMiddle(); - this.tmpClickClass = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown'; - this.trigger.addClass(this.tmpClickClass); - }, - - //private - onMouseUp: function(){ - this.trigger.removeClass(this.tmpClickClass); - }, - - //private - onTriggerClick: function(){ - if (this.disabled || this.el.dom.readOnly) { - return; - } - var middle = this.getMiddle(); - var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down'; - this['onSpin' + ud](); - }, - - //private - getMiddle: function(){ - var t = this.trigger.getTop(); - var h = this.trigger.getHeight(); - var middle = t + (h / 2); - return middle; - }, - - //private - //checks if control is allowed to spin - isSpinnable: function(){ - if (this.disabled || this.el.dom.readOnly) { - Ext.EventObject.preventDefault(); //prevent scrolling when disabled/readonly - return false; - } - return true; - }, - - handleMouseWheel: function(e){ - //disable scrolling when not focused - if (this.wrap.hasClass('x-trigger-wrap-focus') == false) { - return; - } - - var delta = e.getWheelDelta(); - if (delta > 0) { - this.onSpinUp(); - e.stopEvent(); - } else { - if (delta < 0) { - this.onSpinDown(); - e.stopEvent(); - } - } - }, - - //private - startDrag: function(){ - this.proxy.show(); - this._previousY = Ext.fly(this.dd.getDragEl()).getTop(); - }, - - //private - endDrag: function(){ - this.proxy.hide(); - }, - - //private - onDrag: function(){ - if (this.disabled) { - return; - } - var y = Ext.fly(this.dd.getDragEl()).getTop(); - var ud = ''; - - if (this._previousY > y) { - ud = 'Up'; - } //up - if (this._previousY < y) { - ud = 'Down'; - } //down - if (ud != '') { - this['onSpin' + ud](); - } - - this._previousY = y; - }, - - //private - onSpinUp: function(){ - if (this.isSpinnable() == false) { - return; - } - if (Ext.EventObject.shiftKey == true) { - this.onSpinUpAlternate(); - return; - } - else { - this.spin(false, false); - } - this.field.fireEvent("spin", this.field); - this.field.fireEvent("spinup", this.field); - }, - - //private - onSpinDown: function(){ - if (this.isSpinnable() == false) { - return; - } - if (Ext.EventObject.shiftKey == true) { - this.onSpinDownAlternate(); - return; - } - else { - this.spin(true, false); - } - this.field.fireEvent("spin", this.field); - this.field.fireEvent("spindown", this.field); - }, - - //private - onSpinUpAlternate: function(){ - if (this.isSpinnable() == false) { - return; - } - this.spin(false, true); - this.field.fireEvent("spin", this); - this.field.fireEvent("spinup", this); - }, - - //private - onSpinDownAlternate: function(){ - if (this.isSpinnable() == false) { - return; - } - this.spin(true, true); - this.field.fireEvent("spin", this); - this.field.fireEvent("spindown", this); - }, - - spin: function(down, alternate){ - var v = parseFloat(this.field.getValue()); - var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue; - (down == true) ? v -= incr : v += incr; - - v = (isNaN(v)) ? this.defaultValue : v; - v = this.fixBoundaries(v); - this.field.setRawValue(v); - }, - - fixBoundaries: function(value){ - var v = value; - - if (this.field.minValue != undefined && v < this.field.minValue) { - v = this.field.minValue; - } - if (this.field.maxValue != undefined && v > this.field.maxValue) { - v = this.field.maxValue; - } - - return this.fixPrecision(v); - }, - - // private - fixPrecision: function(value){ - var nan = isNaN(value); - if (!this.field.allowDecimals || this.field.decimalPrecision == -1 || nan || !value) { - return nan ? '' : value; - } - return parseFloat(parseFloat(value).toFixed(this.field.decimalPrecision)); - }, - - doDestroy: function(){ - if (this.trigger) { - this.trigger.remove(); - } - if (this.wrap) { - this.wrap.remove(); - delete this.field.wrap; - } - - if (this.splitter) { - this.splitter.remove(); - } - - if (this.dd) { - this.dd.unreg(); - this.dd = null; - } - - if (this.proxy) { - this.proxy.remove(); - } - - if (this.repeater) { - this.repeater.purgeListeners(); - } - if (this.mimicing){ - Ext.get(Ext.isIE ? document.body : document).un("mousedown", this.mimicBlur, this); - } - } -}); - -//backwards compat -Ext.form.Spinner = Ext.ux.Spinner; \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport.js deleted file mode 100644 index e982b3bafa76bd59801746b560403ddc7915f081..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport.js +++ /dev/null @@ -1,275 +0,0 @@ -Ext.namespace('TYPO3.Form', 'TYPO3.Form.Wizard'); - -/** - * The viewport - * - * @class TYPO3.Form.Wizard.Viewport - * @extends Ext.Container - */ -TYPO3.Form.Wizard.Viewport = Ext.extend(Ext.Container, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard', - - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Mixed} renderTo - * Specify the id of the element, a DOM element or an existing Element that - * this component will be rendered into. - */ - renderTo: 'typo3-inner-docbody', - - /** - * @cfg {String} layout - * In order for child items to be correctly sized and positioned, typically - * a layout manager must be specified through the layout configuration option. - * - * The sizing and positioning of child items is the responsibility of the - * Container's layout manager which creates and manages the type of layout - * you have in mind. - */ - layout: 'border', - - /** - * Constructor - * - * Add the left and right part to the viewport - * Add the history buttons - * @todo Move the buttons to the docheader - */ - initComponent: function() { - var config = { - items: [ - { - xtype: 'typo3-form-wizard-viewport-left' - },{ - xtype: 'typo3-form-wizard-viewport-right' - } - ] - }; - - // Add the buttons to the docheader - this.splitButtons.addPreSubmitCallback(this.save); - this.hijackTBE(); - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.superclass.initComponent.apply(this, arguments); - }, - - /** - * hijack TBE save method - */ - hijackTBE: function() { - /** - * @see TBE_EDITOR.submitForm - */ - TBE_EDITOR.submitForm = function() { - if (TBE_EDITOR.doSaveFieldName) { - document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value=1; - } - // Set a short timeout to allow other JS processes to complete, in particular those from - // EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755). - // TODO: This should be solved in a better way when this script is refactored. - window.setTimeout(function() { - var form0 = document.getElementsByName(TBE_EDITOR.formname).item(0); - if(form0 && form0.dataset.typo3_formwizard == 'wait') { - TBE_EDITOR.submitForm(); - return; - } - document.getElementsByName(TBE_EDITOR.formname).item(0).submit(); - }, 10); - } - }, - - /** - * Add the buttons to the docheader - * - * All buttons except close will be handled by the form wizard javascript - * The save and history buttons are put into separate buttongroups, click - * event listeners are added. - */ - addButtonsToDocHeader: function() { - var docHeaderRow1 = Ext.get('typo3-docheader'); - var docHeaderButtonsBar = docHeaderRow1.first('.typo3-docheader-buttons'); - var docHeaderRow1ButtonsLeft = docHeaderButtonsBar.first('.left'); - - var saveButtonGroup = Ext.DomHelper.append(docHeaderRow1ButtonsLeft, { - tag: 'div', - cls: 'buttongroup' - }); - - var save = new Ext.Element( - Ext.DomHelper.append(saveButtonGroup, { - tag: 'span', - cls: 't3-icon t3-icon-actions t3-icon-actions-document t3-icon-document-save', - id: 'formwizard-save', - title: TYPO3.l10n.localize('save') - }) - ); - - var saveAndClose = new Ext.Element( - Ext.DomHelper.append(saveButtonGroup, { - tag: 'span', - cls: 't3-icon t3-icon-actions t3-icon-actions-document t3-icon-document-save-close', - id: 'formwizard-saveandclose', - title: TYPO3.l10n.localize('saveAndClose') - }) - ); - - save.on('click', this.save, this); - saveAndClose.on('click', this.saveAndClose, this); - - var historyButtonGroup = Ext.DomHelper.append(docHeaderRow1ButtonsLeft, { - tag: 'div', - cls: 'buttongroup' - }); - - var undo = new Ext.Element( - Ext.DomHelper.append(historyButtonGroup, { - tag: 'span', - cls: 't3-icon t3-icon-actions t3-icon-actions-document t3-icon-view-go-back', - id: 'formwizard-history-undo', - title: TYPO3.l10n.localize('history_undo') - }) - ); - - var redo = new Ext.Element( - Ext.DomHelper.append(historyButtonGroup, { - tag: 'span', - cls: 't3-icon t3-icon-actions t3-icon-actions-document t3-icon-view-go-forward', - id: 'formwizard-history-redo', - title: TYPO3.l10n.localize('history_redo') - }) - ); - - undo.hide(); - undo.on('click', this.undo, this); - - redo.hide(); - redo.on('click', this.redo, this); - }, - - /** - * @returns {Element} - */ - getEditForm: function() { - return document.querySelector('[name=editform]'); - }, - - /** - * Save the form - * - * @param event - * @param element - * @param object - */ - save: function(event, element, object) { - var configuration = Ext.getCmp('formwizard-right').getConfiguration(); - var wizardUrl = TYPO3.Form.Wizard.Settings.ajaxUrl; - var url = wizardUrl.substring(wizardUrl.indexOf('&P')); - url = TYPO3.settings.ajaxUrls['formwizard_save'] + url; - - // prepare config json - var encodedConfiguration = Ext.encode(configuration); - var formData = new FormData(); - formData.append('configuration', encodedConfiguration); - formData.append('action', 'save'); - - // get domElement - var Viewport = Ext.getCmp('formwizard'); - - // synchronous ajax request - var r = new XMLHttpRequest(); - r.open("POST", url, true); - r.onreadystatechange = function () { - if (this.readyState != 4 || this.status != 200) return; - // form ready - var editForm = Viewport.getEditForm(); - if(editForm) { - editform.dataset.typo3_formwizard = 'ready'; - } - var responseObject = Ext.decode(this.responseText); - Viewport.transportEl.value = responseObject.fakeTs; - }; - // form not ready - var editForm = Viewport.getEditForm(); - if(editForm) { - editform.dataset.typo3_formwizard = 'wait'; - } - r.send(formData); - }, - - /** - * Save the form and close the wizard - * - * @param event - * @param element - * @param object - */ - saveAndClose: function(event, element, object) { - var configuration = Ext.getCmp('formwizard-right').getConfiguration(); - var url = document.location.href.substring(document.location.href.indexOf('&P')); - url = TYPO3.settings.ajaxUrls['formwizard_save'] + url; - Ext.Ajax.request({ - url: url, - method: 'POST', - params: { - configuration: Ext.encode(configuration) - }, - success: function(response, opts) { - var urlParameters = Ext.urlDecode(document.location.search.substring(1)); - document.location = urlParameters['P[returnUrl]']; - }, - failure: function(response, opts) { - Ext.MessageBox.alert( - TYPO3.l10n.localize('action_save'), - TYPO3.l10n.localize('action_save_error') + ' ' + response.status - ); - }, - scope: this - }); - }, - - /** - * Get the previous snapshot from the history if available - * - * @param event - * @param element - * @param object - */ - undo: function(event, element, object) { - TYPO3.Form.Wizard.Helpers.History.undo(); - }, - - /** - * Get the next snapshot from the history if available - * - * @param event - * @param element - * @param object - */ - redo: function(event, element, object) { - TYPO3.Form.Wizard.Helpers.History.redo(); - } -}); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left.js deleted file mode 100644 index 586d7defb1f0223e1d8b33e56d5829c63da26801..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left.js +++ /dev/null @@ -1,129 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport'); - -/** - * The tabpanel on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left - * @extends Ext.TabPanel - */ -TYPO3.Form.Wizard.Viewport.Left = Ext.extend(Ext.TabPanel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left', - - /** - * @cfg {Integer} width - * The width of this component in pixels (defaults to auto). - */ - width: 350, - - /** - * @cfg {String/Number} activeTab A string id or the numeric index of the tab that should be initially - * activated on render (defaults to undefined). - */ - activeTab: 0, - - /** - * @cfg {String} region - * Note: this config is only used when this BoxComponent is rendered - * by a Container which has been configured to use the BorderLayout - * layout manager (e.g. specifying layout:'border'). - */ - region: 'west', - - /** - * @cfg {Boolean} autoScroll - * true to use overflow:'auto' on the components layout element and show - * scroll bars automatically when necessary, false to clip any overflowing - * content (defaults to false). - */ - autoScroll: true, - - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset border, - * but this can be further altered by setting {@link #bodyBorder} to false. - */ - border: false, - - /** - * @cfg {Object|Function} defaults - * - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - autoHeight: true, - autoWidth: true - }, - - /** - * Constructor - * - * Add the tabs to the tabpanel - */ - initComponent: function() { - var allowedTabs = TYPO3.Form.Wizard.Settings.defaults.showTabs.split(/[, ]+/); - var tabs = []; - - Ext.each(allowedTabs, function(option, index, length) { - var tabXtype = 'typo3-form-wizard-viewport-left-' + option; - if (Ext.ComponentMgr.isRegistered(tabXtype)) { - tabs.push({ - xtype: tabXtype - }); - } - }, this); - - var config = { - items: tabs - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.superclass.initComponent.apply(this, arguments); - - // Set the focus when a tab has changed. We need this to remove focus from forms - this.on('tabchange', this.setFocus, this); - }, - - /** - * Set the focus to a tab - * - * doLayout is necessary, because the tabs are sometimes emptied and filled - * again, for instance by the history. Otherwise after a history undo or redo - * the options and form tabs are empty. - * - * @param tabPanel - * @param tab - */ - setFocus: function(tabPanel, tab) { - tabPanel.doLayout(); - tab.el.focus(); - }, - - /** - * Set the options tab as active tab - * - * Called by the options panel when an element has been selected - */ - setOptionsTab: function() { - this.setActiveTab('formwizard-left-options'); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left', TYPO3.Form.Wizard.Viewport.Left); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements.js deleted file mode 100644 index 72a06a0d7fb3f664acb51174b2f20e79eae1ad83..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements.js +++ /dev/null @@ -1,96 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left'); - -/** - * The elements panel in the elements tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Elements - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Elements = Ext.extend(Ext.Panel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-elements', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'x-tab-panel-body-content', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_elements'), - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var allowedAccordions = TYPO3.Form.Wizard.Settings.defaults.tabs.elements.showAccordions.split(/[, ]+/); - var accordions = []; - - Ext.each(allowedAccordions, function(option, index, length) { - var accordionXtype = 'typo3-form-wizard-viewport-left-elements-' + option; - if (Ext.ComponentMgr.isRegistered(accordionXtype)) { - accordions.push({ - xtype: accordionXtype - }); - } - }, this); - - var config = { - items: [ - { - xtype: 'container', - id: 'formwizard-left-elements-intro', - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ), - data: [{ - title: TYPO3.l10n.localize('left_elements_intro_title'), - description: TYPO3.l10n.localize('left_elements_intro_description') - }], - cls: 'formwizard-left-dummy typo3-message message-information' - }, { - xtype: 'panel', - layout: 'accordion', - border: false, - padding: 0, - defaults: { - autoHeight: true, - cls: 'x-panel-accordion' - }, - items: accordions - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Elements.superclass.initComponent.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-elements', TYPO3.Form.Wizard.Viewport.Left.Elements); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Basic.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Basic.js deleted file mode 100644 index 4f2e0fdc0f8da199f7b29f07750836e4681e4ba2..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Basic.js +++ /dev/null @@ -1,178 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Elements'); - -/** - * The basic elements in the elements tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Elements.Basic - * @extends TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup - */ -TYPO3.Form.Wizard.Viewport.Left.Elements.Basic = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-elements-basic', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_elements_basic'), - - /** - * Constructor - * - * Add the buttons to the accordion - */ - initComponent: function() { - var allowedButtons = TYPO3.Form.Wizard.Settings.defaults.tabs.elements.accordions.basic.showButtons.split(/[, ]+/); - var buttons = []; - - Ext.each(allowedButtons, function(option, index, length) { - switch (option) { - case 'button': - buttons.push({ - text: TYPO3.l10n.localize('basic_button'), - id: 'basic-button', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-button', - scope: this - }); - break; - case 'checkbox': - buttons.push({ - text: TYPO3.l10n.localize('basic_checkbox'), - id: 'basic-checkbox', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-checkbox', - scope: this - }); - break; - case 'fieldset': - buttons.push({ - text: TYPO3.l10n.localize('basic_fieldset'), - id: 'basic-fieldset', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-fieldset', - scope: this - }); - break; - case 'fileupload': - buttons.push({ - text: TYPO3.l10n.localize('basic_fileupload'), - id: 'basic-fileupload', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-fileupload', - scope: this - }); - break; - case 'hidden': - buttons.push({ - text: TYPO3.l10n.localize('basic_hidden'), - id: 'basic-hidden', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-hidden', - scope: this - }); - break; - case 'password': - buttons.push({ - text: TYPO3.l10n.localize('basic_password'), - id: 'basic-password', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-password', - scope: this - }); - break; - case 'radio': - buttons.push({ - text: TYPO3.l10n.localize('basic_radio'), - id: 'basic-radio', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-radio', - scope: this - }); - break; - case 'reset': - buttons.push({ - text: TYPO3.l10n.localize('basic_reset'), - id: 'basic-reset', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-reset', - scope: this - }); - break; - case 'select': - buttons.push({ - text: TYPO3.l10n.localize('basic_select'), - id: 'basic-select', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-select', - scope: this - }); - break; - case 'submit': - buttons.push({ - text: TYPO3.l10n.localize('basic_submit'), - id: 'basic-submit', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-submit', - scope: this - }); - break; - case 'textarea': - buttons.push({ - text: TYPO3.l10n.localize('basic_textarea'), - id: 'basic-textarea', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-textarea', - scope: this - }); - break; - case 'textline': - buttons.push({ - text: TYPO3.l10n.localize('basic_textline'), - id: 'basic-textline', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-basic-textline', - scope: this - }); - break; - } - }, this); - - var config = { - items: buttons - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Elements.Basic.superclass.initComponent.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-elements-basic', TYPO3.Form.Wizard.Viewport.Left.Elements.Basic); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/ButtonGroup.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/ButtonGroup.js deleted file mode 100644 index d7d91ed227f0b8820ef34e0fec9950904c09ce47..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/ButtonGroup.js +++ /dev/null @@ -1,122 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Elements'); - -/** - * The button group abstract for the elements tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup - * @extends Ext.ButtonGroup - */ -TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup = Ext.extend(Ext.Panel, { - /** - * @cfg {Object|Function} defaults - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - xtype: 'button', - scale: 'small', - width: 140, - iconAlign: 'left', - cls: 'formwizard-element' - }, - - cls: 'formwizard-buttongroup', - - /** - * @cfg {Boolean} autoHeight - * true to use height:'auto', false to use fixed height (defaults to false). - * Note: Setting autoHeight: true means that the browser will manage the panel's height - * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that - * manages dimensions (fit, border, etc.) then setting autoHeight: true - * can cause issues with scrolling and will not generally work as expected since the panel will take - * on the height of its contents rather than the height required by the Ext layout. - */ - autoHeight: true, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} layout - * In order for child items to be correctly sized and positioned, typically - * a layout manager must be specified through the layout configuration option. - * - * The sizing and positioning of child items is the responsibility of the - * Container's layout manager which creates and manages the type of layout - * you have in mind. - */ - layout: 'table', - - /** - * @cfg {Object} layoutConfig - * This is a config object containing properties specific to the chosen - * layout if layout has been specified as a string. - */ - layoutConfig: { - columns: 2 - }, - - /** - * Constructor - * - * Add the buttons to the accordion - */ - initComponent: function() { - var config = {}; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup.superclass.initComponent.apply(this, arguments); - - // Initialize the dragzone after rendering - this.on('render', this.initializeDrag, this); - }, - - /** - * Initialize the drag zone. - * - * @param buttonGroup - */ - initializeDrag: function(buttonGroup) { - buttonGroup.dragZone = new Ext.dd.DragZone(buttonGroup.getEl(), { - getDragData: function(element) { - var sourceElement = element.getTarget('.formwizard-element'); - if (sourceElement) { - clonedElement = sourceElement.cloneNode(true); - clonedElement.id = Ext.id(); - return buttonGroup.dragData = { - sourceEl: sourceElement, - repairXY: Ext.fly(sourceElement).getXY(), - ddel: clonedElement - }; - } - }, - getRepairXY: function() { - return buttonGroup.dragData.repairXY; - } - }); - }, - - /** - * Called when a button has been double clicked - * - * Tells the form in the right container to add a new element, according to - * the button which has been clicked. - * - * @param button - * @param event - */ - onDoubleClick: function(button, event) { - var formContainer = Ext.getCmp('formwizard-right').get(0).containerComponent; - formContainer.dropElement(button, 'container'); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-elements-buttongroup', TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Content.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Content.js deleted file mode 100644 index bfcb0c3f9da7b6e369d2c9f6e42ccb3c0ed449f1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Content.js +++ /dev/null @@ -1,78 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Elements'); - -/** - * The content elements in the elements tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Elements.Content - * @extends TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup - */ -TYPO3.Form.Wizard.Viewport.Left.Elements.Content = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-elements-content', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_elements_content'), - - /** - * Constructor - * - * Add the buttons to the accordion - */ - initComponent: function() { - var allowedButtons = TYPO3.Form.Wizard.Settings.defaults.tabs.elements.accordions.content.showButtons.split(/[, ]+/); - var buttons = []; - - Ext.each(allowedButtons, function(option, index, length) { - switch (option) { - case 'header': - buttons.push({ - text: TYPO3.l10n.localize('content_header'), - id: 'content-header', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-content-header', - scope: this - }); - break; - case 'textblock': - buttons.push({ - text: TYPO3.l10n.localize('content_textblock'), - id: 'content-textblock', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-content-textblock', - scope: this - }); - break; - } - }, this); - - var config = { - items: buttons - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Elements.Content.superclass.initComponent.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-elements-content', TYPO3.Form.Wizard.Viewport.Left.Elements.Content); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Predefined.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Predefined.js deleted file mode 100644 index d1596e90e3bc66aecbc3245f523553ff067c17a8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Elements/Predefined.js +++ /dev/null @@ -1,98 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Elements'); - -/** - * The predefined elements in the elements tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Elements.Predefined - * @extends TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup - */ -TYPO3.Form.Wizard.Viewport.Left.Elements.Predefined = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Elements.ButtonGroup, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-elements-predefined', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_elements_predefined'), - - /** - * Constructor - * - * Add the buttons to the accordion - */ - initComponent: function() { - var allowedButtons = TYPO3.Form.Wizard.Settings.defaults.tabs.elements.accordions.predefined.showButtons.split(/[, ]+/); - var buttons = []; - - Ext.each(allowedButtons, function(option, index, length) { - switch (option) { - case 'email': - buttons.push({ - text: TYPO3.l10n.localize('predefined_email'), - id: 'predefined-email', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-predefined-email', - scope: this - }); - break; - case 'radiogroup': - buttons.push({ - text: TYPO3.l10n.localize('predefined_radiogroup'), - id: 'predefined-radiogroup', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-predefined-radiogroup', - scope: this - }); - break; - case 'checkboxgroup': - buttons.push({ - text: TYPO3.l10n.localize('predefined_checkboxgroup'), - id: 'predefined-checkboxgroup', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-predefined-checkboxgroup', - scope: this - }); - break; - case 'name': - buttons.push({ - text: TYPO3.l10n.localize('predefined_name'), - id: 'predefined-name', - clickEvent: 'dblclick', - handler: this.onDoubleClick, - iconCls: 'formwizard-left-elements-predefined-name', - scope: this - }); - break; - } - }, this); - - var config = { - items: buttons - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Elements.Predefined.superclass.initComponent.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-elements-predefined', TYPO3.Form.Wizard.Viewport.Left.Elements.Predefined); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form.js deleted file mode 100644 index 89264b98544761f75a9451be85ed31f12bac0ceb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form.js +++ /dev/null @@ -1,194 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.LeftTYPO3.Form.Wizard.Elements'); - -/** - * The form tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Form = Ext.extend(Ext.Panel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-form', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'x-tab-panel-body-content', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_form'), - - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Object|Function} defaults - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - //autoHeight: true, - border: false, - padding: 0 - }, - - /** - * @cfg {Object} validAccordions - * Keeps track which accordions are valid. Accordions contain forms which - * do client validation. If there is a validation change in a form in the - * accordion, a validation event will be fired, which changes one of these - * values - */ - validAccordions: { - behaviour: true, - prefix: true, - attributes: true, - postProcessor: true - }, - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var config = { - items: [{ - xtype: 'panel', - layout: 'accordion', - ref: 'accordion', - defaults: { - autoHeight: true, - cls: 'x-panel-accordion' - } - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Form.superclass.initComponent.apply(this, arguments); - }, - - /** - * Called whenever a form has been added to the right container - * - * Sets element to the form component and calls the function to add the - * attribute fields - * - * @param form - */ - setForm: function(form) { - var allowedAccordions = TYPO3.Form.Wizard.Settings.defaults.tabs.form.showAccordions.split(/[, ]+/); - - this.accordion.removeAll(); - if (form) { - Ext.each(allowedAccordions, function(option, index, length) { - switch (option) { - case 'behaviour': - this.accordion.add({ - xtype: 'typo3-form-wizard-viewport-left-form-behaviour', - element: form, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - break; - case 'prefix': - this.accordion.add({ - xtype: 'typo3-form-wizard-viewport-left-form-prefix', - element: form, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - break; - case 'attributes': - this.accordion.add({ - xtype: 'typo3-form-wizard-viewport-left-form-attributes', - element: form, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - break; - case 'postProcessor': - this.accordion.add({ - xtype: 'typo3-form-wizard-viewport-left-form-postprocessor', - element: form, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - break; - } - }, this); - } - this.doLayout(); - }, - - /** - * Called by the validation listeners of the accordions - * - * Checks if all accordions are valid. If not, adds a class to the tab - * - * @param {String} accordion The accordion which fires the event - * @param {Boolean} isValid Accordion is valid or not - */ - validation: function(accordion, isValid) { - this.validAccordions[accordion] = isValid; - var tabIsValid = true; - Ext.iterate(this.validAccordions, function(key, value) { - if (!value) { - tabIsValid = false; - } - }, this); - if (this.tabEl) { - var tabEl = Ext.get(this.tabEl); - if (tabIsValid && tabEl.hasClass('validation-error')) { - tabEl.removeClass('validation-error'); - } else if (!tabIsValid && !tabEl.hasClass('validation-error')) { - tabEl.addClass('validation-error'); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form', TYPO3.Form.Wizard.Viewport.Left.Form); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Attributes.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Attributes.js deleted file mode 100644 index a98943f5110eff44f659857a1ab5d9d8e852987a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Attributes.js +++ /dev/null @@ -1,26 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form'); - -/** - * The attributes panel in the accordion of the form tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.Attributes - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes - */ -TYPO3.Form.Wizard.Viewport.Left.Form.Attributes = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-form-attributes' -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-attributes', TYPO3.Form.Wizard.Viewport.Left.Form.Attributes); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Behaviour.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Behaviour.js deleted file mode 100644 index f097e49376c15d3f800c315480afc29fc4b775fc..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Behaviour.js +++ /dev/null @@ -1,128 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form'); - -/** - * The behaviour panel in the accordion of the form tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-form-behaviour', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('form_behaviour'), - - /** - * @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Object} element - * The form component - */ - element: null, - - /** - * Constructor - * - * @param config - */ - constructor: function(config){ - // Call our superclass constructor to complete construction process. - TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour.superclass.constructor.call(this, config); - }, - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var config = { - items: [{ - xtype: 'fieldset', - title: '', - ref: 'fieldset', - autoHeight: true, - border: false, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'checkbox', - items: [ - { - fieldLabel: TYPO3.l10n.localize('behaviour_confirmation_page'), - name: 'confirmation', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - } - ] - }] - }; - - // Apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // Call parent - TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour.superclass.initComponent.apply(this, arguments); - - // Fill the form with the configuration values - this.fillForm(); - }, - - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - var fieldName = field.getName(); - - var formConfiguration = {}; - formConfiguration[fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - }, - - /** - * Fill the form with the configuration of the element - * - * @return void - */ - fillForm: function() { - this.getForm().setValues(this.element.configuration); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-behaviour', TYPO3.Form.Wizard.Viewport.Left.Form.Behaviour); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessor.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessor.js deleted file mode 100644 index 001bdf8d64296145334db8f7406a7e3044ba9907..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessor.js +++ /dev/null @@ -1,210 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form'); - -/** - * The post processor accordion panel in the form options in the left tabpanel - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessor - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessor = Ext.extend(Ext.Panel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('form_postprocessor'), - - /** - * @cfg {Object} validPostProcessors - * Keeps track which post processors are valid. Post processors contain forms which - * do client validation. If there is a validation change in a form in the - * post processor, a validation event will be fired, which changes one of these - * values - */ - validPostProcessors: { - mail: true - }, - - /** - * Constructor - * - * Add the post processors to the accordion - */ - initComponent: function() { - var postProcessors = this.getPostProcessorsBySettings(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - var config = { - items: [{ - xtype: 'typo3-form-wizard-viewport-left-form-postprocessors-dummy', - ref: 'dummy' - }], - tbar: [ - { - xtype: 'combo', - hideLabel: true, - name: 'postprocessor', - ref: 'postprocessor', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'postprocessor', - emptyText: TYPO3.l10n.localize('postprocessor_emptytext'), - width: 150, - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: postProcessors - }), - listeners: { - 'select': { - scope: this, - fn: this.addPostProcessor - } - } - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessor.superclass.initComponent.apply(this, arguments); - - // Initialize the post processors when they are available for this element - this.initPostProcessors(); - }, - - /** - * Called when constructing the post processor accordion - * - * Checks if the form already has post processors and loads these instead of the dummy - */ - initPostProcessors: function() { - var postProcessors = this.element.configuration.postProcessor; - if (!Ext.isEmptyObject(postProcessors)) { - this.remove(this.dummy); - Ext.iterate(postProcessors, function(key, value) { - var xtype = 'typo3-form-wizard-viewport-left-form-postprocessors-' + key; - if (Ext.ComponentMgr.isRegistered(xtype)) { - this.add({ - xtype: xtype, - element: this.element, - configuration: value, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - } - }, this); - } - }, - - /** - * Add a post processor to the list - * - * @param comboBox - * @param record - * @param index - */ - addPostProcessor: function(comboBox, record, index) { - var postProcessor = comboBox.getValue(); - var xtype = 'typo3-form-wizard-viewport-left-form-postprocessors-' + postProcessor; - - if (!Ext.isEmpty(this.findByType(xtype))) { - Ext.MessageBox.alert(TYPO3.l10n.localize('postprocessor_alert_title'), TYPO3.l10n.localize('postprocessor_alert_description')); - } else { - this.remove(this.dummy); - - this.add({ - xtype: xtype, - element: this.element, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - this.doLayout(); - } - }, - - /** - * Remove a post processor from the list - * - * Shows dummy when there is no post processor for the form - * - * @param component - */ - removePostProcessor: function(component) { - this.remove(component); - this.validation(component.processor, true); - if (this.items.length == 0) { - this.add({ - xtype: 'typo3-form-wizard-viewport-left-form-postprocessors-dummy', - ref: 'dummy' - }); - } - this.doLayout(); - }, - - getPostProcessorsBySettings: function() { - var postProcessors = []; - - var allowedPostProcessors = []; - try { - allowedPostProcessors = TYPO3.Form.Wizard.Settings.defaults.tabs.form.accordions.postProcessor.showPostProcessors.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedPostProcessors = [ - 'mail' - ]; - } - - Ext.iterate(allowedPostProcessors, function(item, index, allItems) { - postProcessors.push({label: TYPO3.l10n.localize('postprocessor_' + item), value: item}); - }, this); - - return postProcessors; - }, - - /** - * Called by the validation listeners of the post processors - * - * Checks if all post processors are valid. If not, adds a class to the accordion - * - * @param {String} postProcessor The post processor which fires the event - * @param {Boolean} isValid Post processor is valid or not - */ - validation: function(postProcessor, isValid) { - this.validPostProcessors[postProcessor] = isValid; - var accordionIsValid = true; - Ext.iterate(this.validPostProcessors, function(key, value) { - if (!value) { - accordionIsValid = false; - } - }, this); - if (this.el) { - if (accordionIsValid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'postProcessor', accordionIsValid); - } else if (!accordionIsValid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'postProcessor', accordionIsValid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-postprocessor', TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessor); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Dummy.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Dummy.js deleted file mode 100644 index e5e00b3426cee12b0555817d34bdfb8e313f9c87..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Dummy.js +++ /dev/null @@ -1,52 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors'); - -/** - * The dummy item when no post processor is defined for the form - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Dummy - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Dummy = Ext.extend(Ext.Panel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - cls: 'formwizard-left-dummy typo3-message message-information', - - /** - * @cfg {Mixed} data - * The initial set of data to apply to the tpl to update the content area of - * the Component. - */ - data: [{ - title: TYPO3.l10n.localize('postprocessor_dummy_title'), - description: TYPO3.l10n.localize('postprocessor_dummy_description') - }], - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ) -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-postprocessors-dummy', TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Dummy); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Mail.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Mail.js deleted file mode 100644 index 614b3089c00639af87d6153359df63b6dd1e3652..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Mail.js +++ /dev/null @@ -1,34 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors'); - -/** - * The mail post processor - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Mail - * @extends TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor - */ -TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Mail = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor, { - /** - * @cfg {String} processor - * - * The name of this processor - */ - processor: 'mail', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - recipientEmail: '', - senderEmail: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Mail.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-postprocessors-mail', TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Mail); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor.js deleted file mode 100644 index 699b27a418f256fa878fb579232c424902bff2bb..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/PostProcessor.js +++ /dev/null @@ -1,297 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors'); - -/** - * The post processor abstract - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {String} processor - * - * The name of this processor - */ - processor: '', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * Constructor - */ - initComponent: function() { - var fields = this.getFieldsBySettings(); - var formItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(fields, function(item, index, allItems) { - switch(item) { - case 'recipientEmail': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('postprocessor_properties_recipientemail'), - name: 'recipientEmail', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'senderEmail': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('postprocessor_properties_senderemail'), - name: 'senderEmail', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'subject': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('postprocessor_properties_subject'), - name: 'subject', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'destination': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('postprocessor_properties_destination'), - name: 'destination', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - } - }, this); - - formItems.push({ - xtype: 'button', - text: TYPO3.l10n.localize('button_remove'), - handler: this.removePostProcessor, - scope: this - }); - - var config = { - items: [ - { - xtype: 'fieldset', - title: TYPO3.l10n.localize('postprocessor_' + this.processor), - autoHeight: true, - defaults: { - width: 128, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Strange, but we need to call doLayout() after render - this.on('afterrender', this.newOrExistingPostProcessor, this); - }, - - /** - * Decide whether this is a new or an existing one - * - * If new, the default configuration has to be added to the processors - * of the form, otherwise we can fill the form with the existing configuration - */ - newOrExistingPostProcessor: function() { - this.doLayout(); - // Existing processor - if (this.element.configuration.postProcessor[this.processor]) { - this.fillForm(); - // New processor - } else { - this.addProcessorToElement(); - } - }, - - /** - * Fill the form with the configuration of the element - * - * When filling, the events of all form elements should be suspended, - * otherwise the values are written back to the element, for instance on a - * check event on a checkbox. - */ - fillForm: function() { - this.suspendEventsBeforeFilling(); - this.getForm().setValues(this.element.configuration.postProcessor[this.processor]); - this.resumeEventsAfterFilling(); - }, - - /** - * Suspend the events on all items within this component - */ - suspendEventsBeforeFilling: function() { - this.cascade(function(item) { - item.suspendEvents(); - }); - }, - - /** - * Resume the events on all items within this component - */ - resumeEventsAfterFilling: function() { - this.cascade(function(item) { - item.resumeEvents(); - }); - }, - - /** - * Add this processor to the element - */ - addProcessorToElement: function() { - var formConfiguration = {postProcessor: {}}; - formConfiguration.postProcessor[this.processor] = this.configuration; - - this.element.setConfigurationValue(formConfiguration); - - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {postProcessor: {}}; - formConfiguration.postProcessor[this.processor] = {}; - formConfiguration.postProcessor[this.processor][fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Remove the processor - * - * Called when the remove button of this processor has been clicked - */ - removePostProcessor: function() { - this.ownerCt.removePostProcessor(this); - this.element.removePostProcessor(this.processor); - }, - - /** - * Get the fields for the element - * - * Based on the TSconfig general allowed fields - * and the TSconfig allowed fields for this type of element - * - * @returns object - */ - getFieldsBySettings: function() { - var fields = []; - var processorFields = this.configuration; - - var allowedFields = []; - try { - allowedFields = TYPO3.Form.Wizard.Settings.defaults.tabs.form.accordions.postProcessor.postProcessors[this.processor].showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedFields = [ - 'recipientEmail', - 'senderEmail' - ]; - } - - Ext.iterate(allowedFields, function(item, index, allItems) { - fields.push(item); - }, this); - - return fields; - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', this.processor, valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', this.processor, valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-postprocessors-postprocessor', TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Redirect.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Redirect.js deleted file mode 100644 index 5ef78ddc45e08898aeb849c6253ed94c0ede0146..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/PostProcessors/Redirect.js +++ /dev/null @@ -1,33 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors'); - -/** - * The redirect post processor - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Redirect - * @extends TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor - */ -TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Redirect = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.PostProcessor, { - /** - * @cfg {String} processor - * - * The name of this processor - */ - processor: 'redirect', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - destination: '', - } - }); - TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Redirect.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-postprocessors-redirect', TYPO3.Form.Wizard.Viewport.Left.Form.PostProcessors.Redirect); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Prefix.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Prefix.js deleted file mode 100644 index 42ae6975ba42c78a28884078c3f8a4cfefe77eed..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Form/Prefix.js +++ /dev/null @@ -1,168 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Form'); - -/** - * The prefix panel in the accordion of the form tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Form.Prefix - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Form.Prefix = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-form-prefix', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('form_prefix'), - - /** @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Object} element - * The form component - */ - element: null, - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * Constructor - * - * @param config - */ - constructor: function(config){ - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - // Call our superclass constructor to complete construction process. - TYPO3.Form.Wizard.Viewport.Left.Form.Prefix.superclass.constructor.call(this, config); - }, - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var config = { - items: [{ - xtype: 'fieldset', - title: '', - ref: 'fieldset', - autoHeight: true, - border: false, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: [ - { - fieldLabel: TYPO3.l10n.localize('prefix_prefix'), - name: 'prefix', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - } - ] - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Form.Prefix.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Fill the form with the configuration values - this.fillForm(); - }, - - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {}; - formConfiguration[fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Fill the form with the configuration of the element - * - * @param record The current question - * @return void - */ - fillForm: function() { - this.getForm().setValues(this.element.configuration); - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'prefix', valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'prefix', valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-form-prefix', TYPO3.Form.Wizard.Viewport.Left.Form.Prefix); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options.js deleted file mode 100644 index 6e51602abec2628b4ab5684865e443084e9dc6a5..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options.js +++ /dev/null @@ -1,170 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.LeftTYPO3.Form.Wizard.Elements'); - -/** - * The options tab on the left side - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options = Ext.extend(Ext.Panel, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-options', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'x-tab-panel-body-content', - - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('left_options'), - - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {Object} validAccordions - * Keeps track which accordions are valid. Accordions contain forms which - * do client validation. If there is a validation change in a form in the - * accordion, a validation event will be fired, which changes one of these - * values - */ - validAccordions: { - attributes: true, - filters: true, - label: true, - legend: true, - options: true, - validation: true, - various: true - }, - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var config = { - items: [{ - xtype: 'typo3-form-wizard-viewport-left-options-dummy' - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.superclass.initComponent.apply(this, arguments); - - // if the active element changes in helper, this should be reflected here - TYPO3.Form.Wizard.Helpers.Element.on('setactive', this.toggleActive, this); - }, - - /** - * Load options form according to element type - * - * This will be called whenever the current element changes - * - * @param component The current element - * @return void - */ - toggleActive: function(component) { - if (component) { - this.removeAll(); - this.add({ - xtype: 'typo3-form-wizard-viewport-left-options-panel', - element: component, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - this.ownerCt.setOptionsTab(); - } else { - this.removeAll(); - this.add({ - xtype: 'typo3-form-wizard-viewport-left-options-dummy' - }); - } - Ext.get(this.tabEl).removeClass('validation-error'); - Ext.iterate(this.validAccordions, function(key, value) { - this.validAccordions[key] = true; - }, this); - this.doLayout(); - }, - - /** - * Checks if a tab is valid by iterating all accordions on validity - * - * @returns {Boolean} - */ - tabIsValid: function() { - var valid = true; - - Ext.iterate(this.validAccordions, function(key, value) { - if (!value) { - valid = false; - } - }, this); - - return valid; - }, - - /** - * Called by the validation listeners of the accordions - * - * Checks if all accordions are valid. If not, adds a class to the tab - * - * @param {String} accordion The accordion which fires the event - * @param {Boolean} isValid Accordion is valid or not - */ - validation: function(accordion, isValid) { - this.validAccordions[accordion] = isValid; - var tabIsValid = this.tabIsValid(); - - if (this.tabEl) { - var tabEl = Ext.get(this.tabEl); - if (tabIsValid && tabEl.hasClass('validation-error')) { - tabEl.removeClass('validation-error'); - } else if (!tabIsValid && !tabEl.hasClass('validation-error')) { - tabEl.addClass('validation-error'); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options', TYPO3.Form.Wizard.Viewport.Left.Options); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Dummy.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Dummy.js deleted file mode 100644 index 9a40ae1b74e9c494b783850616ed707f2ced94a8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Dummy.js +++ /dev/null @@ -1,65 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options'); - -/** - * The options panel for a dummy item - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Dummy - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Dummy = Ext.extend(Ext.Panel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-options-dummy', - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'formwizard-left-dummy typo3-message message-information', - - /** - * @cfg {Mixed} data - * The initial set of data to apply to the tpl to update the content area of - * the Component. - */ - data: [{ - title: TYPO3.l10n.localize('options_dummy_title'), - description: TYPO3.l10n.localize('options_dummy_description') - }], - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ) -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-dummy', TYPO3.Form.Wizard.Viewport.Left.Options.Dummy); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Attributes.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Attributes.js deleted file mode 100644 index a45bb1183d2b6f9755276e2801b4abc6859242ac..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Attributes.js +++ /dev/null @@ -1,1149 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The attributes properties of the element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_attributes'), - - /** @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfieldsubmit', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * Constructor - * - * @param config - */ - constructor: function(config){ - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - // Call our superclass constructor to complete construction process. - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes.superclass.constructor.call(this, config); - }, - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - var attributes = this.getAttributesBySettings(); - var formItems = new Array(); - - Ext.iterate(attributes, function(item, index, allItems) { - switch(item) { - case 'accept': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_accept'), - name: 'accept', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'accept-charset': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_acceptcharset'), - name: 'accept-charset', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'accesskey': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_accesskey'), - name: 'accesskey', - maxlength: 1, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'action': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_action'), - name: 'action', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'alt': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_alt'), - name: 'alt', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'autocomplete': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_autocomplete'), - name: 'autocomplete', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'autocomplete', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_autocomplete_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_autocomplete_off'), value: 'off'}, - {label: TYPO3.l10n.localize('attributes_autocomplete_on'), value: 'on'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'autofocus': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_autofocus'), - name: 'autofocus', - inputValue: 'autofocus', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'checked': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_checked'), - name: 'checked', - inputValue: 'checked', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'class': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_class'), - name: 'class', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'cols': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_cols'), - name: 'cols', - xtype: 'spinnerfield', - allowBlank: false, - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'contenteditable': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_contenteditable'), - name: 'contenteditable', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'contenteditable', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_contenteditable_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_contenteditable_true'), value: 'true'}, - {label: TYPO3.l10n.localize('attributes_contenteditable_false'), value: 'false'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'contextmenu': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_contextmenu'), - name: 'contextmenu', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'dir': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_dir'), - name: 'dir', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'dir', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_dir_ltr'), value: 'ltr'}, - {label: TYPO3.l10n.localize('attributes_dir_rtl'), value: 'rtl'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'disabled': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_disabled'), - name: 'disabled', - inputValue: 'disabled', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'draggable': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_draggable'), - name: 'draggable', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'draggable', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_draggable_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_draggable_false'), value: 'false'}, - {label: TYPO3.l10n.localize('attributes_draggable_true'), value: 'true'}, - {label: TYPO3.l10n.localize('attributes_draggable_auto'), value: 'auto'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'dropzone': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_dropzone'), - name: 'dropzone', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'enctype': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_enctype'), - name: 'enctype', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'enctype', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_enctype_1'), value: 'application/x-www-form-urlencoded'}, - {label: TYPO3.l10n.localize('attributes_enctype_2'), value: 'multipart/form-data'}, - {label: TYPO3.l10n.localize('attributes_enctype_3'), value: 'text/plain'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'height': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_height'), - name: 'height', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'hidden': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_hidden'), - name: 'hidden', - inputValue: 'hidden', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'id': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_id'), - name: 'id', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'inputmode': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_inputmode'), - name: 'inputmode', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'inputmode', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_inputmode_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_inputmode_verbatim'), value: 'verbatim'}, - {label: TYPO3.l10n.localize('attributes_inputmode_latin'), value: 'latin'}, - {label: TYPO3.l10n.localize('attributes_inputmode_latin-name'), value: 'latin-name'}, - {label: TYPO3.l10n.localize('attributes_inputmode_latin-prose'), value: 'latin-prose'}, - {label: TYPO3.l10n.localize('attributes_inputmode_full-width-latin'), value: 'full-width-latin'}, - {label: TYPO3.l10n.localize('attributes_inputmode_kana'), value: 'kana'}, - {label: TYPO3.l10n.localize('attributes_inputmode_kana-name'), value: 'kana-name'}, - {label: TYPO3.l10n.localize('attributes_inputmode_katakana'), value: 'katakana'}, - {label: TYPO3.l10n.localize('attributes_inputmode_numeric'), value: 'numeric'}, - {label: TYPO3.l10n.localize('attributes_inputmode_tel'), value: 'tel'}, - {label: TYPO3.l10n.localize('attributes_inputmode_email'), value: 'email'}, - {label: TYPO3.l10n.localize('attributes_inputmode_url'), value: 'url'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'label': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_label'), - name: 'label', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'lang': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_lang'), - name: 'lang', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'list': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_list'), - name: 'list', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'max': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_max'), - name: 'max', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'maxlength': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_maxlength'), - name: 'maxlength', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'method': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_method'), - name: 'method', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'method', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_method_get'), value: 'get'}, - {label: TYPO3.l10n.localize('attributes_method_post'), value: 'post'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'min': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_min'), - name: 'min', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'minlength': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_minlength'), - name: 'minlength', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'multiple': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_multiple'), - name: 'multiple', - inputValue: 'multiple', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'name': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_name'), - name: 'name', - allowBlank:false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'novalidate': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_novalidate'), - name: 'novalidate', - inputValue: 'novalidate', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'pattern': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_pattern'), - name: 'pattern', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'placeholder': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_placeholder'), - name: 'placeholder', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'readonly': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_readonly'), - name: 'readonly', - inputValue: 'readonly', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'required': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_required'), - name: 'required', - inputValue: 'required', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'rows': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_rows'), - name: 'rows', - xtype: 'spinnerfield', - allowBlank: false, - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'selected': - formItems.push({ - xtype: 'typo3-form-wizard-valuecheckbox', - fieldLabel: TYPO3.l10n.localize('attributes_selected'), - name: 'selected', - inputValue: 'selected', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'selectionDirection': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_selectionDirection'), - name: 'selectionDirection', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'selectionDirection', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_selectionDirection_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_selectionDirection_forward'), value: 'forward'}, - {label: TYPO3.l10n.localize('attributes_selectionDirection_backward'), value: 'backward'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'selectionEnd': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_selectionEnd'), - name: 'selectionEnd', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'selectionStart': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_selectionStart'), - name: 'selectionStart', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'size': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_size'), - name: 'size', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'spellcheck': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_spellcheck'), - name: 'spellcheck', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'spellcheck', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_spellcheck_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_spellcheck_true'), value: 'true'}, - {label: TYPO3.l10n.localize('attributes_spellcheck_false'), value: 'false'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'src': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_src'), - name: 'src', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'step': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_step'), - name: 'step', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'style': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_style'), - name: 'style', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'tabindex': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_tabindex'), - name: 'tabindex', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'text': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_text'), - xtype: 'textarea', - name: 'text', - allowBlank: true, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'title': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_title'), - name: 'title', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'translate': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_translate'), - name: 'translate', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'translate', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_translate_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_translate_no'), value: 'no'}, - {label: TYPO3.l10n.localize('attributes_translate_yes'), value: 'yes'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'type': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_type'), - name: 'type', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'type', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_type_color'), value: 'color'}, - {label: TYPO3.l10n.localize('attributes_type_date'), value: 'date'}, - {label: TYPO3.l10n.localize('attributes_type_datetime'), value: 'datetime'}, - {label: TYPO3.l10n.localize('attributes_type_datetime-local'), value: 'datetime-local'}, - {label: TYPO3.l10n.localize('attributes_type_email'), value: 'email'}, - {label: TYPO3.l10n.localize('attributes_type_month'), value: 'month'}, - {label: TYPO3.l10n.localize('attributes_type_number'), value: 'number'}, - {label: TYPO3.l10n.localize('attributes_type_search'), value: 'search'}, - {label: TYPO3.l10n.localize('attributes_type_tel'), value: 'tel'}, - {label: TYPO3.l10n.localize('attributes_type_text'), value: 'text'}, - {label: TYPO3.l10n.localize('attributes_type_time'), value: 'time'}, - {label: TYPO3.l10n.localize('attributes_type_url'), value: 'url'}, - {label: TYPO3.l10n.localize('attributes_type_week'), value: 'week'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'value': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_value'), - name: 'value', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'width': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_width'), - name: 'width', - xtype: 'spinnerfield', - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'wrap': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('attributes_wrap'), - name: 'wrap', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'wrap', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('attributes_wrap_none'), value: ''}, - {label: TYPO3.l10n.localize('attributes_wrap_soft'), value: 'soft'}, - {label: TYPO3.l10n.localize('attributes_wrap_hard'), value: 'hard'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - } - }, this); - - var config = { - items: [{ - xtype: 'fieldset', - title: '', - autoHeight: true, - border: false, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Fill the form with the configuration values - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {attributes: {}}; - formConfiguration.attributes[fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Fill the form with the configuration of the element - * - * @return void - */ - fillForm: function() { - this.getForm().setValues(this.element.configuration.attributes); - }, - - /** - * Get the attributes for the element - * - * Based on the elements attributes, the TSconfig general allowed attributes - * and the TSconfig allowed attributes for this type of element - * - * @returns object - */ - getAttributesBySettings: function() { - var attributes = []; - var elementAttributes = this.element.configuration.attributes; - var elementType = this.element.xtype.split('-').pop(); - - var allowedGeneralAttributes = []; - try { - allowedGeneralAttributes = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.attributes.showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedGeneralAttributes = [ - 'accept', - 'acceptcharset', - 'accesskey', - 'action', - 'alt', - 'checked', - 'class', - 'cols', - 'dir', - 'disabled', - 'enctype', - 'id', - 'label', - 'lang', - 'maxlength', - 'method', - 'multiple', - 'name', - 'readonly', - 'rows', - 'selected', - 'size', - 'src', - 'style', - 'tabindex', - 'title', - 'type', - 'value' - ]; - } - - var allowedElementAttributes = []; - try { - allowedElementAttributes = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.attributes.showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedElementAttributes = allowedGeneralAttributes; - } - - Ext.iterate(allowedElementAttributes, function(item, index, allItems) { - if (allowedGeneralAttributes.indexOf(item) > -1 && Ext.isDefined(elementAttributes[item])) { - attributes.push(item); - } - }, this); - - return attributes; - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'attributes', valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'attributes', valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-attributes', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Attributes); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters.js deleted file mode 100644 index 0b835f396245b44c697457ddbebff0aafac1ff34..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters.js +++ /dev/null @@ -1,243 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The filters accordion panel in the element options in the left tabpanel - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters = Ext.extend(Ext.Panel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_filters'), - - /** - * @cfg {Object} validFilters - * Keeps track which filters are valid. Filters contain forms which - * do client validation. If there is a validation change in a form in the - * filter, a validation event will be fired, which changes one of these - * values - */ - validFilters: { - alphabetic: true, - alphanumeric: true, - currency: true, - digit: true, - integer: true, - lowercase: true, - regexp: true, - stripnewlines: true, - titlecase: true, - trim: true, - uppercase: true - }, - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - var filters = this.getFiltersBySettings(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - var config = { - items: [{ - xtype: 'typo3-form-wizard-viewport-left-options-forms-filters-dummy', - ref: 'dummy' - }], - tbar: [ - { - xtype: 'combo', - hideLabel: true, - name: 'filters', - ref: 'filters', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'filters', - emptyText: TYPO3.l10n.localize('filters_emptytext'), - width: 150, - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: filters - }), - listeners: { - 'select': { - scope: this, - fn: this.addFilter - } - } - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.superclass.initComponent.apply(this, arguments); - - // Initialize the filters when they are available for this element - this.initFilters(); - }, - - /** - * Called when constructing the filters accordion - * - * Checks if the element already has filters and loads these instead of the dummy - */ - initFilters: function() { - var filters = this.element.configuration.filters; - if (!Ext.isEmptyObject(filters)) { - this.remove(this.dummy); - Ext.iterate(filters, function(key, value) { - this.add({ - xtype: 'typo3-form-wizard-viewport-left-options-forms-filters-' + key, - element: this.element, - configuration: value, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - }, this); - } - }, - - /** - * Add a filter to the filters list - * - * @param comboBox - * @param record - * @param index - */ - addFilter: function(comboBox, record, index) { - var filter = comboBox.getValue(); - var xtype = 'typo3-form-wizard-viewport-left-options-forms-filters-' + filter; - - if (!Ext.isEmpty(this.findByType(xtype))) { - Ext.MessageBox.alert(TYPO3.l10n.localize('filters_alert_title'), TYPO3.l10n.localize('filters_alert_description')); - } else { - this.remove(this.dummy); - - this.add({ - xtype: xtype, - element: this.element, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - this.doLayout(); - } - }, - - /** - * Remove a filter from the filters list - * - * Shows dummy when there is no filter for this element - * - * @param component - */ - removeFilter: function(component) { - this.remove(component); - this.validation(component.filter, true); - if (this.items.length == 0) { - this.add({ - xtype: 'typo3-form-wizard-viewport-left-options-forms-filters-dummy', - ref: 'dummy' - }); - } - this.doLayout(); - }, - - /** - * Get the allowed filters by the TSconfig settings - * - * @returns {Array} - */ - getFiltersBySettings: function() { - var filters = []; - var elementType = this.element.xtype.split('-').pop(); - - var allowedDefaultFilters = []; - try { - allowedDefaultFilters = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.filtering.showFilters.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedDefaultFilters = [ - 'alphabetic', - 'alphanumeric', - 'currency', - 'digit', - 'integer', - 'lowercase', - 'regexp', - 'stripnewlines', - 'titlecase', - 'trim', - 'uppercase' - ]; - } - - var allowedElementFilters = []; - try { - allowedElementFilters = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.filtering.showFilters.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedElementFilters = allowedDefaultFilters; - } - - Ext.iterate(allowedElementFilters, function(item, index, allItems) { - if (allowedDefaultFilters.indexOf(item) > -1) { - filters.push({label: TYPO3.l10n.localize('filters_' + item), value: item}); - } - }, this); - - return filters; - }, - - /** - * Called by the validation listeners of the filters - * - * Checks if all filters are valid. If not, adds a class to the accordion - * - * @param {String} filter The filter which fires the event - * @param {Boolean} isValid Rule is valid or not - */ - validation: function(filter, isValid) { - this.validFilters[filter] = isValid; - var accordionIsValid = true; - Ext.iterate(this.validFilters, function(key, value) { - if (!value) { - accordionIsValid = false; - } - }, this); - if (this.el) { - if (accordionIsValid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'filters', isValid); - } else if (!accordionIsValid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'filters', isValid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphabetic.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphabetic.js deleted file mode 100644 index ae12e8e3480b9102456b6132b0efd1b7e4cd5322..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphabetic.js +++ /dev/null @@ -1,33 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The alphabetic filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphabetic - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphabetic = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'alphabetic', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - allowWhiteSpace: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphabetic.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-alphabetic', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphabetic); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphanumeric.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphanumeric.js deleted file mode 100644 index 1929ac1addf5144ca7043a5b44b8a1c292214d21..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Alphanumeric.js +++ /dev/null @@ -1,33 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The alphanumeric filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphanumeric - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphanumeric = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'alphanumeric', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - allowWhiteSpace: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphanumeric.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-alphanumeric', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Alphanumeric); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Currency.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Currency.js deleted file mode 100644 index 3878dc6738fff6f2c3d46b4324f575121a96716d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Currency.js +++ /dev/null @@ -1,34 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The currency filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Currency - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Currency = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'currency', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - decimalPoint: '.', - thousandSeparator: ',' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Currency.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-currency', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Currency); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Digit.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Digit.js deleted file mode 100644 index 4fd4c4804d45e85e07ce61a9d2251d70f85a2845..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Digit.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The digit filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Digit - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Digit = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'digit' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-digit', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Digit); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Dummy.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Dummy.js deleted file mode 100644 index f8b71a3f812647bcaadd4d8dc7e053b39fd31d9e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Dummy.js +++ /dev/null @@ -1,58 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The dummy item when no filter is defined for an element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Dummy - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Dummy = Ext.extend(Ext.Panel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'formwizard-left-dummy typo3-message message-information', - - /** - * @cfg {Mixed} data - * The initial set of data to apply to the tpl to update the content area of - * the Component. - */ - data: [{ - title: TYPO3.l10n.localize('filters_dummy_title'), - description: TYPO3.l10n.localize('filters_dummy_description') - }], - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ) -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-dummy', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Dummy); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Filter.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Filter.js deleted file mode 100644 index 3592489c6c1ba8437f7018f1792c98980cd026d6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Filter.js +++ /dev/null @@ -1,345 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The filter abstract - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * @cfg {Object} Default filter configuration - */ - configuration: {}, - - /** - * Constructor - */ - initComponent: function() { - var fields = this.getFieldsBySettings(); - var formItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(fields, function(item, index, allItems) { - switch(item) { - case 'allowWhiteSpace': - formItems.push({ - xtype: 'checkbox', - fieldLabel: TYPO3.l10n.localize('filters_properties_allowwhitespace'), - name: 'allowWhiteSpace', - inputValue: '1', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'decimalPoint': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('filters_properties_decimalpoint'), - name: 'decimalPoint', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'thousandSeparator': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('filters_properties_thousandseparator'), - name: 'thousandSeparator', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'expression': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('filters_properties_expression'), - name: 'expression', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'characterList': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('filters_properties_characterlist'), - name: 'characterList', - allowBlank: true, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - } - }, this); - - if (Ext.isEmpty(formItems)) { - formItems.push({ - xtype: 'box', - autoEl: { - tag: 'div' - }, - width: 256, - cls: 'typo3-message message-information', - data: [{ - title: TYPO3.l10n.localize('filters_properties_none_title'), - description: TYPO3.l10n.localize('filters_properties_none') - }], - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ) - - }); - } - - formItems.push({ - xtype: 'button', - text: TYPO3.l10n.localize('button_remove'), - handler: this.removeFilter, - scope: this - }); - - var config = { - items: [ - { - xtype: 'fieldset', - title: this.filter, - autoHeight: true, - defaults: { - width: 128, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Strange, but we need to call doLayout() after render - this.on('afterrender', this.newOrExistingFilter, this); - }, - - /** - * Decide whether this is a new or an existing one - * - * If new, the default configuration has to be added to the filters - * of the element, otherwise we can fill the form with the existing configuration - */ - newOrExistingFilter: function() { - this.doLayout(); - // Existing filter - if (this.element.configuration.filters[this.filter]) { - this.fillForm(); - // New filter - } else { - this.addFilterToElement(); - } - }, - - /** - * Fill the form with the configuration of the element - * - * When filling, the events of all form elements should be suspended, - * otherwise the values are written back to the element, for instance on a - * check event on a checkbox. - */ - fillForm: function() { - this.suspendEventsBeforeFilling(); - this.getForm().setValues(this.element.configuration.filters[this.filter]); - this.resumeEventsAfterFilling(); - }, - - /** - * Suspend the events on all items within this component - */ - suspendEventsBeforeFilling: function() { - this.cascade(function(item) { - item.suspendEvents(); - }); - }, - - /** - * Resume the events on all items within this component - */ - resumeEventsAfterFilling: function() { - this.cascade(function(item) { - item.resumeEvents(); - }); - }, - - /** - * Add this filter to the element - */ - addFilterToElement: function() { - var formConfiguration = {filters: {}}; - formConfiguration.filters[this.filter] = this.configuration; - - this.element.setConfigurationValue(formConfiguration); - - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {filters: {}}; - formConfiguration.filters[this.filter] = {}; - formConfiguration.filters[this.filter][fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Remove the filter - * - * Called when the remove button of this filter has been clicked - */ - removeFilter: function() { - this.ownerCt.removeFilter(this); - this.element.removeFilter(this.filter); - }, - - /** - * Get the fields for the element - * - * Based on the TSconfig general allowed fields - * and the TSconfig allowed fields for this type of element - * - * @returns object - */ - getFieldsBySettings: function() { - var fields = []; - var filterFields = this.configuration; - var elementType = this.element.xtype.split('-').pop(); - - var allowedGeneralFields = []; - try { - allowedGeneralFields = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.filtering.filters[this.filter].showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedGeneralFields = [ - 'allowWhiteSpace', - 'decimalPoint', - 'thousandSeparator', - 'expression', - 'characterList' - ]; - } - - var allowedElementFields = []; - try { - allowedElementFields = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.filtering.filters[this.filter].showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedElementFields = allowedGeneralFields; - } - - Ext.iterate(allowedElementFields, function(item, index, allItems) { - if (allowedGeneralFields.indexOf(item) > -1 && Ext.isDefined(filterFields[item])) { - fields.push(item); - } - }, this); - - return fields; - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', this.filter, valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', this.filter, valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-filter', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Integer.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Integer.js deleted file mode 100644 index a2931b6d6aefed24e322d226220d17aa7f19ec2b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Integer.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The integer filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Integer - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Integer = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'integer' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-integer', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Integer); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/LowerCase.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/LowerCase.js deleted file mode 100644 index 96f2ac09cbf52da64d3a0a7319e0423e76377c7e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/LowerCase.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The lower case filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.LowerCase - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.LowerCase = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'lowercase' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-lowercase', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.LowerCase); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/RegExp.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/RegExp.js deleted file mode 100644 index 242fdb6dc33a77f16621f0c306aa8ebd17058438..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/RegExp.js +++ /dev/null @@ -1,33 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The regular expression filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.RegExp - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.RegExp = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'regexp', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - expression: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.RegExp.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-regexp', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.RegExp); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/StripNewLines.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/StripNewLines.js deleted file mode 100644 index c37ced00a713241e459de4d5dbc83f913daa1b05..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/StripNewLines.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The strip new lines filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.StripNewLines - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.StripNewLines = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'stripnewlines' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-stripnewlines', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.StripNewLines); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/TitleCase.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/TitleCase.js deleted file mode 100644 index df367ce4bb47418a3b0f9e7db0c33728959dff9b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/TitleCase.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The title case filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.TitleCase - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.TitleCase = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'titlecase' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-titlecase', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.TitleCase); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Trim.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Trim.js deleted file mode 100644 index 32c9a4b4c7e959e494daa18c8a2d87d922fa4807..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/Trim.js +++ /dev/null @@ -1,33 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The trim filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Trim - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Trim = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'trim', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - characterList: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Trim.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-trim', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Trim); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/UpperCase.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/UpperCase.js deleted file mode 100644 index 680b40822d3ad971a95034a8e0b09ffa14183a70..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Filters/UpperCase.js +++ /dev/null @@ -1,18 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters'); - -/** - * The upper case filter - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.UpperCase - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.UpperCase = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.Filter, { - /** - * @cfg {String} filter - * - * The name of this filter - */ - filter: 'uppercase' -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-filters-uppercase', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Filters.UpperCase); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Label.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Label.js deleted file mode 100644 index 2f46d194ec94878cdbe89ef4ab64cbdee6b81213..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Label.js +++ /dev/null @@ -1,229 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The label properties and the layout of the element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Label - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Label = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_label'), - - /** @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'x-panel-accordion', - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - var fields = this.getFieldsBySettings(); - var formItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(fields, function(item, index, allItems) { - switch(item) { - case 'label': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('label_label'), - name: 'label', - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'layout': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('label_layout'), - name: 'layout', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'layout', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('label_layout_front'), value: 'front'}, - {label: TYPO3.l10n.localize('label_layout_back'), value: 'back'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - default: - } - }, this); - - var config = { - items: [{ - xtype: 'fieldset', - title: '', - border: false, - autoHeight: true, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Label.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Fill the form with the configuration values - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - if (fieldName == 'label') { - var formConfiguration = { - label: { - value: field.getValue() - } - }; - } else { - var formConfiguration = {}; - formConfiguration[fieldName] = field.getValue(); - } - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Fill the form with the configuration of the element - * - * @param record The current question - * @return void - */ - fillForm: function() { - this.getForm().setValues({ - label: this.element.configuration.label.value, - layout: this.element.configuration.layout - }); - }, - - /** - * Get the fields for the element - * - * Based on the TSconfig general allowed fields - * and the TSconfig allowed fields for this type of element - * - * @returns object - */ - getFieldsBySettings: function() { - var fields = []; - var elementType = this.element.xtype.split('-').pop(); - - var allowedGeneralFields = []; - try { - allowedGeneralFields = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.label.showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedGeneralFields = [ - 'label', - 'layout' - ]; - } - - var allowedElementFields = []; - try { - allowedElementFields = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.label.showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedElementFields = allowedGeneralFields; - } - - Ext.iterate(allowedElementFields, function(item, index, allItems) { - if (allowedGeneralFields.indexOf(item) > -1) { - fields.push(item); - } - }, this); - - return fields; - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'label', valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'label', valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-label', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Label); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Legend.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Legend.js deleted file mode 100644 index 701e7bb793eebd4c519b9801058c6dc1e812bc2b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Legend.js +++ /dev/null @@ -1,152 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The legend properties of the element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Legend - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Legend = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_legend'), - - /** @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'x-panel-accordion', - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - var config = { - items: [{ - xtype: 'fieldset', - title: '', - autoHeight: true, - border: false, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: [ - { - fieldLabel: TYPO3.l10n.localize('legend_legend'), - name: 'legend', - enableKeyEvents: true, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - } - ] - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Legend.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Fill the form with the configuration values - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - if (fieldName == 'legend') { - var formConfiguration = { - legend: { - value: field.getValue() - } - }; - } else { - var formConfiguration = {}; - formConfiguration[fieldName] = field.getValue(); - } - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Fill the form with the configuration of the element - * - * @param record The current question - * @return void - */ - fillForm: function() { - this.getForm().setValues({ - legend: this.element.configuration.legend.value - }); - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'legend', valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'legend', valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-legend', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Legend); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Options.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Options.js deleted file mode 100644 index a4772e7176462e1b750814ec783ddf2142e256a3..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Options.js +++ /dev/null @@ -1,249 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The options properties of the element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Options - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Options = Ext.extend(Ext.grid.EditorGridPanel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_fieldoptions'), - - /** - * @cfg {String} autoExpandColumn - * The id of a column in this grid that should expand to fill unused space. - * This value specified here can not be 0. - */ - autoExpandColumn: 'text', - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: '10px 0 10px 15px', - - /** - * @cfg {Number} clicksToEdit - * The number of clicks on a cell required to display the cell's editor (defaults to 2). - * Setting this option to 'auto' means that mousedown on the selected cell starts - * editing that cell. - */ - clicksToEdit: 1, - - /** - * @cfg {Object} viewConfig A config object that will be applied to the grid's UI view. Any of - * the config options available for Ext.grid.GridView can be specified here. This option - * is ignored if view is specified. - */ - viewConfig: { - forceFit: true, - emptyText: TYPO3.l10n.localize('fieldoptions_emptytext'), - scrollOffset: 0 - }, - - /** - * Constructor - * - * Configure store and columns for the grid - */ - initComponent: function () { - var optionRecord = Ext.data.Record.create([ - { - name: 'text', - mapping: 'text', - type: 'string' - }, { - name: 'selected', - convert: this.convertSelected, - type: 'bool' - }, { - name: 'value', - convert: this.convertValue, - type: 'string' - } - ]); - - var store = new Ext.data.JsonStore({ - idIndex: 1, - fields: optionRecord, - data: this.element.configuration.options, - autoDestroy: true, - autoSave: true, - listeners: { - 'add': { - scope: this, - fn: this.storeOptions - }, - 'remove': { - scope: this, - fn: this.storeOptions - }, - 'update': { - scope: this, - fn: this.storeOptions - } - } - }); - - var checkColumn = new Ext.ux.grid.SingleSelectCheckColumn({ - id: 'selected', - header: TYPO3.l10n.localize('fieldoptions_selected'), - dataIndex: 'selected', - width: 20 - }); - - var itemDeleter = new Ext.ux.grid.ItemDeleter(); - - var config = { - store: store, - cm: new Ext.grid.ColumnModel({ - defaults: { - sortable: false - }, - columns: [ - { - width: 40, - id: 'data', - header: TYPO3.l10n.localize('fieldoptions_text'), - dataIndex: 'text', - editor: new Ext.ux.form.TextFieldSubmit({ - allowBlank: false, - listeners: { - 'triggerclick': function (field) { - field.gridEditor.record.set('text', field.getValue()); - } - } - }) - }, - checkColumn, - { - width: 40, - id: 'value', - header: TYPO3.l10n.localize('fieldoptions_value'), - dataIndex: 'value', - editor: new Ext.ux.form.TextFieldSubmit({ - allowBlank: true, - listeners: { - 'triggerclick': function (field) { - field.gridEditor.record.set('value', field.getValue()); - } - } - }) - }, - itemDeleter - ] - }), - selModel: itemDeleter, - plugins: [checkColumn], - tbar: [{ - text: TYPO3.l10n.localize('fieldoptions_button_add'), - handler: this.addOption, - scope: this - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Options.superclass.initComponent.apply(this, arguments); - }, - - /** - * Adds a new record to the grid - * - * Called when the button to add option in the top bar has been clicked - */ - addOption: function () { - var option = this.store.recordType; - var newOption = new option({ - text: TYPO3.l10n.localize('fieldoptions_new'), - selected: false, - value: TYPO3.l10n.localize('fieldoptions_value') - }); - this.stopEditing(); - this.store.add(newOption); - this.startEditing(0, 0); - }, - - /** - * Stores the options in the element whenever a change has been done to the - * grid, like add, remove or update - * - * @param store - * @param record - */ - storeOptions: function (store, record) { - if (record && record.dirty) { - record.commit(); - } else { - var option = {}; - var options = []; - this.store.each(function (record) { - var option = { - text: record.get('text') - }; - if (record.get('selected')) { - if (!option.attributes) { - option.attributes = {}; - } - option.attributes['selected'] = 'selected'; - } - if (record.get('value')) { - if (!option.attributes) { - option.attributes = {}; - } - option.attributes['value'] = record.get('value'); - } - options.push(option); - }); - this.element.configuration.options = []; - var formConfiguration = { - options: options - }; - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Convert and remap the "selected" attribute. In HTML the attribute needs - * be as selected="selected", while the grid uses a boolean. - * - * @param v - * @param record - * @returns {Boolean} - */ - convertSelected: function (v, record) { - if (record.attributes && record.attributes.selected) { - if (record.attributes.selected == 'selected') { - return true; - } - } - return false; - }, - - /** - * Remap value from different locations - * - * @param v - * @param record - * @returns {string} - */ - convertValue: function (v, record) { - if (record.attributes && record.attributes.value) { - return record.attributes.value; - } else if (record.data) { - return record.data; - } - return ''; - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-options', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Options); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation.js deleted file mode 100644 index 11618cfc04b99009cd170afea1280c89ae60849d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation.js +++ /dev/null @@ -1,275 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The validation accordion panel in the element options in the left tabpanel - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation = Ext.extend(Ext.Panel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_validation'), - - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-left-options-validation', - - /** - * @cfg {Object} validRules - * Keeps track which rules are valid. Rules contain forms which - * do client validation. If there is a validation change in a form in the - * rule, a validation event will be fired, which changes one of these - * values - */ - validRules: { - alphabetic: true, - alphanumeric: true, - between: true, - date: true, - digit: true, - email: true, - equals: true, - fileallowedtypes: true, - float: true, - greaterthan: true, - inarray: true, - integer: true, - ip: true, - length: true, - lessthan: true, - regexp: true, - required: true, - uri: true - }, - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - var rules = this.getRulesBySettings(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - var config = { - items: [{ - xtype: 'typo3-form-wizard-viewport-left-options-forms-validation-dummy', - ref: 'dummy' - }], - tbar: [ - { - xtype: 'combo', - hideLabel: true, - name: 'rules', - ref: 'rules', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'rules', - emptyText: TYPO3.l10n.localize('validation_emptytext'), - width: 150, - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: rules - }), - listeners: { - 'select': { - scope: this, - fn: this.addRule - } - } - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.superclass.initComponent.apply(this, arguments); - - // Initialize the rules when they are available for this element - this.initRules(); - }, - - /** - * Called when constructing the validation accordion - * - * Checks if the element already has rules and loads these instead of the dummy - */ - initRules: function() { - var rules = this.element.configuration.validation; - if (!Ext.isEmptyObject(rules)) { - this.remove(this.dummy); - Ext.iterate(rules, function(key, value) { - var xtype = 'typo3-form-wizard-viewport-left-options-forms-validation-' + key; - if (Ext.ComponentMgr.isRegistered(xtype)) { - this.add({ - xtype: xtype, - element: this.element, - configuration: value, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - } - }, this); - } - }, - - /** - * Add a rule to the validation list - * - * @param comboBox - * @param record - * @param index - */ - addRule: function(comboBox, record, index) { - var rule = comboBox.getValue(); - var xtype = 'typo3-form-wizard-viewport-left-options-forms-validation-' + rule; - - if (!Ext.isEmpty(this.findByType(xtype))) { - Ext.MessageBox.alert(TYPO3.l10n.localize('validation_alert_title'), TYPO3.l10n.localize('validation_alert_description')); - } else { - this.remove(this.dummy); - - this.add({ - xtype: xtype, - element: this.element, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - this.doLayout(); - } - }, - - /** - * Remove a rule from the validation list - * - * Shows dummy when there is no validation rule for this element - * - * @param component - */ - removeRule: function(component) { - this.remove(component); - this.validation(component.rule, true); - if (this.items.length == 0) { - this.add({ - xtype: 'typo3-form-wizard-viewport-left-options-forms-validation-dummy', - ref: 'dummy' - }); - } - this.doLayout(); - }, - - /** - * Get the rules by the TSconfig settings - * - * @returns {Array} - */ - getRulesBySettings: function() { - var rules = []; - var elementType = this.element.xtype.split('-').pop(); - - var allowedDefaultRules = []; - try { - allowedDefaultRules = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.validation.showRules.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedDefaultRules = [ - 'alphabetic', - 'alphanumeric', - 'between', - 'date', - 'digit', - 'email', - 'equals', - 'fileallowedtypes', - 'float', - 'greaterthan', - 'inarray', - 'integer', - 'ip', - 'length', - 'lessthan', - 'regexp', - 'required', - 'uri' - ]; - } - - var allowedElementRules = []; - try { - allowedElementRules = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.validation.showRules.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedElementRules = allowedDefaultRules; - } - - Ext.iterate(allowedElementRules, function(item, index, allItems) { - if (allowedDefaultRules.indexOf(item) > -1) { - rules.push({label: TYPO3.l10n.localize('validation_' + item), value: item}); - } - }, this); - - return rules; - }, - - /** - * Called by the validation listeners of the rules - * - * Checks if all rules are valid. If not, adds a class to the accordion - * - * @param {String} rule The rule which fires the event - * @param {Boolean} isValid Rule is valid or not - */ - validation: function(rule, isValid) { - this.validRules[rule] = isValid; - var accordionIsValid = true; - Ext.iterate(this.validRules, function(key, value) { - if (!value) { - accordionIsValid = false; - } - }, this); - if (this.el) { - if (accordionIsValid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'validation', isValid); - } else if (!accordionIsValid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'validation', isValid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphabetic.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphabetic.js deleted file mode 100644 index eb9fd1a5f5076f8b710c4a5330c828050bc6a245..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphabetic.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The alphabetic validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphabetic - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphabetic = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'alphabetic', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_alphabetic.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_alphabetic.error'), - allowWhiteSpace: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphabetic.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-alphabetic', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphabetic); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphanumeric.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphanumeric.js deleted file mode 100644 index bbd4cdf0f1f8fc6733a19c4fb7a1aa6b7373a67a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Alphanumeric.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The alphanumeric validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphanumeric - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphanumeric = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'alphanumeric', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_alphanumeric.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_alphanumeric.error'), - allowWhiteSpace: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphanumeric.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-alphanumeric', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Alphanumeric); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Between.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Between.js deleted file mode 100644 index bb45fc96b04a5d4458cd81dae843336227f55a0c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Between.js +++ /dev/null @@ -1,38 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The between validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Between - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Between = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'between', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_between.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_between.error'), - minimum: 0, - maximum: 0, - inclusive: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Between.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-between', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Between); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Date.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Date.js deleted file mode 100644 index ac222c02fb1cc1ae8c8d72ec2e724efe3a87d62d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Date.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The date validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Date - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Date = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'date', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_date.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_date.error'), - format: '%e-%m-%Y' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Date.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-date', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Date); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Digit.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Digit.js deleted file mode 100644 index 501dafd326ab84dbf439e3b2b7a27f032300cf99..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Digit.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The digit validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Digit - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Digit = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'digit', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_digit.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_digit.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Digit.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-digit', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Digit); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Dummy.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Dummy.js deleted file mode 100644 index 603b73edfa39ae5aba64df07eca317efd3673b65..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Dummy.js +++ /dev/null @@ -1,58 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The dummy item when no validation rule is defined for an element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Dummy - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Dummy = Ext.extend(Ext.Panel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} cls - * An optional extra CSS class that will be added to this component's - * Element (defaults to ''). This can be useful for adding customized styles - * to the component or any of its children using standard CSS rules. - */ - cls: 'formwizard-left-dummy typo3-message message-information', - - /** - * @cfg {Mixed} data - * The initial set of data to apply to the tpl to update the content area of - * the Component. - */ - data: [{ - title: TYPO3.l10n.localize('validation_dummy_title'), - description: TYPO3.l10n.localize('validation_dummy_description') - }], - - /** - * @cfg {Mixed} tpl - * An Ext.Template, Ext.XTemplate or an array of strings to form an - * Ext.XTemplate. Used in conjunction with the data and tplWriteMode - * configurations. - */ - tpl: new Ext.XTemplate( - '<tpl for=".">', - '<p><strong>{title}</strong></p>', - '<p>{description}</p>', - '</tpl>' - ) -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-dummy', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Dummy); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Email.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Email.js deleted file mode 100644 index 391e7725d44538bb83e0842a83d0c993cd02193a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Email.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The email validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'email', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_email.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_email.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-email', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Equals.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Equals.js deleted file mode 100644 index f80f8c1385e3007240ec2010c998036e437fc17f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Equals.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The equals validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Email - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Equals = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'equals', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_equals.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_equals.error'), - field: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Equals.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-equals', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Equals); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileAllowedTypes.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileAllowedTypes.js deleted file mode 100644 index ba7baa124e7347c0d69af3f43ee578fe0ce7e7db..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileAllowedTypes.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.FileAllowedTypes'); - -/** - * The allowed file types rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileAllowedTypes - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileAllowedTypes = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'fileallowedtypes', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_fileallowedtypes.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_fileallowedtypes.error'), - types: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileAllowedTypes.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-fileallowedtypes', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileAllowedTypes); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMaximumSize.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMaximumSize.js deleted file mode 100644 index 967e7226895ce7c06c0d95ae9dad70e41f343ea1..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMaximumSize.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.FileMaximumSize'); - -/** - * The maximum file size rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMaximumSize - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMaximumSize = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'filemaximumsize', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_filemaximumsize.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_filemaximumsize.error'), - maximum: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMaximumSize.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-filemaximumsize', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMaximumSize); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMinimumSize.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMinimumSize.js deleted file mode 100644 index 5304191023b4ad1fe2ea38bd8d3f0136cf4e6031..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/FileMinimumSize.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.FileMinimumSize'); - -/** - * The minimum file size rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMinimumSize - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMinimumSize = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'fileminimumsize', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_fileminimumsize.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_fileminimumsize.error'), - minimum: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMinimumSize.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-fileminimumsize', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.FileMinimumSize); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Float.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Float.js deleted file mode 100644 index e189f462b8b894db12f614acb725fae80acd5b3f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Float.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The float validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Float - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Float = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'float', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_float.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_float.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Float.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-float', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Float); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/GreaterThan.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/GreaterThan.js deleted file mode 100644 index 795a460c40d03794c483c33ce620af5da199eabd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/GreaterThan.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The greater than validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.GreaterThan - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.GreaterThan = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'greaterthan', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_greaterthan.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_greaterthan.error'), - minimum: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.GreaterThan.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-greaterthan', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.GreaterThan); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/InArray.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/InArray.js deleted file mode 100644 index 0f922089db455eabc5bfe302c0c5a57ff86b4c96..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/InArray.js +++ /dev/null @@ -1,37 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The in arrayt validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.InArray - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.InArray = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'inarray', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_inarray.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_inarray.error'), - array: '', - strict: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.InArray.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-inarray', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.InArray); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Integer.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Integer.js deleted file mode 100644 index 5219315f26e2197634a8b0e01f474cae4dd0116d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Integer.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The integer validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Integer - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Integer = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'integer', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_integer.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_integer.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Integer.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-integer', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Integer); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Ip.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Ip.js deleted file mode 100644 index 7e65761eb46ff738d73b52f527dfff7ad22f0d55..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Ip.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The IP validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Ip - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Ip = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'ip', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_ip.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_ip.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Ip.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-ip', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Ip); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Length.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Length.js deleted file mode 100644 index 7ba06c3ee70cf30d373945602954239bae4be8b6..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Length.js +++ /dev/null @@ -1,37 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The length validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Length - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Length = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'length', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_length.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_length.error'), - minimum: 0, - maximum: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Length.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-length', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Length); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/LessThan.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/LessThan.js deleted file mode 100644 index a3db3b6bc155f57540c1b5f3e49eedb369f0122e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/LessThan.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The less than validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.LessThan - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.LessThan = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'lessthan', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_lessthan.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_lessthan.error'), - maximum: 0 - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.LessThan.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-lessthan', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.LessThan); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/RegExp.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/RegExp.js deleted file mode 100644 index 059eda36154ecf439c3b5e956a8fb9ab9733ac4c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/RegExp.js +++ /dev/null @@ -1,36 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The regular expression validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.RegExp - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.RegExp = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'regexp', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_regexp.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_regexp.error'), - expression: '' - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.RegExp.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-regexp', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.RegExp); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Required.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Required.js deleted file mode 100644 index f15fe85c28008b24d2915900e9e01b6eac2090f8..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Required.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The required validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Required - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Required = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'required', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_required.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_required.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Required.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-required', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Required); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Rule.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Rule.js deleted file mode 100644 index 7dfc5d061f2180de230d7797740e785101b06e98..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Rule.js +++ /dev/null @@ -1,436 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The validation rules abstract - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Number/String} padding - * A shortcut for setting a padding style on the body element. The value can - * either be a number to be applied to all sides, or a normal css string - * describing padding. - */ - padding: 0, - - /** - * @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: '', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * Constructor - */ - initComponent: function() { - var fields = this.getFieldsBySettings(); - var formItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(fields, function(item, index, allItems) { - switch(item) { - case 'message': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_message'), - name: 'message', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'error': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_error'), - name: 'error', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'showMessage': - formItems.push({ - xtype: 'checkbox', - fieldLabel: TYPO3.l10n.localize('validation_properties_showmessage'), - name: 'showMessage', - inputValue: '1', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'allowWhiteSpace': - formItems.push({ - xtype: 'checkbox', - fieldLabel: TYPO3.l10n.localize('validation_properties_allowwhitespace'), - name: 'allowWhiteSpace', - inputValue: '1', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'minimum': - formItems.push({ - xtype: 'spinnerfield', - fieldLabel: TYPO3.l10n.localize('validation_properties_minimum'), - name: 'minimum', - minValue: 0, - accelerate: true, - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'maximum': - formItems.push({ - xtype: 'spinnerfield', - fieldLabel: TYPO3.l10n.localize('validation_properties_maximum'), - name: 'maximum', - minValue: 0, - accelerate: true, - listeners: { - 'spin': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'inclusive': - formItems.push({ - xtype: 'checkbox', - fieldLabel: TYPO3.l10n.localize('validation_properties_inclusive'), - name: 'inclusive', - inputValue: '1', - listeners: { - 'check': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'format': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_format'), - name: 'format', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'field': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_field'), - name: 'field', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'array': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_array'), - name: 'array', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'expression': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_expression'), - name: 'expression', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - case 'types': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('validation_properties_types'), - name: 'types', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - } - }, this); - - formItems.push({ - xtype: 'button', - text: TYPO3.l10n.localize('button_remove'), - handler: this.removeRule, - scope: this - }); - - var config = { - items: [ - { - xtype: 'fieldset', - title: TYPO3.l10n.localize('validation_' + this.rule), - autoHeight: true, - defaults: { - width: 128, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Strange, but we need to call doLayout() after render - this.on('afterrender', this.newOrExistingRule, this); - }, - - /** - * Decide whether this is a new or an existing one - * - * If new, the default configuration has to be added to the validation rules - * of the element, otherwise we can fill the form with the existing configuration - */ - newOrExistingRule: function() { - this.doLayout(); - // Existing rule - if (this.element.configuration.validation[this.rule]) { - this.fillForm(); - // New rule - } else { - this.addRuleToElement(); - } - }, - - /** - * Fill the form with the configuration of the element - * - * When filling, the events of all form elements should be suspended, - * otherwise the values are written back to the element, for instance on a - * check event on a checkbox. - */ - fillForm: function() { - this.suspendEventsBeforeFilling(); - this.getForm().setValues(this.element.configuration.validation[this.rule]); - this.resumeEventsAfterFilling(); - }, - - /** - * Suspend the events on all items within this component - */ - suspendEventsBeforeFilling: function() { - this.cascade(function(item) { - item.suspendEvents(); - }); - }, - - /** - * Resume the events on all items within this component - */ - resumeEventsAfterFilling: function() { - this.cascade(function(item) { - item.resumeEvents(); - }); - }, - - /** - * Add this rule to the element - */ - addRuleToElement: function() { - var formConfiguration = {validation: {}}; - formConfiguration.validation[this.rule] = this.configuration; - - this.element.setConfigurationValue(formConfiguration); - - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {validation: {}}; - formConfiguration.validation[this.rule] = {}; - formConfiguration.validation[this.rule][fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Remove the rule - * - * Called when the remove button of this rule has been clicked - */ - removeRule: function() { - this.ownerCt.removeRule(this); - this.element.removeValidationRule(this.rule); - }, - - /** - * Get the fields for the element - * - * Based on the TSconfig general allowed fields - * and the TSconfig allowed fields for this type of element - * - * @returns object - */ - getFieldsBySettings: function() { - var fields = []; - var ruleFields = this.configuration; - var elementType = this.element.xtype.split('-').pop(); - - var allowedGeneralFields = []; - try { - allowedGeneralFields = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.validation.rules[this.rule].showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedGeneralFields = [ - 'message', - 'error', - 'showMessage', - 'allowWhiteSpace', - 'minimum', - 'maximum', - 'inclusive', - 'format', - 'field', - 'array', - 'strict', - 'expression' - ]; - } - - var allowedElementFields = []; - try { - allowedElementFields = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.validation.rules[this.rule].showProperties.split(/[, ]+/); - } catch (error) { - // The object has not been found or constructed wrong - allowedElementFields = allowedGeneralFields; - } - - Ext.iterate(allowedElementFields, function(item, index, allItems) { - if (allowedGeneralFields.indexOf(item) > -1 && Ext.isDefined(ruleFields[item])) { - fields.push(item); - } - }, this); - - return fields; - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', this.rule, valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', this.rule, valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-rule', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Uri.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Uri.js deleted file mode 100644 index 5503a70b9acfae0629952dfaa1be6cf02090b060..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Validation/Uri.js +++ /dev/null @@ -1,35 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation'); - -/** - * The uri validation rule - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Uri - * @extends TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Uri = Ext.extend(TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule, { - /** - * @cfg {String} rule - * - * The name of this rule - */ - rule: 'uri', - - /** - * Constructor - * - * Add the configuration object to this component - * @param config - */ - constructor: function(config) { - Ext.apply(this, { - configuration: { - showMessage: 1, - message: TYPO3.l10n.localize('tx_form_system_validate_uri.message'), - error: TYPO3.l10n.localize('tx_form_system_validate_uri.error') - } - }); - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Uri.superclass.constructor.apply(this, arguments); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-uri', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Uri); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Various.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Various.js deleted file mode 100644 index 499fa4e8566dfda73db13c3578819d8f46397471..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Forms/Various.js +++ /dev/null @@ -1,290 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms'); - -/** - * The various properties of the element - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various - * @extends Ext.FormPanel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various = Ext.extend(Ext.ux.form.FakeFormPanel, { - /** - * @cfg {String} title - * The title text to be used as innerHTML (html tags are accepted) to - * display in the panel header (defaults to ''). - */ - title: TYPO3.l10n.localize('options_various'), - - /** @cfg {String} defaultType - * - * The default xtype of child Components to create in this Container when - * a child item is specified as a raw configuration object, - * rather than as an instantiated Component. - * - * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem', - * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'. - */ - defaultType: 'textfield', - - /** - * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and - * regularly fires the clientvalidation event passing that state. - * When monitoring valid state, the FormPanel enables/disables any of its configured - * buttons which have been configured with formBind: true depending - * on whether the form is valid or not. Defaults to false - */ - monitorValid: true, - - /** - * Constructor - * - * Add the form elements to the accordion - */ - initComponent: function() { - var various = this.element.configuration.various; - var formItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(various, function(key, value) { - switch(key) { - case 'name': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_name'), - name: 'name', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'content': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_content'), - xtype: 'textarea', - name: 'content', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'text': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_text'), - xtype: 'textarea', - name: 'text', - allowBlank: false, - listeners: { - 'triggerclick': { - scope: this, - fn: this.storeValue - }, - 'blur': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'headingSize': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_headingsize'), - name: 'headingSize', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'headingSize', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: 'H1', value: 'h1'}, - {label: 'H2', value: 'h2'}, - {label: 'H3', value: 'h3'}, - {label: 'H4', value: 'h4'}, - {label: 'H5', value: 'h5'} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'prefix': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_prefix'), - name: 'prefix', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'prefix', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('yes'), value: true}, - {label: TYPO3.l10n.localize('no'), value: false} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'suffix': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_suffix'), - name: 'suffix', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'suffix', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('yes'), value: true}, - {label: TYPO3.l10n.localize('no'), value: false} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - case 'middleName': - formItems.push({ - fieldLabel: TYPO3.l10n.localize('various_properties_middlename'), - name: 'middleName', - xtype: 'combo', - mode: 'local', - triggerAction: 'all', - forceSelection: true, - editable: false, - hiddenName: 'middleName', - displayField: 'label', - valueField: 'value', - store: new Ext.data.JsonStore({ - fields: ['label', 'value'], - data: [ - {label: TYPO3.l10n.localize('yes'), value: true}, - {label: TYPO3.l10n.localize('no'), value: false} - ] - }), - listeners: { - 'select': { - scope: this, - fn: this.storeValue - } - } - }); - break; - } - }, this); - - var config = { - items: [{ - xtype: 'fieldset', - title: '', - autoHeight: true, - border: false, - defaults: { - width: 150, - msgTarget: 'side' - }, - defaultType: 'textfieldsubmit', - items: formItems - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various.superclass.initComponent.apply(this, arguments); - - // Initialize clientvalidation event - this.on('clientvalidation', this.validation, this); - - // Fill the form with the configuration values - this.fillForm(); - }, - - /** - * Store a changed value from the form in the element - * - * @param {Object} field The field which has changed - */ - storeValue: function(field) { - if (field.isValid()) { - var fieldName = field.getName(); - - var formConfiguration = {various: {}}; - formConfiguration.various[fieldName] = field.getValue(); - - this.element.setConfigurationValue(formConfiguration); - } - }, - - /** - * Fill the form with the configuration of the element - * - * @return void - */ - fillForm: function() { - this.getForm().setValues(this.element.configuration.various); - }, - - /** - * Called by the clientvalidation event - * - * Adds or removes the error class if the form is valid or not - * - * @param {Object} formPanel This formpanel - * @param {Boolean} valid True if the client validation is true - */ - validation: function(formPanel, valid) { - if (this.el) { - if (valid && this.el.hasClass('validation-error')) { - this.removeClass('validation-error'); - this.fireEvent('validation', 'various', valid); - } else if (!valid && !this.el.hasClass('validation-error')) { - this.addClass('validation-error'); - this.fireEvent('validation', 'various', valid); - } - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-forms-various', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Various); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Panel.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Panel.js deleted file mode 100644 index acff06a5a3d0eaf12b76239bbc6724d4b92a77ac..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Left/Options/Panel.js +++ /dev/null @@ -1,148 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options'); - -/** - * The options panel - * - * @class TYPO3.Form.Wizard.Viewport.Left.Options.Panel - * @extends Ext.Panel - */ -TYPO3.Form.Wizard.Viewport.Left.Options.Panel = Ext.extend(Ext.Panel, { - /** - * @cfg {Object} element - * The element for the options form - */ - element: null, - - /** - * @cfg {Boolean} border - * True to display the borders of the panel's body element, false to hide - * them (defaults to true). By default, the border is a 2px wide inset - * border, but this can be further altered by setting bodyBorder to false. - */ - border: false, - - /** - * @cfg {Object|Function} defaults - * This option is a means of applying default settings to all added items - * whether added through the items config or via the add or insert methods. - */ - defaults: { - autoHeight: true, - border: false, - padding: 0 - }, - - /** - * Constructor - * - * Add the form elements to the tab - */ - initComponent: function() { - var accordions = this.getAccordionsBySettings(); - var accordionItems = new Array(); - - // Adds the specified events to the list of events which this Observable may fire. - this.addEvents({ - 'validation': true - }); - - Ext.iterate(accordions, function(item, index, allItems) { - var accordionXtype = 'typo3-form-wizard-viewport-left-options-forms-' + item; - accordionItems.push({ - xtype: accordionXtype, - element: this.element, - listeners: { - 'validation': { - fn: this.validation, - scope: this - } - } - }); - }, this); - - var config = { - items: [{ - xtype: 'panel', - layout: 'accordion', - ref: 'accordion', - defaults: { - autoHeight: true, - cls: 'x-panel-accordion' - }, - items: accordionItems - }] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Left.Options.Panel.superclass.initComponent.apply(this, arguments); - }, - - /** - * Adds the accordions depending on the TSconfig settings - * - * It will first look at showAccordions for the tab, then it will filter it - * down with the accordions allowed for the element. - * - * @returns {Array} - */ - getAccordionsBySettings: function() { - var accordions = []; - if (this.element) { - var elementType = this.element.xtype.split('-').pop(); - - var allowedDefaultAccordions = []; - try { - allowedDefaultAccordions = TYPO3.Form.Wizard.Settings.defaults.tabs.options.showAccordions.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedDefaultAccordions = [ - 'legend', - 'label', - 'attributes', - 'options', - 'validation', - 'filters', - 'various' - ]; - } - - var allowedElementAccordions = []; - try { - allowedElementAccordions = TYPO3.Form.Wizard.Settings.elements[elementType].showAccordions.split(/[, ]+/); - } catch (error) { - // The object has not been found - allowedElementAccordions = allowedDefaultAccordions; - } - - Ext.iterate(allowedElementAccordions, function(item, index, allItems) { - var accordionXtype = 'typo3-form-wizard-viewport-left-options-forms-' + item; - if ( - Ext.isDefined(this.element.configuration[item]) && - allowedElementAccordions.indexOf(item) > -1 && - Ext.ComponentMgr.isRegistered(accordionXtype) - ) { - accordions.push(item); - } - }, this); - } - - return accordions; - }, - - /** - * Fire the validation event - * - * This is only a pass-through for the accordion validation events - * - * @param accordion - * @param valid - */ - validation: function(accordion, valid) { - this.fireEvent('validation', accordion, valid); - } -}); - -Ext.reg('typo3-form-wizard-viewport-left-options-panel', TYPO3.Form.Wizard.Viewport.Left.Options.Panel); \ No newline at end of file diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Right.js b/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Right.js deleted file mode 100644 index 994fee3aec4c36f0905f7ad6f87a45b45bc5ef2d..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Resources/Public/JavaScript/Wizard/Viewport/Right.js +++ /dev/null @@ -1,144 +0,0 @@ -Ext.namespace('TYPO3.Form.Wizard.Viewport'); - -/** - * The form container on the right side - * - * @class TYPO3.Form.Wizard.Viewport.Right - * @extends TYPO3.Form.Wizard.Elements.Container - */ -TYPO3.Form.Wizard.Viewport.Right = Ext.extend(Ext.Container, { - /** - * @cfg {String} id - * The unique id of this component (defaults to an auto-assigned id). - * You should assign an id if you need to be able to access the component - * later and you do not have an object reference available - * (e.g., using Ext.getCmp). - * - * Note that this id will also be used as the element id for the containing - * HTML element that is rendered to the page for this component. - * This allows you to write id-based CSS rules to style the specific - * instance of this component uniquely, and also to select sub-elements - * using this component's id as the parent. - */ - id: 'formwizard-right', - - /** - * @cfg {Mixed} autoEl - * A tag name or DomHelper spec used to create the Element which will - * encapsulate this Component. - */ - autoEl: 'ol', - - /** - * @cfg {String} region - * Note: this config is only used when this BoxComponent is rendered - * by a Container which has been configured to use the BorderLayout - * layout manager (e.g. specifying layout:'border'). - */ - region: 'center', - - /** - * @cfg {Boolean} autoScroll - * true to use overflow:'auto' on the components layout element and show - * scroll bars automatically when necessary, false to clip any overflowing - * content (defaults to false). - */ - autoScroll: true, - - /** - * Constructor - */ - initComponent: function() { - var config = { - items: [ - { - xtype: 'typo3-form-wizard-elements-basic-form' - } - ] - }; - - // apply config - Ext.apply(this, Ext.apply(this.initialConfig, config)); - - // call parent - TYPO3.Form.Wizard.Viewport.Right.superclass.initComponent.apply(this, arguments); - - // Initialize the form after rendering - this.on('afterrender', this.initializeForm, this); - }, - - /** - * Initialize the form after rendering - */ - initializeForm: function() { - this.loadForm(); - - }, - - /** - * Load the form from config - * - * Loads the configuration and initializes the history - */ - loadForm: function() { - this.loadConfiguration(TYPO3.Form.Wizard.Settings.Configuration); - this.initializeHistory(); - }, - - /** - * Initialize the history - * - * After the form has been rendered for the first time, we need to add the - * initial configuration to the history, so it is possible to go back to the - * initial state of the form when it was loaded. - */ - initializeHistory: function() { - TYPO3.Form.Wizard.Helpers.History.setHistory(); - this.setForm(); - }, - - /** - * Called by the history class when a change has been made in the form - * - * Constructs an array out of this component and the children to add it to - * the history or to use when saving the form - * - * @returns {Array} - */ - getConfiguration: function() { - var historyConfiguration = new Array; - - if (this.items) { - this.items.each(function(item, index, length) { - historyConfiguration.push(item.getConfiguration()); - }, this); - } - return historyConfiguration; - }, - - /** - * Load a previous configuration from the history - * - * Removes all the components from this container and adds the components - * from the history configuration depending on the 'undo' or 'redo' action. - * - * @param historyConfiguration - */ - loadConfiguration: function(historyConfiguration) { - this.removeAll(); - this.add(historyConfiguration); - this.doLayout(); - this.setForm(); - }, - - /** - * Pass the form configuration to the left form tab - */ - setForm: function() { - if (Ext.getCmp('formwizard-left-form')) { - Ext.getCmp('formwizard-left-form').setForm(this.get(0)); - } - } -}); - -Ext.reg('typo3-form-wizard-viewport-right', TYPO3.Form.Wizard.Viewport.Right); diff --git a/typo3/sysext/form/Tests/Unit/Controller/AbstractBackendControllerTest.php b/typo3/sysext/form/Tests/Unit/Controller/AbstractBackendControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ddbf506ca1712bb04358b12f53ac51472834c89c --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Controller/AbstractBackendControllerTest.php @@ -0,0 +1,48 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Controller\AbstractBackendController; + +/** + * Test case + */ +class AbstractBackendControllerTest extends UnitTestCase +{ + + /** + * @test + */ + public function resolveResourcePathsExpectResolve() + { + $mockController = $this->getAccessibleMockForAbstractClass( + AbstractBackendController::class, + [], + '', + false + ); + + $input = [ + 0 => 'EXT:form/Resources/Public/Css/form.css' + ]; + + $expected = [ + 0 => 'typo3/sysext/form/Resources/Public/Css/form.css' + ]; + + $this->assertSame($expected, $mockController->_call('resolveResourcePaths', $input)); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Controller/Fixtures/BackendUtilityFixture.php b/typo3/sysext/form/Tests/Unit/Controller/Fixtures/BackendUtilityFixture.php new file mode 100644 index 0000000000000000000000000000000000000000..45177c90790b930036b4da6a51e5005ef94e664f --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Controller/Fixtures/BackendUtilityFixture.php @@ -0,0 +1,60 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Tests\Unit\Controller\Fixtures; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +/** + * Fixture for BackendUtility methods + */ +class BackendUtilityFixture +{ + + /** + * @param string $table + * @param int $uid + * @param string $fields + * @param string $where + * @param bool $useDeleteClause + * @return array + */ + public static function getRecord($table, $uid, $fields = '*', $where = '', $useDeleteClause = true) + { + return [ + 'uid' => 1, + ]; + } + + /** + * @param string $table + * @param array $row + * @param bool $prep + * @param bool $forceResult + * @return string + */ + public static function getRecordTitle($table, $row, $prep = false, $forceResult = true) + { + return 'record title'; + } + + /** + * @param string $moduleName + * @param array $urlParameters + * @return string + */ + public static function getModuleUrl($moduleName, $urlParameters = []) + { + return '/typo3/index.php?some=param'; + } +} diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Button.html b/typo3/sysext/form/Tests/Unit/Controller/Fixtures/BlankForm.yaml similarity index 100% rename from typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Button.html rename to typo3/sysext/form/Tests/Unit/Controller/Fixtures/BlankForm.yaml diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/ButtonTag.html b/typo3/sysext/form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml similarity index 100% rename from typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/ButtonTag.html rename to typo3/sysext/form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml diff --git a/typo3/sysext/form/Tests/Unit/Controller/FormEditorControllerTest.php b/typo3/sysext/form/Tests/Unit/Controller/FormEditorControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..92a7e48d9c21d7949ce40cbb48446ec86d4faa6d --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Controller/FormEditorControllerTest.php @@ -0,0 +1,424 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Controller\FormEditorController; +use TYPO3\CMS\Form\Domain\Exception\RenderingException; +use TYPO3\CMS\Form\Service\TranslationService; + +/** + * Test case + */ +class FormEditorControllerTest extends UnitTestCase +{ + + /** + * @var array A backup of registered singleton instances + */ + protected $singletonInstances = []; + + /** + * Set up + */ + public function setUp() + { + $this->singletonInstances = GeneralUtility::getSingletonInstances(); + } + + /** + * Tear down + */ + public function tearDown() + { + GeneralUtility::resetSingletonInstances($this->singletonInstances); + parent::tearDown(); + } + + /** + * @test + */ + public function getInsertRenderablesPanelConfigurationReturnsGroupedAndSortedConfiguration() + { + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + + $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [ + 'translate' + ], [], '', false); + + $mockTranslationService + ->expects($this->any()) + ->method('translate') + ->willReturnArgument(4); + + $objectMangerProphecy + ->get(TranslationService::class) + ->willReturn($mockTranslationService); + + $mockController->_set('prototypeConfiguration', [ + 'formEditor' => [ + 'formElementGroups' => [ + 'input' => [ + 'label' => 'Basic elements', + ], + 'select' => [ + 'label' => 'Select elements', + ], + ], + ], + ]); + + $input = [ + 'Password' => [ + 'group' => 'input', + 'groupSorting' => 110, + 'iconIdentifier' => 't3-form-icon-password', + 'label' => 'Password label', + ], + 'Text' => [ + 'group' => 'input', + 'groupSorting' => 100, + 'iconIdentifier' => 't3-form-icon-text', + 'label' => 'Text label', + ], + 'SingleSelect' => [ + 'group' => 'select', + 'groupSorting' => 100, + 'iconIdentifier' => 't3-form-icon-single-select', + 'label' => 'Single select label', + ], + ]; + + $expected = [ + 0 => [ + 'key' => 'input', + 'elements' => [ + 0 => [ + 'key' => 'Text', + 'cssKey' => 'text', + 'label' => 'Text label', + 'sorting' => 100, + 'iconIdentifier' => 't3-form-icon-text', + ], + 1 => [ + 'key' => 'Password', + 'cssKey' => 'password', + 'label' => 'Password label', + 'sorting' => 110, + 'iconIdentifier' => 't3-form-icon-password', + ], + ], + 'label' => 'Basic elements', + ], + 1 => [ + 'key' => 'select', + 'elements' => [ + 0 => [ + 'key' => 'SingleSelect', + 'cssKey' => 'singleselect', + 'label' => 'Single select label', + 'sorting' => 100, + 'iconIdentifier' => 't3-form-icon-single-select', + ], + ], + 'label' => 'Select elements', + ], + ]; + + $this->assertSame($expected, $mockController->_call('getInsertRenderablesPanelConfiguration', $input)); + } + + /** + * @test + */ + public function getFormEditorDefinitionsReturnReducedConfiguration() + { + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + + $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [ + 'translateValuesRecursive' + ], [], '', false); + + $mockTranslationService + ->expects($this->any()) + ->method('translateValuesRecursive') + ->willReturnArgument(0); + + $objectMangerProphecy + ->get(TranslationService::class) + ->willReturn($mockTranslationService); + + $mockController->_set('prototypeConfiguration', [ + 'formEditor' => [ + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + 'formElementPropertyValidatorsDefinition' => [ + 'NotEmpty' => [ + 'key' => 'value', + ], + ], + ], + 'formElementsDefinition' => [ + 'Form' => [ + 'formEditor' => [ + 'key' => 'value', + ], + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + ], + 'Text' => [ + 'formEditor' => [ + 'key' => 'value', + ], + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + ], + ], + 'finishersDefinition' => [ + 'Confirmation' => [ + 'formEditor' => [ + 'key' => 'value', + ], + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + ], + 'EmailToSender' => [ + 'formEditor' => [ + 'key' => 'value', + ], + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + ], + ], + 'someOtherValues' => [ + 'horst' => [ + 'key' => 'value', + ], + 'gertrud' => [ + 'key' => 'value', + ], + ], + ]); + + $expected = [ + 'formElements' => [ + 'Form' => [ + 'key' => 'value', + ], + 'Text' => [ + 'key' => 'value', + ], + ], + 'finishers' => [ + 'Confirmation' => [ + 'key' => 'value', + ], + 'EmailToSender' => [ + 'key' => 'value', + ], + ], + 'formElementPropertyValidators' => [ + 'NotEmpty' => [ + 'key' => 'value', + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('getFormEditorDefinitions')); + } + + /** + * @test + */ + public function convertJsonArrayToAssociativeArrayReturnTransformedArray() + { + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'francine' => 'stan', + 'properties' => [ + 'options' => [ + 0 => [ + '_label' => 'label', + '_value' => 'value', + ], + ], + ], + ]; + + $expected = [ + 'francine' => 'stan', + 'properties' => [ + 'options' => [ + 'value' => 'label', + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('convertJsonArrayToAssociativeArray', $input)); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfTemplateRootPathsNotSet() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294720); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $mockController->_call('renderFormEditorTemplates', [], []); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfTemplateRootPathsNotArray() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294720); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'templateRootPaths' => '', + ]; + $mockController->_call('renderFormEditorTemplates', $input, []); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfLayoutRootPathsNotSet() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294721); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'templateRootPaths' => [], + ]; + $mockController->_call('renderFormEditorTemplates', $input, []); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfLayoutRootPathsNotArray() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294721); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'templateRootPaths' => [], + 'layoutRootPaths' => '', + ]; + $mockController->_call('renderFormEditorTemplates', $input, []); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfPartialRootPathsNotSet() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294722); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'templateRootPaths' => [], + 'layoutRootPaths' => [], + ]; + $mockController->_call('renderFormEditorTemplates', $input, []); + } + + /** + * @test + */ + public function renderFormEditorTemplatesThrowsExceptionIfPartialRootPathsNotArray() + { + $this->expectException(RenderingException::class); + $this->expectExceptionCode(1480294722); + + $mockController = $this->getAccessibleMock(FormEditorController::class, [ + 'dummy' + ], [], '', false); + + $input = [ + 'templateRootPaths' => [], + 'layoutRootPaths' => [], + ]; + $mockController->_call('renderFormEditorTemplates', $input, []); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Controller/FormFrontendControllerTest.php b/typo3/sysext/form/Tests/Unit/Controller/FormFrontendControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8c79fddb7a15bbc2e6bbcd19cc679d0a780c2294 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Controller/FormFrontendControllerTest.php @@ -0,0 +1,418 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Prophecy\Argument; +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Controller\FormFrontendController; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Mvc\Configuration\TypoScriptService; + +/** + * Test case + */ +class FormFrontendControllerTest extends UnitTestCase +{ + + /** + * @test + */ + public function overrideByFlexFormSettingsReturnsNoOverriddenConfigurationIfFlexformOverridesDisabled() + { + $mockController = $this->getAccessibleMock(FormFrontendController::class, [ + 'dummy' + ], [], '', false); + + $configurationServiceProphecy = $this->prophesize(ConfigurationService::class); + + $objectManagerMock = $this->createMock(ObjectManager::class); + $objectManagerMock + ->expects($this->any()) + ->method('get') + ->with(ConfigurationService::class) + ->willReturn($configurationServiceProphecy->reveal()); + + $mockController->_set('objectManager', $objectManagerMock); + + $configurationServiceProphecy->getPrototypeConfiguration(Argument::cetera())->willReturn([ + 'finishersDefinition' => [ + 'EmailToReceiver' => [ + 'FormEngine' => [ + 'elements' => [ + 'subject' => [], + 'recipientAddress' => [], + 'format' => [], + ], + ], + ], + ], + ]); + + $mockController->_set('settings', [ + 'overrideFinishers' => 0, + 'finishers' => [ + 'EmailToReceiver' => [ + 'subject' => 'Mesage Subject overridden', + 'recipientAddress' => 'your.company@example.com overridden', + 'format' => 'html overridden', + ], + ], + ]); + + $input = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject', + 'recipientAddress' => 'your.company@example.com', + 'format' => 'html', + ], + ], + ], + ]; + + $expected = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject', + 'recipientAddress' => 'your.company@example.com', + 'format' => 'html', + ], + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('overrideByFlexFormSettings', $input)); + } + + /** + * @test + */ + public function overrideByFlexFormSettingsReturnsOverriddenConfigurationIfFlexformOverridesEnabled() + { + $mockController = $this->getAccessibleMock(FormFrontendController::class, [ + 'dummy' + ], [], '', false); + + $configurationServiceProphecy = $this->prophesize(ConfigurationService::class); + + $objectManagerMock = $this->createMock(ObjectManager::class); + $objectManagerMock + ->expects($this->any()) + ->method('get') + ->with(ConfigurationService::class) + ->willReturn($configurationServiceProphecy->reveal()); + + $mockController->_set('objectManager', $objectManagerMock); + + $configurationServiceProphecy->getPrototypeConfiguration(Argument::cetera())->willReturn([ + 'finishersDefinition' => [ + 'EmailToReceiver' => [ + 'FormEngine' => [ + 'elements' => [ + 'subject' => [], + 'recipientAddress' => [], + 'format' => [], + ], + ], + ], + ], + ]); + + $mockController->_set('settings', [ + 'overrideFinishers' => 1, + 'finishers' => [ + 'EmailToReceiver' => [ + 'subject' => 'Mesage Subject overridden', + 'recipientAddress' => 'your.company@example.com overridden', + 'format' => 'html overridden', + ], + ], + ]); + + $input = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject', + 'recipientAddress' => 'your.company@example.com', + 'format' => 'html', + ], + ], + ], + ]; + + $expected = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject overridden', + 'recipientAddress' => 'your.company@example.com overridden', + 'format' => 'html overridden', + ], + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('overrideByFlexFormSettings', $input)); + } + + /** + * @test + */ + public function overrideByFlexFormSettingsReturnsNotOverriddenConfigurationKeyIfFlexformOverridesAreNotRepresentedInFormEngineConfiguration() + { + $mockController = $this->getAccessibleMock(FormFrontendController::class, [ + 'dummy' + ], [], '', false); + + $configurationServiceProphecy = $this->prophesize(ConfigurationService::class); + + $objectManagerMock = $this->createMock(ObjectManager::class); + $objectManagerMock + ->expects($this->any()) + ->method('get') + ->with(ConfigurationService::class) + ->willReturn($configurationServiceProphecy->reveal()); + + $mockController->_set('objectManager', $objectManagerMock); + + $configurationServiceProphecy->getPrototypeConfiguration(Argument::cetera())->willReturn([ + 'finishersDefinition' => [ + 'EmailToReceiver' => [ + 'FormEngine' => [ + 'elements' => [ + 'subject' => [], + 'recipientAddress' => [], + ], + ], + ], + ], + ]); + + $mockController->_set('settings', [ + 'overrideFinishers' => 1, + 'finishers' => [ + 'EmailToReceiver' => [ + 'subject' => 'Mesage Subject overridden', + 'recipientAddress' => 'your.company@example.com overridden', + 'format' => 'html overridden', + ], + ], + ]); + + $input = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject', + 'recipientAddress' => 'your.company@example.com', + 'format' => 'html', + ], + ], + ], + ]; + + $expected = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'finishers' => [ + 0 => [ + 'identifier' => 'EmailToReceiver', + 'options' => [ + 'subject' => 'Mesage Subject overridden', + 'recipientAddress' => 'your.company@example.com overridden', + 'format' => 'html', + ], + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('overrideByFlexFormSettings', $input)); + } + + /** + * @test + */ + public function overrideByTypoScriptSettingsReturnsNotOverriddenConfigurationIfNoTypoScriptOverridesExists() + { + $mockController = $this->getAccessibleMock(FormFrontendController::class, [ + 'dummy' + ], [], '', false); + + $typoScriptServiceProphecy = $this->prophesize(TypoScriptService::class); + + $objectManagerMock = $this->createMock(ObjectManager::class); + $objectManagerMock + ->expects($this->any()) + ->method('get') + ->with(TypoScriptService::class) + ->willReturn($typoScriptServiceProphecy->reveal()); + + $mockController->_set('objectManager', $objectManagerMock); + + $typoScriptServiceProphecy + ->resolvePossibleTypoScriptConfiguration(Argument::cetera()) + ->willReturnArgument(0); + + $mockController->_set('settings', [ + 'formDefinitionOverrides' => [ + ], + ]); + + $input = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'page-1', + 'type' => 'Page', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'text-1', + 'type' => 'Text', + 'label' => 'Label', + ], + ], + ], + ], + ]; + + $expected = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'page-1', + 'type' => 'Page', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'text-1', + 'type' => 'Text', + 'label' => 'Label', + ], + ], + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('overrideByTypoScriptSettings', $input)); + } + + /** + * @test + */ + public function overrideByTypoScriptSettingsReturnsOverriddenConfigurationIfTypoScriptOverridesExists() + { + $mockController = $this->getAccessibleMock(FormFrontendController::class, [ + 'dummy' + ], [], '', false); + + $typoScriptServiceProphecy = $this->prophesize(TypoScriptService::class); + + $objectManagerMock = $this->createMock(ObjectManager::class); + $objectManagerMock + ->expects($this->any()) + ->method('get') + ->with(TypoScriptService::class) + ->willReturn($typoScriptServiceProphecy->reveal()); + + $mockController->_set('objectManager', $objectManagerMock); + + $typoScriptServiceProphecy + ->resolvePossibleTypoScriptConfiguration(Argument::cetera()) + ->willReturnArgument(0); + + $mockController->_set('settings', [ + 'formDefinitionOverrides' => [ + 'ext-form-identifier' => [ + 'label' => 'Label override', + 'renderables' => [ + 0 => [ + 'renderables' => [ + 0 => [ + 'label' => 'Label override', + ], + ], + ], + ], + ], + ], + ]); + + $input = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'page-1', + 'type' => 'Page', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'text-1', + 'type' => 'Text', + 'label' => 'Label', + ], + ], + ], + ], + ]; + + $expected = [ + 'identifier' => 'ext-form-identifier', + 'prototypeName' => 'standard', + 'label' => 'Label override', + 'renderables' => [ + 0 => [ + 'identifier' => 'page-1', + 'type' => 'Page', + 'label' => 'Label', + 'renderables' => [ + 0 => [ + 'identifier' => 'text-1', + 'type' => 'Text', + 'label' => 'Label override', + ], + ], + ], + ], + ]; + + $this->assertSame($expected, $mockController->_call('overrideByTypoScriptSettings', $input)); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Controller/FormManagerControllerTest.php b/typo3/sysext/form/Tests/Unit/Controller/FormManagerControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..83ac02029597a9d4fd64b3a922e43d45f9559da3 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Controller/FormManagerControllerTest.php @@ -0,0 +1,410 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Prophecy\Argument; +use TYPO3\CMS\Core\Resource\Folder; +use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext; +use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Controller\FormManagerController; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager; +use TYPO3\CMS\Form\Service\TranslationService; +use TYPO3\CMS\Form\Tests\Unit\Controller\Fixtures\BackendUtilityFixture; + +/** + * Test case + */ +class FormManagerControllerTest extends UnitTestCase +{ + + /** + * @var array A backup of registered singleton instances + */ + protected $singletonInstances = []; + + /** + * Set up + */ + public function setUp() + { + $this->singletonInstances = GeneralUtility::getSingletonInstances(); + } + + /** + * Tear down + */ + public function tearDown() + { + GeneralUtility::resetSingletonInstances($this->singletonInstances); + parent::tearDown(); + } + + /** + * @test + */ + public function getAccessibleFormStorageFoldersReturnsProcessedArray() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $formPersistenceManagerProphecy = $this->prophesize(FormPersistenceManager::class); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + $mockController->_set('formPersistenceManager', $formPersistenceManagerProphecy->reveal()); + + $folder1 = new Folder($mockStorage, '/user_upload/', 'user_upload'); + $folder2 = new Folder($mockStorage, '/forms/', 'forms'); + + $formPersistenceManagerProphecy->getAccessibleFormStorageFolders(Argument::cetera())->willReturn([ + '1:/user_upload/' => $folder1, + '2:/forms/' => $folder2, + ]); + + $expected = [ + 0 => [ + 'label' => 'user_upload', + 'value' => '1:/user_upload/', + ], + 1 => [ + 'label' => 'forms', + 'value' => '2:/forms/', + ], + ]; + + $this->assertSame($expected, $mockController->_call('getAccessibleFormStorageFolders')); + } + + /** + * @test + */ + public function getFormManagerAppInitialDataReturnsProcessedArray() + { + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + + $mockTranslationService = $this->getAccessibleMock(TranslationService::class, [ + 'translateValuesRecursive' + ], [], '', false); + + $mockTranslationService + ->expects($this->any()) + ->method('translateValuesRecursive') + ->willReturnArgument(0); + + $objectMangerProphecy + ->get(TranslationService::class) + ->willReturn($mockTranslationService); + + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'getAccessibleFormStorageFolders' + ], [], '', false); + + $mockUriBuilder = $this->createMock(UriBuilder::class); + $mockControllerContext = $this->createMock(ControllerContext::class); + $mockControllerContext + ->expects($this->any()) + ->method('getUriBuilder') + ->will($this->returnValue($mockUriBuilder)); + + $mockController->_set('controllerContext', $mockControllerContext); + + $mockController->_set('formSettings', [ + 'formManager' => [ + 'selectablePrototypesConfiguration' => [], + ], + ]); + + $mockUriBuilder->expects($this->any())->method('uriFor')->willReturn( + '/typo3/index.php?some=param' + ); + + $mockController + ->expects($this->any()) + ->method('getAccessibleFormStorageFolders') + ->willReturn([ + 0 => [ + 'label' => 'user_upload', + 'value' => '1:/user_upload/', + ], + ]); + + $expected = [ + 'selectablePrototypesConfiguration' => [], + 'accessibleFormStorageFolders' => [ + 0 => [ + 'label' => 'user_upload', + 'value' => '1:/user_upload/', + ], + ], + 'endpoints' => [ + 'create' => '/typo3/index.php?some=param', + 'duplicate' => '/typo3/index.php?some=param', + 'delete' => '/typo3/index.php?some=param', + 'references' => '/typo3/index.php?some=param', + ], + ]; + + $this->assertSame(json_encode($expected), $mockController->_call('getFormManagerAppInitialData')); + } + + /** + * @test + */ + public function getAvailableFormDefinitionsReturnsProcessedArray() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'getReferences' + ], [], '', false); + + $formPersistenceManagerProphecy = $this->prophesize(FormPersistenceManager::class); + $mockController->_set('formPersistenceManager', $formPersistenceManagerProphecy->reveal()); + + $formPersistenceManagerProphecy->listForms(Argument::cetera())->willReturn([ + 0 => [ + 'identifier' => 'ext-form-identifier', + 'name' => 'some name', + 'persistenceIdentifier' => '1:/user_uploads/someFormName.yaml', + 'readOnly' => false, + 'location' => 'storage', + 'duplicateIdentifier' => false, + ], + ]); + + $mockController + ->expects($this->any()) + ->method('getReferences') + ->willReturn([ + 'someRow', + 'anotherRow', + ]); + + $expected = [ + 0 => [ + 'identifier' => 'ext-form-identifier', + 'name' => 'some name', + 'persistenceIdentifier' => '1:/user_uploads/someFormName.yaml', + 'readOnly' => false, + 'location' => 'storage', + 'duplicateIdentifier' => false, + 'referenceCount' => 2, + ], + ]; + + $this->assertSame($expected, $mockController->_call('getAvailableFormDefinitions')); + } + + /** + * @test + */ + public function getProcessedReferencesRowsThrowsExceptionIfPersistenceIdentifierIsEmpty() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionCode(1477071939); + + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $mockController->_call('getProcessedReferencesRows', ''); + } + + /** + * @test + */ + public function getProcessedReferencesRowsReturnsProcessedArray() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'getReferences', + 'getBackendUtility', + ], [], '', false); + + $mockController + ->expects($this->any()) + ->method('getBackendUtility') + ->willReturn(BackendUtilityFixture::class); + + $mockController + ->expects($this->any()) + ->method('getReferences') + ->willReturn([ + 0 => [ + 'tablename' => 'tt_content', + 'recuid' => -1, + ], + ]); + + $expected = [ + 0 => [ + 'recordPageTitle' => 'record title', + 'recordTitle' => 'record title', + 'recordIcon' => +'<span class="t3js-icon icon icon-size-small icon-state-default icon-default-not-found" data-identifier="default-not-found"> + <span class="icon-markup"> +<img src="typo3/sysext/core/Resources/Public/Icons/T3Icons/default/default-not-found.svg" width="16" height="16" /> + </span> + +</span>', + 'recordUid' => -1, + 'recordEditUrl' => '/typo3/index.php?some=param', + ], + ]; + + $this->assertSame($expected, $mockController->_call('getProcessedReferencesRows', 'fake')); + } + + /** + * @test + */ + public function isValidTemplatePathReturnsTrueIfTemplateIsDefinedAndExists() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $mockController->_set('formSettings', [ + 'formManager' => [ + 'selectablePrototypesConfiguration' => [ + 0 => [ + 'identifier' => 'standard', + 'label' => 'some label', + 'newFormTemplates' => [ + 0 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/BlankForm.yaml', + 'label' => 'some label', + ], + 1 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml', + 'label' => 'some other label', + ], + ], + ], + ], + ], + ]); + + $this->assertTrue($mockController->_call('isValidTemplatePath', 'standard', 'EXT:form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml')); + } + + /** + * @test + */ + public function isValidTemplatePathReturnsFalseIfTemplateIsDefinedButNotExists() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $mockController->_set('formSettings', [ + 'formManager' => [ + 'selectablePrototypesConfiguration' => [ + 0 => [ + 'identifier' => 'standard', + 'label' => 'some label', + 'newFormTemplates' => [ + 0 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/BlankForm.yaml', + 'label' => 'some label', + ], + 1 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml', + 'label' => 'some other label', + ], + ], + ], + ], + ], + ]); + + $this->assertFalse($mockController->_call('isValidTemplatePath', 'standard', 'EXT:form/Tests/Unit/Controller/Fixtures/NonExistingForm.yaml')); + } + + /** + * @test + */ + public function isValidTemplatePathReturnsFalseIfTemplateIsNotDefinedAndExists() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $mockController->_set('formSettings', [ + 'formManager' => [ + 'selectablePrototypesConfiguration' => [ + 0 => [ + 'identifier' => 'standard', + 'label' => 'some label', + 'newFormTemplates' => [ + 0 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/BlankForm.yaml', + 'label' => 'some label', + ], + 1 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml', + 'label' => 'some other label', + ], + ], + ], + 1 => [ + 'identifier' => 'other', + 'label' => 'some label', + 'newFormTemplates' => [ + 0 => [ + 'templatePath' => 'EXT:form/Tests/Unit/Controller/Fixtures/BlankForm.yaml', + 'label' => 'some label', + ], + ], + ], + ], + ], + ]); + + $this->assertFalse($mockController->_call('isValidTemplatePath', 'other', 'EXT:form/Tests/Unit/Controller/Fixtures/SimpleContactForm.yaml')); + } + + /** + * @test + */ + public function convertFormNameToIdentifierRemoveSpaces() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $input = 'test form'; + $expected = 'testform'; + $this->assertSame($expected, $mockController->_call('convertFormNameToIdentifier', $input)); + } + + /** + * @test + */ + public function convertFormNameToIdentifierRemoveSpecialChars() + { + $mockController = $this->getAccessibleMock(FormManagerController::class, [ + 'dummy' + ], [], '', false); + + $input = 'test form ä#!_-01'; + $expected = 'testform_-01'; + $this->assertSame($expected, $mockController->_call('convertFormNameToIdentifier', $input)); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Domain/Configuration/ConfigurationServiceTest.php b/typo3/sysext/form/Tests/Unit/Domain/Configuration/ConfigurationServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..76a6ab53d8003f0d862ac70a04933187f44670e6 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Domain/Configuration/ConfigurationServiceTest.php @@ -0,0 +1,71 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Domain\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Domain\Configuration\ConfigurationService; +use TYPO3\CMS\Form\Domain\Configuration\Exception\PrototypeNotFoundException; + +/** + * Test case + */ +class ConfigurationServiceTest extends UnitTestCase +{ + + /** + * @test + */ + public function getPrototypeConfigurationReturnsPrototypeConfiguration() + { + $mockConfigurationService = $this->getAccessibleMock(ConfigurationService::class, [ + 'dummy' + ], [], '', false); + + $mockConfigurationService->_set('formSettings', [ + 'prototypes' => [ + 'standard' => [ + 'key' => 'value', + ], + ], + ]); + + $expected = [ + 'key' => 'value', + ]; + + $this->assertSame($expected, $mockConfigurationService->getPrototypeConfiguration('standard')); + } + + /** + * @test + */ + public function getPrototypeConfigurationThrowsExceptionIfNoPrototypeFound() + { + $mockConfigurationService = $this->getAccessibleMock(ConfigurationService::class, [ + 'dummy' + ], [], '', false); + + $this->expectException(PrototypeNotFoundException::class); + $this->expectExceptionCode(1475924277); + + $mockConfigurationService->_set('formSettings', [ + 'prototypes' => [ + 'noStandard' => [], + ], + ]); + + $mockConfigurationService->getPrototypeConfiguration('standard'); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Domain/Model/ConfigurationTest.php b/typo3/sysext/form/Tests/Unit/Domain/Model/ConfigurationTest.php deleted file mode 100644 index ca41160d961488d119f0cae99cbd03cd4f3569ab..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Domain/Model/ConfigurationTest.php +++ /dev/null @@ -1,136 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Domain; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Tests\UnitTestCase; -use TYPO3\CMS\Form\Domain\Model\Configuration; -use TYPO3\CMS\Form\Domain\Repository\TypoScriptRepository; - -/** - * Test case for class \TYPO3\CMS\Form\Domain\Model\Configuration - */ -class ConfigurationTest extends UnitTestCase -{ - /** - * @var Configuration - */ - protected $subject = null; - - /* - * @var TypoScriptRepository|\Prophecy\Prophecy\ObjectProphecy - */ - protected $typoScriptRepositoryProphecy; - - /** - * Sets up this test case. - */ - protected function setUp() - { - parent::setUp(); - $this->typoScriptRepositoryProphecy = $this->prophesize(TypoScriptRepository::class); - $this->subject = $this->getAccessibleMock(Configuration::class, ['__none']); - $this->subject->_set('typoScriptRepository', $this->typoScriptRepositoryProphecy->reveal()); - } - - /** - * Tears down this test case. - */ - protected function tearDown() - { - parent::tearDown(); - unset($this->typoScriptRepositoryProphecy); - unset($this->subject); - } - - /** - * @param array $typoScript - * @param string $globalThemeName - * @param array $expected - * - * @test - * @dataProvider propertiesAreUpdatedFromTypoScriptDataProvider - */ - public function propertiesAreUpdatedFromTypoScript(array $typoScript, $globalThemeName, array $expected) - { - $this->typoScriptRepositoryProphecy - ->getModelConfigurationByScope('FORM', 'themeName') - ->willReturn($globalThemeName); - - $this->subject->setTypoScript($typoScript); - $this->assertEquals($expected['prefix'], $this->subject->getPrefix()); - $this->assertEquals($expected['contentElementRendering'], $this->subject->getContentElementRendering()); - } - - /** - * @return array - */ - public function propertiesAreUpdatedFromTypoScriptDataProvider() - { - return [ - '#1' => [ - [ - 'prefix' => '', - 'themeName' => '', - 'disableContentElement' => false, - ], - '', - [ - 'prefix' => 'form', - 'themeName' => 'Default', - 'contentElementRendering' => true, - ], - ], - '#2' => [ - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'disableContentElement' => true, - ], - '', - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'contentElementRendering' => false, - ], - ], - '#3' => [ - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'disableContentElement' => true, - ], - '', - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'contentElementRendering' => false, - ], - ], - '#4' => [ - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'disableContentElement' => true, - ], - '', - [ - 'prefix' => 'somePrefix', - 'themeName' => 'someTheme', - 'contentElementRendering' => false, - ], - ], - ]; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/AlphabeticFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/AlphabeticFilterTest.php deleted file mode 100644 index 5c45350e5dd4c9c02e22c0793023ae6b5dd4f76e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/AlphabeticFilterTest.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class AlphabeticFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\AlphabeticFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\AlphabeticFilter(); - } - - /** - * @test - */ - public function filterForStringWithUnicodeCharactersAndSpacesReturnsInputString() - { - $input = 'My name contains äøüößØœ'; - // This is default, but let's be explicit: - $this->subject->setAllowWhiteSpace(true); - $this->assertSame($input, $this->subject->filter($input)); - } - - /** - * @test - */ - public function filterForStringWithUnicodeCharactersAndSpacesWithAllowWhitespaceSetToFalseReturnsInputStringWithoutSpaces() - { - $input = 'My name contains äøüößØœ'; - $expected = 'MynamecontainsäøüößØœ'; - $this->subject->setAllowWhiteSpace(false); - $this->assertSame($expected, $this->subject->filter($input)); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/AlphanumericFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/AlphanumericFilterTest.php deleted file mode 100644 index 3d1c6a30d37593d06cb3a6ac60d81c639e04d8dd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/AlphanumericFilterTest.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class AlphanumericFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\AlphanumericFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\AlphanumericFilter(); - } - - /** - * @test - */ - public function filterForStringWithUnicodeCharactersAndSpacesReturnsInputString() - { - $input = 'My name contains äøüößØœ'; - // This is default, but let's be explicit: - $this->subject->setAllowWhiteSpace(true); - $this->assertSame($input, $this->subject->filter($input)); - } - - /** - * @test - */ - public function filterForStringWithUnicodeCharactersAndSpacesWithAllowWhitespaceSetToFalseReturnsInputStringWithoutSpaces() - { - $input = 'My name contains äøüößØœ'; - $expected = 'MynamecontainsäøüößØœ'; - $this->subject->setAllowWhiteSpace(false); - $this->assertSame($expected, $this->subject->filter($input)); - } - - /** - * @test - */ - public function filterAllowsNumericCharacters() - { - $this->assertSame('foo23bar', $this->subject->filter('foo23bar')); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/CurrencyFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/CurrencyFilterTest.php deleted file mode 100644 index b141ae4db01ecd4453fc369b155719c42c8dcd8b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/CurrencyFilterTest.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class CurrencyFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\CurrencyFilter - */ - protected $subject; - - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\CurrencyFilter(); - } - - public function validDataProvider() - { - return [ - '1200 => 1.200,00' => [ - '1200', // input - '.', // thousand separator - ',', // decimal point - '1.200,00' // expected - ], - '0 => 0,00' => [ - '0', - null, - ',', - '0,00' - ], - '3333.33 => 3,333.33' => [ - '3333.33', - ',', - '.', - '3,333.33' - ], - '1099.33 => 1 099,33' => [ - '1099.33', - ' ', - ',', - '1 099,33' - ], - '1200,00 => 1.200,00' => [ - '1200,00', // input - '.', // thousand separator - ',', // decimal point - '1.200,00' // expected - ], - '1.200,00 => 1.200,00' => [ - '1.200,00', // input - '.', // thousand separator - ',', // decimal point - '1.200,00' // expected - ], - '1.200 => 1.200,00' => [ - '1.200', // input - '.', // thousand separator - ',', // decimal point - '1.200,00' // expected - ], - '-1 => -1,00' => [ - '-1', // input - '.', // thousand separator - ',', // decimal point - '-1,00' // expected - ], - '1.200 => 1.200,00' => [ - '1.200', // input - '.', // thousand separator - ',', // decimal point - '1.200,00' // expected - ], - ]; - } - - /** - * @test - * @dataProvider validDataProvider - */ - public function filterForVariousIntegerInputsReturnsFormattedCurrencyNotation($input, $thousandSeparator, $decimalPoint, $expected) - { - $this->subject->setThousandSeparator($thousandSeparator); - $this->subject->setDecimalsPoint($decimalPoint); - $this->assertSame($expected, $this->subject->filter($input)); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/DigitFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/DigitFilterTest.php deleted file mode 100644 index e438af25b075c647f5185aa72a5db790a1943a5f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/DigitFilterTest.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class DigitFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\DigitFilter - */ - protected $subject; - - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\DigitFilter(); - } - - public function validDataProvider() - { - return [ - '1,00 -> 100' => ['1,00', '100'], - '1E+49 -> 149' => ['1E+49', '149'], - '100 -> 100' => ['100', '100'], - '00000 -> 00000' => ['00000', '00000'], - 'ABCD -> ""' => ['ABCD', ''], - ]; - } - - /** - * @test - * @dataProvider validDataProvider - */ - public function filterForStringsReturnsStringsFilteredToOnlyContainDigits($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/IntegerFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/IntegerFilterTest.php deleted file mode 100644 index 3194a6b0223f9ef7ccb9f33cc4fa74359d379614..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/IntegerFilterTest.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class IntegerFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\IntegerFilter - */ - protected $subject; - - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\IntegerFilter(); - } - - public function dataProvider() - { - return [ - '"1" -> 1' => ['1', 1], - '1 -> 1' => [1, 1], - '1.1 -> 1' => [1.1, 1], - 'a -> 0' => ['a', 0], - 'a42 -> 0' => ['a42', 0], - '-100.00 -> -100' => [-100.00, -100], - ]; - } - - /** - * @test - * @dataProvider dataProvider - */ - public function filterForVariousInputReturnsInputCastedToInteger($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/LowerCaseFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/LowerCaseFilterTest.php deleted file mode 100644 index 9016aee750e0abe871b7255332889d88596112d9..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/LowerCaseFilterTest.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class LowerCaseFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\LowerCaseFilter - */ - protected $subject; - - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\LowerCaseFilter(); - $GLOBALS['TSFE'] = new \stdClass(); - $GLOBALS['TSFE']->csConvObj = new \TYPO3\CMS\Core\Charset\CharsetConverter(); - } - - public function dataProvider() - { - return [ - 'a -> a' => ['a', 'a'], - 'A -> a' => ['A', 'a'], - 'AaA -> aaa' => ['AaA', 'aaa'], - 'ÜßbÉØ -> üßbéø' => ['ÜßbÉØ', 'üßbéø'], - '01A23b -> 01a23b' => ['01A23b', '01a23b'], - ]; - } - - /** - * @test - * @dataProvider dataProvider - */ - public function filterForVariousInputReturnsLowercasedInput($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/RegExpFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/RegExpFilterTest.php deleted file mode 100644 index 8d1404b495fb2b4003c2e1b58ab3e39bca407a0e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/RegExpFilterTest.php +++ /dev/null @@ -1,65 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class RegExpFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\RegExpFilter - */ - protected $subject; - - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\RegExpFilter(); - } - - public function dataProvider() - { - return [ - 'a-a -> aa for /-/' => [ - 'a-a', - '/-/', - 'aa' - ], - 'aaa -> "" for /.+/' => [ - 'aaa', - '/.+/', - '' - ], - 'aAa -> aa for /[^a]+/' => [ - 'aAa', - '/[^a]+/', - 'aa' - ], - ]; - } - - /** - * @test - * @dataProvider dataProvider - */ - public function filterForStringReturnsInputWithoutCharactersMatchedByRegularExpression($input, $regularExpression, $expected) - { - $this->subject->setRegularExpression($regularExpression); - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/StripNewLinesFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/StripNewLinesFilterTest.php deleted file mode 100644 index 9aa3b16006f02898f8fb9f541157ac78b74fd869..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/StripNewLinesFilterTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class StripNewLinesFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\StripNewLinesFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\StripNewLinesFilter(); - } - - public function dataProviderWithNewlines() - { - return [ - 'some\rtext' => ["some\rtext", 'some text'], - 'some\ntext' => ["some\ntext", 'some text'], - 'some\r\ntext' => ["some\r\ntext", 'some text'], - 'somechr(13)text' => ['some' . chr(13) . 'text', 'some text'], - 'somechr(10)text' => ['some' . chr(10) . 'text', 'some text'], - 'somechr(13)chr(10)text' => ['some' . chr(13) . chr(10) . 'text', 'some text'], - 'someCRtext' => ['some' . CR . 'text', 'some text'], - 'someLFtext' => ['some' . LF . 'text', 'some text'], - 'someCRLFtext' => ['some' . CRLF . 'text', 'some text'], - 'some^Mtext' => ['some -text', 'some text'], - 'trailing newline\r' => ["trailing newline\n", 'trailing newline '], - 'trailing newline\n' => ["trailing newline\r", 'trailing newline '], - 'trailing newline\r\n' => ["trailing newline\r\n", 'trailing newline '], - 'trailing newlinechr(13)' => ['trailing newline' . chr(13), 'trailing newline '], - 'trailing newlinechr(10)' => ['trailing newline' . chr(10), 'trailing newline '], - 'trailing newlinechr(13)chr(10)' => ['trailing newline' . chr(13) . chr(10), 'trailing newline '], - 'trailing newlineCR' => ['trailing newline' . CR, 'trailing newline '], - 'trailing newlineLF' => ['trailing newline' . LF, 'trailing newline '], - 'trailing newlineCRLF' => ['trailing newline' . CRLF, 'trailing newline '], - 'trailing newline^M' => ['trailing newline -', 'trailing newline '] - ]; - } - - /** - * @test - * @dataProvider dataProviderWithNewlines - */ - public function filterForStringWithNewlineReturnsStringWithoutNewline($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/TitleCaseFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/TitleCaseFilterTest.php deleted file mode 100644 index 79a40462f3f488528527129ef3346561cf3ddd40..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/TitleCaseFilterTest.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Charset\CharsetConverter; -use TYPO3\CMS\Form\Domain\Filter\TitleCaseFilter; - -/** - * Test case - */ -class TitleCaseFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var TitleCaseFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new TitleCaseFilter(); - $GLOBALS['TSFE'] = new \stdClass(); - $GLOBALS['TSFE']->csConvObj = new CharsetConverter(); - } - - /** - * @return array - */ - public function stringProvider() - { - return [ - 'some text' => ['some text', 'Some Text'], - 'some Text' => ['some Text', 'Some Text'], - 'Ein Maß' => ['Ein Maß', 'Ein Maß'], - '¿por que?' => ['¿por que?', '¿por Que?'], - ]; - } - - /** - * @test - * @dataProvider stringProvider - */ - public function filterForStringReturnsStringWithUppercasedWords($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/TrimFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/TrimFilterTest.php deleted file mode 100644 index d091186d8157c532ff972c41435a716958694790..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/TrimFilterTest.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class TrimFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\TrimFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\TrimFilter(); - } - - public function stringProvider() - { - return [ - '\tsome text ' => ["\tsome text ", 'some text'], - 'some text ' => ['some text ', 'some text'], - 'some text^M' => ['some text -', 'some text'], - ]; - } - - public function stringProviderForCharacterList() - { - return [ - '$some text;' => ['$some text;', 'some text', '$;'], - '$some text ' => ['$some text ', 'some text', '$ '], - '^Msome text ' => [' -some text ', 'some text', ' - '], - ]; - } - - /** - * @test - * @dataProvider stringProvider - */ - public function filterForStringWithWhitespaceInFrontAndEndReturnsStringWithoutThisWhitespace($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } - - /** - * @test - * @dataProvider stringProviderForCharacterList - */ - public function filterForStringWithCharactersInCharacterListReturnsStringWithoutTheseCharacters($input, $expected, $characterList) - { - $this->subject->setCharacterList($characterList); - - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Filter/UpperCaseFilterTest.php b/typo3/sysext/form/Tests/Unit/Filter/UpperCaseFilterTest.php deleted file mode 100644 index 37319a272a299b46ab2b061e02158ee7a8566457..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Filter/UpperCaseFilterTest.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Filter; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class UpperCaseFilterTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\Domain\Filter\UpperCaseFilter - */ - protected $subject = null; - - /** - * Set up - */ - protected function setUp() - { - $this->subject = new \TYPO3\CMS\Form\Domain\Filter\UpperCaseFilter(); - $GLOBALS['TSFE'] = new \stdClass(); - $GLOBALS['TSFE']->csConvObj = new \TYPO3\CMS\Core\Charset\CharsetConverter(); - } - - public function stringProvider() - { - return [ - 'asdf' => ['asdf', 'ASDF'], - 'as?df' => ['as?df', 'AS?DF'], - ]; - } - - /** - * @test - * @dataProvider stringProvider - */ - public function filterForStringReturnsUppercasedString($input, $expected) - { - $this->assertSame( - $expected, - $this->subject->filter($input) - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithFormPrefixFixture.php b/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithFormPrefixFixture.php deleted file mode 100644 index eb7df1475aa17f0e528f6fb8a4521ab87a968350..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithFormPrefixFixture.php +++ /dev/null @@ -1,47 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Fixtures; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Form\PostProcess\AbstractPostProcessor; -use TYPO3\CMS\Form\PostProcess\PostProcessorInterface; - -/** - * Post processor with form prefix fixture - */ -class PostProcessorWithFormPrefixFixture extends AbstractPostProcessor implements PostProcessorInterface -{ - /** - * @param \TYPO3\CMS\Form\Domain\Model\Element $form - * @param array $typoScript - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript) - { - } - - /** - * @param \TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext - */ - public function setControllerContext(\TYPO3\CMS\Form\Mvc\Controller\ControllerContext $controllerContext) - { - } - - /** - * @return string - */ - public function process() - { - return 'processedWithPrefix'; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutFormPrefixFixture.php b/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutFormPrefixFixture.php deleted file mode 100644 index 2bfb626408ab04ceca965976af7ab17f8e4dda84..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutFormPrefixFixture.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Fixtures; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Form\PostProcess\AbstractPostProcessor; -use TYPO3\CMS\Form\PostProcess\PostProcessorInterface; - -/** - * Post processor without form prefix fixture - */ -class PostProcessorWithoutFormPrefixFixture extends AbstractPostProcessor implements PostProcessorInterface -{ - /** - * @param \TYPO3\CMS\Form\Domain\Model\Element $form - * @param array $typoScript - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript) - { - } - - /** - * @return string - */ - public function process() - { - return 'processedWithoutPrefix'; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutInterfaceFixture.php b/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutInterfaceFixture.php deleted file mode 100644 index 5b49b62e84e38180403b9b983c0b112efccc16e0..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Fixtures/PostProcessorWithoutInterfaceFixture.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Fixtures; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Post processor with form prefix fixture - */ -class PostProcessorWithoutInterfaceFixture -{ - /** - * @param \TYPO3\CMS\Form\Domain\Model\Element $form - * @param array $typoScript - */ - public function __construct(\TYPO3\CMS\Form\Domain\Model\Element $form, array $typoScript) - { - } - - /** - * @return string - */ - public function process() - { - return 'withoutInterface'; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Hooks/DataStructureIdentifierHookTest.php b/typo3/sysext/form/Tests/Unit/Hooks/DataStructureIdentifierHookTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bea5013271e700bf911c7177485af99eb64e3701 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Hooks/DataStructureIdentifierHookTest.php @@ -0,0 +1,240 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Hooks; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface; + +/** + * Test case + */ +class DataStructureIdentifierHookTest extends UnitTestCase +{ + /** + * @var array A backup of registered singleton instances + */ + protected $singletonInstances = []; + + /** + * Set up + */ + public function setUp() + { + $this->singletonInstances = GeneralUtility::getSingletonInstances(); + } + + /** + * Tear down + */ + public function tearDown() + { + GeneralUtility::resetSingletonInstances($this->singletonInstances); + parent::tearDown(); + } + + /** + * @test + */ + public function getDataStructureIdentifierPostProcessReturnsIdentifierForNotMatchingScenario() + { + $givenIdentifier = ['aKey' => 'aValue']; + $result = (new DataStructureIdentifierHook())->getDataStructureIdentifierPostProcess( + [], 'aTable', 'aField', [], $givenIdentifier + ); + $this->assertEquals($givenIdentifier, $result); + } + + /** + * @test + */ + public function getDataStructureIdentifierPostProcessAddDefaultValuesForNewRecord() + { + $result = (new DataStructureIdentifierHook())->getDataStructureIdentifierPostProcess( + [], 'tt_content', 'pi_flexform', ['CType' => 'form_formframework'], [] + ); + $this->assertEquals( + ['ext-form-persistenceIdentifier' => '', 'ext-form-overrideFinishers' => false], + $result + ); + } + + /** + * @test + */ + public function getDataStructureIdentifierPostProcessAddsGivenPersistenceIdentifier() + { + $row = [ + 'CType' => 'form_formframework', + 'pi_flexform' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + <T3FlexForms> + <data> + <sheet index="sDEF"> + <language index="lDEF"> + <field index="settings.persistenceIdentifier"> + <value index="vDEF">1:user_upload/karl.yml</value> + </field> + </language> + </sheet> + </data> + </T3FlexForms> + ', + ]; + $incomingIdentifier = [ + 'aKey' => 'aValue', + ]; + $expected = [ + 'aKey' => 'aValue', + 'ext-form-persistenceIdentifier' => '1:user_upload/karl.yml', + 'ext-form-overrideFinishers' => false, + ]; + $result = (new DataStructureIdentifierHook())->getDataStructureIdentifierPostProcess( + [], 'tt_content', 'pi_flexform', $row, $incomingIdentifier + ); + $this->assertEquals($expected, $result); + } + + /** + * @test + */ + public function getDataStructureIdentifierPostProcessAddsOverrideFinisherValue() + { + $row = [ + 'CType' => 'form_formframework', + 'pi_flexform' => '<?xml version="1.0" encoding="utf-8" standalone="yes" ?> + <T3FlexForms> + <data> + <sheet index="sDEF"> + <language index="lDEF"> + <field index="settings.overrideFinishers"> + <value index="vDEF">1</value> + </field> + </language> + </sheet> + </data> + </T3FlexForms> + ', + ]; + $expected = [ + 'ext-form-persistenceIdentifier' => '', + 'ext-form-overrideFinishers' => true, + ]; + $result = (new DataStructureIdentifierHook())->getDataStructureIdentifierPostProcess( + [], 'tt_content', 'pi_flexform', $row, [] + ); + $this->assertEquals($expected, $result); + } + + /** + * @test + */ + public function parseDataStructureByIdentifierPostProcessReturnsDataStructureUnchanged() + { + $dataStructure = ['foo' => 'bar']; + $expected = $dataStructure; + $result = (new DataStructureIdentifierHook())->parseDataStructureByIdentifierPostProcess( + $dataStructure, [] + ); + $this->assertEquals($expected, $result); + } + + /** + * @test + */ + public function parseDataStructureByIdentifierPostProcessAddsExistingFormItems() + { + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + $formPersistenceManagerProphecy = $this->prophesize(FormPersistenceManager::class); + $objectMangerProphecy->get(FormPersistenceManagerInterface::class) + ->willReturn($formPersistenceManagerProphecy->reveal()); + + $existingForms = [ + [ + 'persistenceIdentifier' => 'hugo1', + 'name' => 'myHugo1', + ], + [ + 'persistenceIdentifier' => 'hugo2', + 'name' => 'myHugo2', + ] + ]; + $formPersistenceManagerProphecy->listForms()->shouldBeCalled()->willReturn($existingForms); + + $incomingDataStructure = [ + 'sheets' => [ + 'sDEF' => [ + 'ROOT' => [ + 'el' => [ + 'settings.persistenceIdentifier' => [ + 'TCEforms' => [ + 'config' => [ + 'items' => [ + 0 => [ + 0 => 'default, no value', + 1 => '', + ], + ], + ], + ], + ], + ], + ], + ], + ], + ]; + + $expected = [ + 'sheets' => [ + 'sDEF' => [ + 'ROOT' => [ + 'el' => [ + 'settings.persistenceIdentifier' => [ + 'TCEforms' => [ + 'config' => [ + 'items' => [ + 0 => [ + 0 => 'default, no value', + 1 => '', + ], + 1 => [ + 0 => 'myHugo1 (hugo1)', + 1 => 'hugo1', + ], + 2 => [ + 0 => 'myHugo2 (hugo2)', + 1 => 'hugo2', + ], + ], + ], + ], + ], + ], + ], + ], + ], + ]; + + $result = (new DataStructureIdentifierHook())->parseDataStructureByIdentifierPostProcess( + $incomingDataStructure, + ['ext-form-persistenceIdentifier' => ''] + ); + + $this->assertEquals($expected, $result); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Header.yaml b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Header.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ab19ab69cdc88804edfa3c1c3e59650c25149a07 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Header.yaml @@ -0,0 +1,6 @@ +# Header 1 +# Header 2 + +yaml + +# Comment \ No newline at end of file diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Invalid.yaml b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Invalid.yaml new file mode 100644 index 0000000000000000000000000000000000000000..261338580151f403c7d395faaad662d097e8fb05 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/Fixtures/Invalid.yaml @@ -0,0 +1,2 @@ +key + yek \ No newline at end of file diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/InheritancesResolverServiceTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/InheritancesResolverServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0e7b33216a6a4da967a781f4a105565ddc74edd0 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/InheritancesResolverServiceTest.php @@ -0,0 +1,429 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\CycleInheritancesException; +use TYPO3\CMS\Form\Mvc\Configuration\InheritancesResolverService; + +/** + * Test case + */ +class InheritancesResolverServiceTest extends UnitTestCase +{ + /** + * @var InheritancesResolverService + */ + protected $subject; + + protected function setUp() + { + $this->subject = new InheritancesResolverService(); + } + + /** + * @test + */ + public function getMergedConfigurationSimpleInheritance() + { + $input = [ + 'Form' => [ + 'klaus01' => [ + 'key01' => 'value', + 'key02' => [ + 'key03' => 'value', + ], + ], + 'klaus02' => [ + '__inheritances' => [ + 10 => 'Form.klaus01', + ], + ], + ], + ]; + + $expected = [ + 'Form' => [ + 'klaus01' => [ + 'key01' => 'value', + 'key02' => [ + 'key03' => 'value' + ], + ], + 'klaus02' => [ + 'key01' => 'value', + 'key02' => [ + 'key03' => 'value', + ], + ], + ], + ]; + + $this->assertSame($expected, $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input)); + } + + /** + * @test + */ + public function getMergedConfigurationSimpleInheritanceOverrideValue() + { + $input = [ + 'Form' => [ + 'klaus01' => [ + 'key' => 'value', + ], + 'klaus02' => [ + '__inheritances' => [ + 10 => 'Form.klaus01', + ], + 'key' => 'value override', + ], + ], + ]; + + $expected = [ + 'Form' => [ + 'klaus01' => [ + 'key' => 'value', + ], + 'klaus02' => [ + 'key' => 'value override', + ], + ], + ]; + + $this->assertSame($expected, $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input)); + } + + /** + * @test + */ + public function getMergedConfigurationSimpleInheritanceRemoveValue() + { + $input = [ + 'Form' => [ + 'klaus01' => [ + 'key01' => [ + 'key02' => 'value', + ], + 'key02' => [ + 10 => [ + 'key' => 'value', + ], + 20 => [ + 'key' => 'value', + ], + ], + ], + 'klaus02' => [ + '__inheritances' => [ + 10 => 'Form.klaus01', + ], + 'key01' => null, + 'key02' => [ + 10 => null, + 20 => [ + 'key' => null, + ], + ], + ], + ], + ]; + + $expected = [ + 'Form' => [ + 'klaus01' => [ + 'key01' => [ + 'key02' => 'value', + ], + 'key02' => [ + 10 => [ + 'key' => 'value', + ], + 20 => [ + 'key' => 'value', + ], + ], + ], + 'klaus02' => [ + 'key01' => null, + 'key02' => [ + 10 => null, + 20 => [ + 'key' => null, + ], + ], + ], + ], + ]; + + $this->assertSame($expected, $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input)); + } + + /** + * @test + */ + public function getMergedConfigurationSimpleMixin() + { + $input = [ + 'Form' => [ + 'mixin01' => [ + 'key' => 'value', + ], + 'klaus01' => [ + '__inheritances' => [ + 10 => 'Form.mixin01', + ], + ], + 'klaus02' => [ + 'key' => [ + '__inheritances' => [ + 10 => 'Form.mixin01', + ], + ], + ], + ], + ]; + + $expected = [ + 'Form' => [ + 'mixin01' => [ + 'key' => 'value', + ], + 'klaus01' => [ + 'key' => 'value', + ], + 'klaus02' => [ + 'key' => [ + 'key' => 'value', + ], + ], + ], + ]; + + $this->assertSame($expected, $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input)); + } + + /** + * @test + */ + public function getMergedConfigurationAdvancedMixin() + { + $input = [ + 'Form' => [ + 'mixin01' => [ + 'key01' => 'value01', + 'key02' => 'value02', + ], + 'mixin02' => [ + '__inheritances' => [ + 10 => 'Form.mixin01', + ], + ], + 'mixin03' => [ + 'key03' => 'value03', + ], + + 'klaus01' => [ + '__inheritances' => [ + 10 => 'Form.mixin01', + ], + 'key01' => 'value01 override 01', + ], + 'klaus02' => [ + '__inheritances' => [ + 10 => 'Form.klaus01', + 20 => 'Form.mixin03', + ], + 'key01' => 'value01 override 02', + 'key02' => [ + 'horst01' => 'gerda01' + ], + 'key03' => [ + '__inheritances' => [ + 10 => 'Form.mixin02', + ], + 'key02' => null, + ], + ], + 'klaus03' => [ + '__inheritances' => [ + 10 => 'Form.klaus02', + ], + ], + ], + ]; + + $expected = [ + 'Form' => [ + 'mixin01' => [ + 'key01' => 'value01', + 'key02' => 'value02', + ], + 'mixin02' => [ + 'key01' => 'value01', + 'key02' => 'value02', + ], + 'mixin03' => [ + 'key03' => 'value03', + ], + 'klaus01' => [ + 'key01' => 'value01 override 01', + 'key02' => 'value02', + ], + 'klaus02' => [ + 'key01' => 'value01 override 02', + 'key02' => [ + 'horst01' => 'gerda01' + ], + 'key03' => [ + 'key01' => 'value01', + 'key02' => null, + ], + ], + 'klaus03' => [ + 'key01' => 'value01 override 02', + 'key02' => [ + 'horst01' => 'gerda01' + ], + 'key03' => [ + 'key01' => 'value01', + 'key02' => null, + ], + ], + ], + ]; + + $this->assertSame($expected, $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input)); + } + + /** + * @test + */ + public function getResolvedConfigurationThrowsExceptionIfCycleDepenciesOnSameLevelIsFound() + { + $input = [ + 'TYPO3' => [ + 'CMS' => [ + 'Form' => [ + 'someKey' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.anotherKey', + ], + ], + 'anotherKey' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.someKey', + ], + ], + ], + ], + ], + ]; + + $this->expectException(CycleInheritancesException::class); + $this->expectExceptionCode(1474900797); + + $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input); + } + + /** + * @test + */ + public function getResolvedConfigurationThrowsExceptionIfCycleDepenciesOnSameLevelWithGapIsFound() + { + $input = [ + 'TYPO3' => [ + 'CMS' => [ + 'Form' => [ + 'klaus1' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.klaus2', + ], + ], + 'klaus2' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.mixin1', + ], + ], + 'mixin1' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.mixin2', + ], + ], + 'mixin2' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.klaus2', + ], + ], + ], + ], + ], + ]; + + $this->expectException(CycleInheritancesException::class); + $this->expectExceptionCode(1474900799); + + $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input); + } + + /** + * @test + */ + public function getResolvedConfigurationThrowsExceptionIfCycleDepenciesOnHigherLevelIsFound() + { + $input = [ + 'TYPO3' => [ + 'CMS' => [ + 'Form' => [ + 'klaus1' => [ + 'key01' => 'value', + 'key02' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.mixin01', + ], + ], + ], + 'klaus2' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.klaus1', + ], + 'key02' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.mixin01', + 20 => 'TYPO3.CMS.Form.mixin02', + ], + ], + ], + 'mixin01' => [ + 'liselotte01' => 'value', + ], + 'mixin02' => [ + '__inheritances' => [ + 10 => 'TYPO3.CMS.Form.klaus2', + ], + 'liselotte02' => 'value', + ], + ], + ], + ], + ]; + + $this->expectException(CycleInheritancesException::class); + $this->expectExceptionCode(1474900797); + + $this->subject->reset()->setReferenceConfiguration($input)->getResolvedConfiguration($input); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/TypoScriptServiceTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/TypoScriptServiceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..31e89dbbbedd19eab5d908cd6e2fbc75352ac9e5 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/TypoScriptServiceTest.php @@ -0,0 +1,69 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Configuration\TypoScriptService; +use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; + +/** + * Test case + */ +class TypoScriptServiceTest extends UnitTestCase +{ + /** + * @test + */ + public function resolveTypoScriptConfigurationReturnsResolvedConfiguration() + { + $mockTypoScriptService = $this->getAccessibleMock(TypoScriptService::class, [ + 'getTypoScriptFrontendController' + ], [], '', false); + + $mockContentObjectRenderer = $this->getMockBuilder( + ContentObjectRenderer::class + )->getMock(); + + $fakeTypoScriptFrontendController = new \stdClass; + $fakeTypoScriptFrontendController->cObj = $mockContentObjectRenderer; + + $mockContentObjectRenderer + ->expects($this->any()) + ->method('cObjGetSingle') + ->with('TEXT', ['value' => 'rambo']) + ->will($this->returnValue('rambo')); + + $mockTypoScriptService + ->expects($this->any()) + ->method('getTypoScriptFrontendController') + ->willReturn($fakeTypoScriptFrontendController); + + $input = [ + 'key.' => [ + 'john' => 'TEXT', + 'john.' => [ + 'value' => 'rambo' + ], + ], + ]; + $expected = [ + 'key' => [ + 'john' => 'rambo', + ], + ]; + + $this->assertSame($expected, $mockTypoScriptService->_call('resolveTypoScriptConfiguration', $input)); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..faf1ab90929a191147368488a21364cc507d52bd --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Configuration/YamlSourceTest.php @@ -0,0 +1,107 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\NoSuchFileException; +use TYPO3\CMS\Form\Mvc\Configuration\Exception\ParseErrorException; +use TYPO3\CMS\Form\Mvc\Configuration\YamlSource; + +/** + * Test case + */ +class YamlSourceTest extends UnitTestCase +{ + + /** + * @test + */ + public function loadThrowsExceptionIfFileToLoadNotExists() + { + $this->expectException(NoSuchFileException::class); + $this->expectExceptionCode(1471473378); + + $mockYamlSource = $this->getAccessibleMock(YamlSource::class, [ + 'dummy', + ], [], '', false); + + $input = [ + 'EXT:form/Resources/Forms/_example.yaml' + ]; + + $mockYamlSource->_call('load', $input); + } + + /** + * @test + */ + public function loadThrowsExceptionIfFileToLoadIsNotValidYamlUseSymfonyParser() + { + if (!extension_loaded('yaml')) { + $this->expectException(ParseErrorException::class); + $this->expectExceptionCode(1480195405); + + $mockYamlSource = $this->getAccessibleMock(YamlSource::class, [ + 'dummy', + ], [], '', false); + + $input = [ + 'EXT:form/Tests/Unit/Mvc/Configuration/Fixtures/Invalid.yaml' + ]; + + $mockYamlSource->_call('load', $input); + } + } + + /** + * @test + */ + public function loadThrowsExceptionIfFileToLoadIsNotValidYamlUsePhpExtensionParser() + { + if (extension_loaded('yaml')) { + $this->expectException(ParseErrorException::class); + $this->expectExceptionCode(1391894094); + + $mockYamlSource = $this->getAccessibleMock(YamlSource::class, [ + 'dummy', + ], [], '', false); + + $input = [ + 'EXT:form/Tests/Unit/Mvc/Configuration/Fixtures/Invalid.yaml' + ]; + + $mockYamlSource->_call('load', $input); + } + } + + /** + * @test + */ + public function getHeaderFromFileReturnsHeaderPart() + { + $mockYamlSource = $this->getAccessibleMock(YamlSource::class, [ + 'dummy', + ], [], '', false); + + $input = GeneralUtility::getFileAbsFileName('EXT:form/Tests/Unit/Mvc/Configuration/Fixtures/Header.yaml'); + $expected = +'# Header 1 +# Header 2 +'; + + $this->assertSame($expected, $mockYamlSource->_call('getHeaderFromFile', $input)); + } +} diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/ContentElement.html b/typo3/sysext/form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.txt similarity index 100% rename from typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/ContentElement.html rename to typo3/sysext/form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.txt diff --git a/typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Header.html b/typo3/sysext/form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.yaml similarity index 100% rename from typo3/sysext/form/Resources/Private/Partials/Default/Confirmation/FlatElements/Header.html rename to typo3/sysext/form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.yaml diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Persistence/FormPersistenceManagerTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Persistence/FormPersistenceManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c4c32805db78f405ce270d97a5c22afbf9f95b58 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Persistence/FormPersistenceManagerTest.php @@ -0,0 +1,617 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Persistence; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Resource\StorageRepository; +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniqueIdentifierException; +use TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException; +use TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager; + +/** + * Test case + */ +class FormPersistenceManagerTest extends UnitTestCase +{ + + /** + * @test + */ + public function loadThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1477679819); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = '-1:/user_uploads/_example.php'; + $mockFormPersistenceManager->_call('load', $input); + } + + /** + * @test + */ + public function saveThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1477679820); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = '-1:/user_uploads/_example.php'; + $mockFormPersistenceManager->_call('save', $input, []); + } + + /** + * @test + */ + public function saveThrowsExceptionIfPersistenceIdentifierIsAExtensionLocationAndSaveToExtensionLocationIsNotAllowed() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1477680881); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $mockFormPersistenceManager->_set('formSettings', [ + 'persistenceManager' => [ + 'allowSaveToExtensionPaths' => false, + ], + ]); + + $input = 'EXT:form/Resources/Forms/_example.yaml'; + $mockFormPersistenceManager->_call('save', $input, []); + } + + /** + * @test + */ + public function deleteThrowsExceptionIfPersistenceIdentifierHasNoYamlExtension() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1472239534); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = '-1:/user_uploads/_example.php'; + $mockFormPersistenceManager->_call('delete', $input); + } + + /** + * @test + */ + public function deleteThrowsExceptionIfPersistenceIdentifierFileDoesNotExists() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1472239535); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'exists' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('exists') + ->willReturn(false); + + $input = '-1:/user_uploads/_example.yaml'; + $mockFormPersistenceManager->_call('delete', $input); + } + + /** + * @test + */ + public function deleteThrowsExceptionIfPersistenceIdentifierIsExtensionLocation() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1472239536); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'exists' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('exists') + ->willReturn(true); + + $input = 'EXT:form/Resources/Forms/_example.yaml'; + $mockFormPersistenceManager->_call('delete', $input); + } + + /** + * @test + */ + public function deleteThrowsExceptionIfPersistenceIdentifierIsStorageLocationAndDeleteFromStorageIsNotAllowed() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1472239516); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid', + 'exists' + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage + ->expects($this->any()) + ->method('checkFileActionPermission') + ->willReturn(false); + + $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage); + $mockStorage + ->expects($this->any()) + ->method('getFile') + ->willReturn($file); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('exists') + ->willReturn(true); + + $input = '-1:/user_uploads/_example.yaml'; + $mockFormPersistenceManager->_call('delete', $input); + } + + /** + * @test + */ + public function existsReturnsTrueIfPersistenceIdentifierIsExtensionLocationAndFileExistsAndFileHasYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.yaml'; + $this->assertTrue($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function existsReturnsFalseIfPersistenceIdentifierIsExtensionLocationAndFileExistsAndFileHasNoYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/BlankForm.txt'; + $this->assertFalse($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function existsReturnsFalseIfPersistenceIdentifierIsExtensionLocationAndFileNotExistsAndFileHasYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy' + ], [], '', false); + + $input = 'EXT:form/Tests/Unit/Mvc/Persistence/Fixtures/_BlankForm.yaml'; + $this->assertFalse($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function existsReturnsTrueIfPersistenceIdentifierIsStorageLocationAndFileExistsAndFileHasYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid' + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + $mockStorage + ->expects($this->any()) + ->method('hasFile') + ->willReturn(true); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/_example.yaml'; + $this->assertTrue($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function existsReturnsFalseIfPersistenceIdentifierIsStorageLocationAndFileExistsAndFileNoYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid' + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + $mockStorage + ->expects($this->any()) + ->method('hasFile') + ->willReturn(true); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/_example.php'; + $this->assertFalse($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function existsReturnsFalseIfPersistenceIdentifierIsStorageLocationAndFileNotExistsAndFileHasYamlExtension() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid' + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + $mockStorage + ->expects($this->any()) + ->method('hasFile') + ->willReturn(false); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/_example.yaml'; + $this->assertFalse($mockFormPersistenceManager->_call('exists', $input)); + } + + /** + * @test + */ + public function getUniquePersistenceIdentifierAppendNumberIfPersistenceIdentifierExists() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'exists' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->at(0)) + ->method('exists') + ->willReturn(true); + + $mockFormPersistenceManager + ->expects($this->at(1)) + ->method('exists') + ->willReturn(true); + + $mockFormPersistenceManager + ->expects($this->at(2)) + ->method('exists') + ->willReturn(false); + + $input = 'example'; + $expected = '-1:/user_uploads/example_2.yaml'; + $this->assertSame($expected, $mockFormPersistenceManager->_call('getUniquePersistenceIdentifier', $input, '-1:/user_uploads/')); + } + + /** + * @test + */ + public function getUniquePersistenceIdentifierAppendTimestampIfPersistenceIdentifierExists() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'exists' + ], [], '', false); + + for ($attempts = 0; $attempts <= 99; $attempts++) { + $mockFormPersistenceManager + ->expects($this->at($attempts)) + ->method('exists') + ->willReturn(true); + } + + $mockFormPersistenceManager + ->expects($this->at(100)) + ->method('exists') + ->willReturn(false); + + $input = 'example'; + $expected = '#^-1:/user_uploads/example_([0-9]{10}).yaml$#'; + + $returnValue = $mockFormPersistenceManager->_call('getUniquePersistenceIdentifier', $input, '-1:/user_uploads/'); + $this->assertEquals(1, preg_match($expected, $returnValue)); + } + + /** + * @test + */ + public function getUniqueIdentifierThrowsExceptionIfIdentifierExists() + { + $this->expectException(NoUniqueIdentifierException::class); + $this->expectExceptionCode(1477688567); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'checkForDuplicateIdentifier' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('checkForDuplicateIdentifier') + ->willReturn(true); + + $input = 'example'; + $mockFormPersistenceManager->_call('getUniqueIdentifier', $input); + } + + /** + * @test + */ + public function getUniqueIdentifierAppendTimestampIfIdentifierExists() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'checkForDuplicateIdentifier' + ], [], '', false); + + for ($attempts = 0; $attempts <= 99; $attempts++) { + $mockFormPersistenceManager + ->expects($this->at($attempts)) + ->method('checkForDuplicateIdentifier') + ->willReturn(true); + } + + $mockFormPersistenceManager + ->expects($this->at(100)) + ->method('checkForDuplicateIdentifier') + ->willReturn(false); + + $input = 'example'; + $expected = '#^example_([0-9]{10})$#'; + + $returnValue = $mockFormPersistenceManager->_call('getUniqueIdentifier', $input); + $this->assertEquals(1, preg_match($expected, $returnValue)); + } + + /** + * @test + */ + public function checkForDuplicateIdentifierReturnsTrueIfIdentifierIsUsed() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'listForms' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->at($attempts)) + ->method('listForms') + ->willReturn([ + 0 => [ + 'identifier' => 'example', + ], + ]); + + $input = 'example'; + $this->assertTrue($mockFormPersistenceManager->_call('checkForDuplicateIdentifier', $input)); + } + + /** + * @test + */ + public function checkForDuplicateIdentifierReturnsFalseIfIdentifierIsUsed() + { + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'listForms' + ], [], '', false); + + $mockFormPersistenceManager + ->expects($this->at($attempts)) + ->method('listForms') + ->willReturn([ + 0 => [ + 'identifier' => 'example', + ], + ]); + + $input = 'other-example'; + $this->assertFalse($mockFormPersistenceManager->_call('checkForDuplicateIdentifier', $input)); + } + + /** + * @test + */ + public function getFileByIdentifierThrowsExceptionIfReadFromStorageIsNotAllowed() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1471630578); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid', + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage + ->expects($this->any()) + ->method('checkFileActionPermission') + ->willReturn(false); + + $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage); + $mockStorage + ->expects($this->any()) + ->method('getFile') + ->willReturn($file); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/example.yaml'; + $mockFormPersistenceManager->_call('getFileByIdentifier', $input); + } + + /** + * @test + */ + public function getOrCreateFileThrowsExceptionIfFolderNotExistsInStorage() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1471630579); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid', + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage + ->expects($this->any()) + ->method('hasFolder') + ->willReturn(false); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/example.yaml'; + $mockFormPersistenceManager->_call('getOrCreateFile', $input); + } + + /** + * @test + */ + public function getOrCreateFileThrowsExceptionIfWriteToStorageIsNotAllowed() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1471630580); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'getStorageByUid', + ], [], '', false); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage + ->expects($this->any()) + ->method('hasFolder') + ->willReturn(true); + + $mockStorage + ->expects($this->any()) + ->method('checkFileActionPermission') + ->willReturn(false); + + $file = new File(['identifier' => '', 'mime_type' => ''], $mockStorage); + $mockStorage + ->expects($this->any()) + ->method('getFile') + ->willReturn($file); + + $mockFormPersistenceManager + ->expects($this->any()) + ->method('getStorageByUid') + ->willReturn($mockStorage); + + $input = '-1:/user_uploads/example.yaml'; + $mockFormPersistenceManager->_call('getOrCreateFile', $input); + } + + /** + * @test + */ + public function getStorageByUidThrowsExceptionIfStorageNotExists() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1471630581); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy', + ], [], '', false); + + $mockStorageRepository = $this->getMockBuilder(StorageRepository::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorageRepository + ->expects($this->any()) + ->method('findByUid') + ->willReturn(null); + + $mockFormPersistenceManager->_set('storageRepository', $mockStorageRepository); + $mockFormPersistenceManager->_call('getStorageByUid', -1); + } + + /** + * @test + */ + public function getStorageByUidThrowsExceptionIfStorageIsNotBrowsable() + { + $this->expectException(PersistenceManagerException::class); + $this->expectExceptionCode(1471630581); + + $mockFormPersistenceManager = $this->getAccessibleMock(FormPersistenceManager::class, [ + 'dummy', + ], [], '', false); + + $mockStorageRepository = $this->getMockBuilder(StorageRepository::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $mockStorage + ->expects($this->any()) + ->method('isBrowsable') + ->willReturn(false); + + $mockStorageRepository + ->expects($this->any()) + ->method('findByUid') + ->willReturn($mockStorage); + + $mockFormPersistenceManager->_set('storageRepository', $mockStorageRepository); + $mockFormPersistenceManager->_call('getStorageByUid', -1); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/ProcessingRuleTest.php b/typo3/sysext/form/Tests/Unit/Mvc/ProcessingRuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..714658aaa8f995fcb9b2018d0a29dcd2c67c7480 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/ProcessingRuleTest.php @@ -0,0 +1,120 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Configuration; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Error\Result; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; +use TYPO3\CMS\Extbase\Validation\Validator\ConjunctionValidator; +use TYPO3\CMS\Form\Mvc\ProcessingRule; +use TYPO3\CMS\Form\Tests\Unit\Mvc\Validation\Fixtures\TestValidator; + +/** + * Test case + */ +class ProcessingRuleTest extends UnitTestCase +{ + + /** + * @var array A backup of registered singleton instances + */ + protected $singletonInstances = []; + + /** + * Set up + */ + public function setUp() + { + $this->singletonInstances = GeneralUtility::getSingletonInstances(); + } + + /** + * Tear down + */ + public function tearDown() + { + GeneralUtility::resetSingletonInstances($this->singletonInstances); + parent::tearDown(); + } + + /** + * @test + */ + public function addValidatorAddValidator() + { + $mockProcessingRule = $this->getAccessibleMock(ProcessingRule::class, [ + 'dummy' + ], [], '', false); + + $mockProcessingRule->_set('validator', new ConjunctionValidator([])); + $mockProcessingRule->addValidator(new TestValidator()); + $validators = $mockProcessingRule->_get('validator')->getValidators(); + $validators->rewind(); + $this->assertInstanceOf(AbstractValidator::class, $validators->current()); + } + + /** + * @test + */ + public function processNoPropertyMappingReturnsNotModifiedValue() + { + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + $resultProphecy = $this->prophesize(Result::class); + + $objectMangerProphecy + ->get(Result::class) + ->willReturn($resultProphecy->reveal()); + + $mockProcessingRule = $this->getAccessibleMock(ProcessingRule::class, [ + 'dummy' + ], [], '', false); + + $mockProcessingRule->_set('dataType', null); + $mockProcessingRule->_set('processingMessages', $resultProphecy->reveal()); + $mockProcessingRule->_set('validator', new ConjunctionValidator([])); + + $input = 'someValue'; + $this->assertSame($input, $mockProcessingRule->_call('process', $input)); + } + + /** + * @test + */ + public function processNoPropertyMappingAndHasErrorsIfValidatorContainsErrors() + { + $objectMangerProphecy = $this->prophesize(ObjectManager::class); + GeneralUtility::setSingletonInstance(ObjectManager::class, $objectMangerProphecy->reveal()); + + $objectMangerProphecy + ->get(Result::class) + ->willReturn(new Result); + + $mockProcessingRule = $this->getAccessibleMock(ProcessingRule::class, [ + 'dummy' + ], [], '', true); + + $mockProcessingRule->_set('dataType', null); + $mockProcessingRule->_set('validator', new ConjunctionValidator([])); + $mockProcessingRule->addValidator(new TestValidator()); + + $input = 'addError'; + $mockProcessingRule->_call('process', $input); + + $this->assertTrue($mockProcessingRule->_get('processingMessages')->hasErrors()); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Validation/CountValidatorTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Validation/CountValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bcff4b5c87a8bb06068f8f77ce61caab8c78a9d1 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Validation/CountValidatorTest.php @@ -0,0 +1,120 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Validation\CountValidator; + +/** + * Test case + */ +class CountValidatorTest extends UnitTestCase +{ + + /** + * @test + */ + public function CountValidatorReturnsFalseIfInputItemsCountIsEqualToMaximum() + { + $options = ['minimum' => 1, 'maximum' => 2]; + $validator = $this->getMockBuilder(CountValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs([$options]) + ->getMock(); + + $input = [ + 'klaus', + 'steve' + ]; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function CountValidatorReturnsFalseIfInputItemsCountIsEqualToMinimum() + { + $options = ['minimum' => 2, 'maximum' => 3]; + $validator = $this->getMockBuilder(CountValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs([$options]) + ->getMock(); + + $input = [ + 'klaus', + 'steve' + ]; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function CountValidatorReturnsFalseIfInputItemsCountIsEqualToMinimumAndMaximum() + { + $options = ['minimum' => 2, 'maximum' => 2]; + $validator = $this->getMockBuilder(CountValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs([$options]) + ->getMock(); + + $input = [ + 'klaus', + 'steve' + ]; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function CountValidatorReturnsTrueIfInputCountHasMoreItemsAsMaximumValue() + { + $options = ['minimum' => 1, 'maximum' => 2]; + $validator = $this->getMockBuilder(CountValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs([$options]) + ->getMock(); + + $input = [ + 'klaus', + 'steve', + 'francine' + ]; + + $this->assertTrue($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function CountValidatorReturnsTrueIfInputCountHasLessItemsAsMinimumValue() + { + $options = ['minimum' => 2, 'maximum' => 3]; + $validator = $this->getMockBuilder(CountValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs([$options]) + ->getMock(); + + $input = [ + 'klaus', + ]; + + $this->assertTrue($validator->validate($input)->hasErrors()); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Validation/EmptyValidatorTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Validation/EmptyValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fce017f58ec26d8f4eace57e5227091b987a8e32 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Validation/EmptyValidatorTest.php @@ -0,0 +1,123 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Validation\EmptyValidator; + +/** + * Test case + */ +class EmptyValidatorTest extends UnitTestCase +{ + + /** + * @test + */ + public function EmptyValidatorReturnsFalseIfInputIsEmptyString() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = ''; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsFalseIfInputIsNull() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = null; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsFalseIfInputIsEmptyArray() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = []; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsFalseIfInputIsZero() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = 0; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsFalseIfInputIsZeroAsString() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = '0'; + + $this->assertFalse($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsTrueIfInputIsNonEmptyString() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = 'hellö'; + + $this->assertTrue($validator->validate($input)->hasErrors()); + } + + /** + * @test + */ + public function EmptyValidatorReturnsTrueIfInputIsNonEmptyArray() + { + $validator = $this->getMockBuilder(EmptyValidator::class) + ->setMethods(['translateErrorMessage']) + ->getMock(); + + $input = ['hellö']; + + $this->assertTrue($validator->validate($input)->hasErrors()); + } +} diff --git a/typo3/sysext/form/Classes/Domain/Filter/DigitFilter.php b/typo3/sysext/form/Tests/Unit/Mvc/Validation/Fixtures/TestValidator.php similarity index 54% rename from typo3/sysext/form/Classes/Domain/Filter/DigitFilter.php rename to typo3/sysext/form/Tests/Unit/Mvc/Validation/Fixtures/TestValidator.php index 95d49c510d9326a99514ad8c2a27eaaa36b3c905..1ddc62cea40fc88b2a47ea90a6d05a0a7d8f5dac 100644 --- a/typo3/sysext/form/Classes/Domain/Filter/DigitFilter.php +++ b/typo3/sysext/form/Tests/Unit/Mvc/Validation/Fixtures/TestValidator.php @@ -1,5 +1,5 @@ <?php -namespace TYPO3\CMS\Form\Domain\Filter; +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Validation\Fixtures; /* * This file is part of the TYPO3 CMS project. @@ -14,21 +14,23 @@ namespace TYPO3\CMS\Form\Domain\Filter; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator; + /** - * Digit filter + * Validator for unit tetst + * + * @api */ -class DigitFilter extends AbstractFilter implements FilterInterface +class TestValidator extends AbstractValidator { /** - * Return filtered value - * Remove all but digits - * - * @param string $value - * @return string + * @param mixed $value + * @return void */ - public function filter($value) + public function isValid($value) { - $pattern = '/[^0-9]/'; - return preg_replace($pattern, '', (string)$value); + if ($value === 'addError') { + $this->addError('Error', 1480201569); + } } } diff --git a/typo3/sysext/form/Tests/Unit/Mvc/Validation/MimeTypeValidatorTest.php b/typo3/sysext/form/Tests/Unit/Mvc/Validation/MimeTypeValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ed234322b4c02f19ee68f6c587f3ac1f712c07d4 --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Mvc/Validation/MimeTypeValidatorTest.php @@ -0,0 +1,109 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Mvc\Validation; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\ResourceStorage; +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Mvc\Validation\Exception\InvalidValidationOptionsException; +use TYPO3\CMS\Form\Mvc\Validation\MimeTypeValidator; + +/** + * Test case + */ +class MimeTypeValidatorTest extends UnitTestCase +{ + + /** + * @test + */ + public function MimeTypeValidatorThrowsExceptionIfAllowedMimeTypesOptionIsString() + { + $this->expectException(InvalidValidationOptionsException::class); + $this->expectExceptionCode(1471713296); + + $options = ['allowedMimeTypes' => '']; + $validator = $this->getMockBuilder(MimeTypeValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs(['options' => $options]) + ->getMock(); + + $validator->validate(true); + } + + /** + * @test + */ + public function MimeTypeValidatorThrowsExceptionIfAllowedMimeTypesOptionIsEmptyArray() + { + $this->expectException(InvalidValidationOptionsException::class); + $this->expectExceptionCode(1471713296); + + $options = ['allowedMimeTypes' => []]; + $validator = $this->getMockBuilder(MimeTypeValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs(['options' => $options]) + ->getMock(); + + $validator->validate(true); + } + + /** + * @test + */ + public function MimeTypeValidatorReturnsTrueIfFileResourceIsNotAllowedMimeType() + { + $options = ['allowedMimeTypes' => ['image/jpeg']]; + $validator = $this->getMockBuilder(MimeTypeValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs(['options' => $options]) + ->getMock(); + + $mockedStorage = $this->getMockBuilder(ResourceStorage::class) + ->disableOriginalConstructor() + ->getMock(); + + $file = new File(['identifier' => '/foo', 'mime_type' => 'image/png'], $mockedStorage); + $this->assertTrue($validator->validate($file)->hasErrors()); + } + + /** + * @test + */ + public function MimeTypeValidatorReturnsFalseIfInputIsEmptyString() + { + $options = ['allowedMimeTypes' => ['fake']]; + $validator = $this->getMockBuilder(MimeTypeValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs(['options' => $options]) + ->getMock(); + + $this->assertFalse($validator->validate('')->hasErrors()); + } + + /** + * @test + */ + public function MimeTypeValidatorReturnsTrueIfInputIsNoFileResource() + { + $options = ['allowedMimeTypes' => ['fake']]; + $validator = $this->getMockBuilder(MimeTypeValidator::class) + ->setMethods(['translateErrorMessage']) + ->setConstructorArgs(['options' => $options]) + ->getMock(); + + $this->assertTrue($validator->validate('string')->hasErrors()); + } +} diff --git a/typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php b/typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php deleted file mode 100644 index 510986f83dec40ec2576b51f5660137119ea9b08..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/PostProcess/MailPostProcessorTest.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class MailPostProcessorTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * @var \TYPO3\CMS\Form\PostProcess\MailPostProcessor - */ - protected $mailPostProcessor; - - /** - * Set up - * - * @return void - */ - protected function setUp() - { - parent::setUp(); - $this->mailPostProcessor = $this->getAccessibleMock( - \TYPO3\CMS\Form\PostProcess\MailPostProcessor::class, - ['__none'], - [], - '', - false - ); - } - - /** - * Data provider for filterValidEmailsReturnsOnlyValidAddresses - * - * @return array input string, expected return array - * @TODO: Add a umlaut domain test case - */ - public function filterValidEmailsProvider() - { - return [ - 'empty string' => [ - '', - [], - ], - 'string not representing an email' => [ - 'notAnAddress', - [], - ], - 'simple single valid address' => [ - 'someone@example.com', - [ - 'someone@example.com', - ], - ], - 'multiple valid simple addresses' => [ - 'someone@example.com, foo@bar.com', - [ - 'someone@example.com', - 'foo@bar.com', - ], - ], - 'multiple addresses with personal part' => [ - 'Foo <foo@example.com>, <bar@example.com>, "Foo, bar" <foo.bar@example.com>', - [ - 'bar@example.com', - 'foo@example.com' => 'Foo', - 'foo.bar@example.com' => '"Foo, bar"', - ], - ], - 'list with invalid addresses is filtered' => [ - 'invalid, @invalid, someone@example.com', - [ - 'someone@example.com', - ], - ], - ]; - } - - /** - * @test - * @dataProvider filterValidEmailsProvider - */ - public function filterValidEmailsReturnsOnlyValidAddresses($input, $expected) - { - $actualResult = $this->mailPostProcessor->_call('filterValidEmails', $input); - $this->assertEquals($expected, $actualResult); - } -} diff --git a/typo3/sysext/form/Tests/Unit/PostProcess/PostProcessorTest.php b/typo3/sysext/form/Tests/Unit/PostProcess/PostProcessorTest.php deleted file mode 100644 index 7429417e5746c3cc71b5dcc32ef7206b70510dbd..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/PostProcess/PostProcessorTest.php +++ /dev/null @@ -1,149 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\PostProcess; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use Prophecy\Argument; -use TYPO3\CMS\Core\Tests\UnitTestCase; -use TYPO3\CMS\Extbase\Object\ObjectManager; -use TYPO3\CMS\Form\Domain\Model\Element; -use TYPO3\CMS\Form\Mvc\Controller\ControllerContext; -use TYPO3\CMS\Form\PostProcess\PostProcessor; -use TYPO3\CMS\Form\Tests\Unit\Fixtures\PostProcessorWithFormPrefixFixture; -use TYPO3\CMS\Form\Tests\Unit\Fixtures\PostProcessorWithoutFormPrefixFixture; -use TYPO3\CMS\Form\Tests\Unit\Fixtures\PostProcessorWithoutInterfaceFixture; - -/** - * Testcase for PostProcessor - */ -class PostProcessorTest extends UnitTestCase -{ - /** - * @var array A backup of registered singleton instances - */ - protected $singletonInstances = []; - - /** - * @var Element|\Prophecy\Prophecy\ObjectProphecy - */ - protected $elementProphecy; - - /** - * @var ObjectManager|\Prophecy\Prophecy\ObjectProphecy - */ - protected $objectManagerProphecy; - - /** - * @var ControllerContext|\Prophecy\Prophecy\ObjectProphecy - */ - protected $controllerContextProphecy; - - /** - * Sets up this test case. - */ - protected function setUp() - { - parent::setUp(); - $this->elementProphecy = $this->prophesize(Element::class); - $this->objectManagerProphecy = $this->prophesize(ObjectManager::class); - $this->controllerContextProphecy = $this->prophesize(ControllerContext::class); - } - - /** - * Tears down this test case. - */ - protected function tearDown() - { - parent::tearDown(); - unset($this->elementProphecy); - unset($this->objectManagerProphecy); - unset($this->controllerContextProphecy); - } - - /** - * @test - */ - public function processFindsClassSpecifiedByTypoScriptWithoutFormPrefix() - { - $typoScript = [ - 10 => $this->getUniqueId('postprocess'), - 20 => PostProcessorWithoutFormPrefixFixture::class - ]; - - $this->objectManagerProphecy - ->get(Argument::cetera()) - ->will(function ($arguments) { - return new $arguments[0]($arguments[1], $arguments[2]); - }); - - $subject = $this->createSubject($typoScript); - $this->assertEquals('processedWithoutPrefix', $subject->process()); - } - - /** - * @test - */ - public function processFindsClassSpecifiedByTypoScriptWithFormPrefix() - { - $typoScript = [ - 10 => $this->getUniqueId('postprocess'), - 20 => PostProcessorWithFormPrefixFixture::class - ]; - - $this->objectManagerProphecy - ->get(Argument::cetera()) - ->will(function ($arguments) { - return new $arguments[0]($arguments[1], $arguments[2]); - }); - - $subject = $this->createSubject($typoScript); - $this->assertEquals('processedWithPrefix', $subject->process()); - } - - /** - * @test - */ - public function processReturnsEmptyStringIfSpecifiedPostProcessorDoesNotImplementTheInterface() - { - $typoScript = [ - 10 => $this->getUniqueId('postprocess'), - 20 => PostProcessorWithoutInterfaceFixture::class - ]; - - $this->objectManagerProphecy - ->get(Argument::cetera()) - ->will(function ($arguments) { - return new $arguments[0]($arguments[1], $arguments[2]); - }); - - $subject = $this->createSubject($typoScript); - $this->assertEquals('', $subject->process()); - } - - /** - * @param array $typoScript - * @return PostProcessor|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface - */ - protected function createSubject(array $typoScript) - { - $subject = $this->getAccessibleMock( - PostProcessor::class, - ['__none'], - [$this->elementProphecy->reveal(), $typoScript] - ); - $subject->_set('controllerContext', $this->controllerContextProphecy->reveal()); - $subject->_set('objectManager', $this->objectManagerProphecy->reveal()); - return $subject; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Utility/ArrayUtilityTest.php b/typo3/sysext/form/Tests/Unit/Utility/ArrayUtilityTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9fbdc4fa13566d8d3a85db93e29fe423c1c00e1b --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/Utility/ArrayUtilityTest.php @@ -0,0 +1,251 @@ +<?php +namespace TYPO3\CMS\Form\Tests\Unit\Utility; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException; +use TYPO3\CMS\Form\Utility\ArrayUtility; + +/** + * Test case + */ +class ArrayUtilityTest extends UnitTestCase +{ + + /** + * @test + */ + public function assertAllArrayKeysAreValidThrowsExceptionOnNotAllowedArrayKeys() + { + $this->expectException(TypeDefinitionNotValidException::class); + $this->expectExceptionCode(1325697085); + + $arrayToTest = [ + 'roger' => '', + 'francine' => '', + 'stan' => '', + ]; + + $allowedArrayKeys = [ + 'roger', + 'francine', + ]; + + ArrayUtility::assertAllArrayKeysAreValid($arrayToTest, $allowedArrayKeys); + } + + /** + * @test + */ + public function assertAllArrayKeysAreValidReturnsNullOnAllowedArrayKeys() + { + $arrayToTest = [ + 'roger' => '', + 'francine' => '', + 'stan' => '', + ]; + + $allowedArrayKeys = [ + 'roger', + 'francine', + 'stan', + ]; + + $this->assertNull(ArrayUtility::assertAllArrayKeysAreValid($arrayToTest, $allowedArrayKeys)); + } + + /** + * @test + */ + public function sortNumericArrayKeysRecursiveExpectSorting() + { + $input = [ + 20 => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + 50 => [ + 20 => 'a', + 10 => 'b', + ], + ]; + + $expected = [ + 10 => 'a', + 20 => 'b', + 30 => 'c', + 40 => 'd', + 50 => [ + 10 => 'b', + 20 => 'a', + ], + ]; + + $this->assertSame($expected, ArrayUtility::sortNumericArrayKeysRecursive($input)); + } + + /** + * @test + */ + public function sortNumericArrayKeysRecursiveExpectNoSorting() + { + $input = [ + 'b' => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + ]; + + $expected = [ + 'b' => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + ]; + + $this->assertSame($expected, ArrayUtility::sortNumericArrayKeysRecursive($input)); + } + + /** + * @test + */ + public function reIndexNumericArrayKeysRecursiveExpectReindexing() + { + $input = [ + 20 => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + 50 => [ + 20 => 'a', + 10 => 'b', + ], + ]; + + $expected = [ + 0 => 'b', + 1 => 'a', + 2 => 'd', + 3 => 'c', + 4 => [ + 0 => 'a', + 1 => 'b', + ], + ]; + + $this->assertSame($expected, ArrayUtility::reIndexNumericArrayKeysRecursive($input)); + } + + /** + * @test + */ + public function reIndexNumericArrayKeysRecursiveExpectNoReindexing() + { + $input = [ + 'a' => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + 50 => [ + 20 => 'a', + 10 => 'b', + ], + ]; + + $expected = [ + 'a' => 'b', + 10 => 'a', + 40 => 'd', + 30 => 'c', + 50 => [ + 0 => 'a', + 1 => 'b', + ], + ]; + + $this->assertSame($expected, ArrayUtility::reIndexNumericArrayKeysRecursive($input)); + } + + /** + * @test + */ + public function removeNullValuesRecursiveExpectRemoval() + { + $input = [ + 'a' => 'a', + 'b' => [ + 'c' => null, + 'd' => 'd', + ], + ]; + + $expected = [ + 'a' => 'a', + 'b' => [ + 'd' => 'd', + ], + ]; + + $this->assertSame($expected, ArrayUtility::removeNullValuesRecursive($input)); + } + + /** + * @test + */ + public function stripTagsFromValuesRecursiveExpectRemoval() + { + $input = [ + 'a' => 'a', + 'b' => [ + 'c' => '<b>i am evil</b>', + 'd' => 'd', + ], + ]; + + $expected = [ + 'a' => 'a', + 'b' => [ + 'c' => 'i am evil', + 'd' => 'd', + ], + ]; + + $this->assertSame($expected, ArrayUtility::stripTagsFromValuesRecursive($input)); + } + + /** + * @test + */ + public function convertBooleanStringsToBooleanRecursiveExpectConverting() + { + $input = [ + 'a' => 'a', + 'b' => [ + 'c' => 'true', + 'd' => 'd', + ], + ]; + + $expected = [ + 'a' => 'a', + 'b' => [ + 'c' => true, + 'd' => 'd', + ], + ]; + + $this->assertSame($expected, ArrayUtility::convertBooleanStringsToBooleanRecursive($input)); + } +} diff --git a/typo3/sysext/form/Tests/Unit/Utility/TypoScriptToJsonConverterTest.php b/typo3/sysext/form/Tests/Unit/Utility/TypoScriptToJsonConverterTest.php deleted file mode 100644 index 3b641ba061162fd046a6708a24e0090a8e77b925..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Utility/TypoScriptToJsonConverterTest.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Utility; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Core\Tests\AccessibleObjectInterface; -use TYPO3\CMS\Core\Tests\UnitTestCase; -use TYPO3\CMS\Form\Domain\Model\Json\FormJsonElement; -use TYPO3\CMS\Form\Utility\TypoScriptToJsonConverter; - -/** - * Test case for \TYPO3\CMS\Form\Utility\TypoScriptToJsonConverter - */ -class TypoScriptToJsonConverterTest extends UnitTestCase -{ - /** - * Checks if calling protected method getChildElementsByIntegerKey with different data - * calls the addMethod in the mocked FormJsonElement for an expected method count. - * - * @dataProvider getChildElementsByIntegerKeyCallsAddElementDataProvider - * @param array $typoScript - * @param int $methodCount - * @test - */ - public function getChildElementsByIntegerKeyCallsAddElement(array $typoScript, $methodCount) - { - /** @var FormJsonElement|\PHPUnit_Framework_MockObject_MockObject $mockSubject */ - $parentElement = $this->getMockBuilder(FormJsonElement::class) - ->setMethods(['addElement']) - ->getMock(); - // check if method gets called exactly X times - $parentElement->expects($this->exactly($methodCount))->method('addElement'); - - /** @var TypoScriptToJsonConverter|\PHPUnit_Framework_MockObject_MockObject|AccessibleObjectInterface $subjectAccessible */ - $accessibleSubject = $this->getAccessibleMock(TypoScriptToJsonConverter::class, ['dummy']); - $accessibleSubject->_call('getChildElementsByIntegerKey', $parentElement, $typoScript); - } - - /** - * Data provider for test method getChildElementsByIntegerKeyCallsAddElement. - * - * @return array - */ - public function getChildElementsByIntegerKeyCallsAddElementDataProvider() - { - return [ - [ - 'typoscript' => [ - 'prefix' => 'tx_form', - 'confirmation' => '1', - 'postProcessor.' => [ - '1' => 'mail', - '1.' => [ - 'recipientEmail' => '', - 'senderEmail' => '', - ], - ], - '10' => 'FILEUPLOAD', - '10.' => [ - 'name' => 'foo', - 'type' => 'file', - 'label.' => [ - 'value' => 'Edit this label', - ], - ], - ], - 1 - ], - ]; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/AbstractValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/AbstractValidatorTest.php deleted file mode 100644 index b934c76de3e511f892c96a65c1185c574ad1652f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/AbstractValidatorTest.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\CMS\Form\Domain\Validator\AbstractValidator; -use TYPO3\CMS\Form\Utility\FormUtility; - -/** - * Test case - */ -abstract class AbstractValidatorTest extends \TYPO3\CMS\Core\Tests\UnitTestCase -{ - /** - * Must be filled with subject class name - * in specific test implementation. - * - * @var string - */ - protected $subjectClassName = null; - - /** - * @param array $options - * @return AbstractValidator|\PHPUnit_Framework_MockObject_MockObject - */ - protected function createSubject(array $options) - { - /** @var AbstractValidator $subject */ - $subject = $this->getMockBuilder($this->subjectClassName) - ->setMethods(['getLocalLanguageLabel', 'humanReadableDateFormat']) - ->setConstructorArgs(['options' => $options]) - ->getMock(); - - /** @var FormUtility $formUtilityMock */ - $formUtilityMock = $this->createMock(FormUtility::class); - $subject->setFormUtility($formUtilityMock); - - return $subject; - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/AlphabeticValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/AlphabeticValidatorTest.php deleted file mode 100644 index 0fd578f3490e13e76d3b8b7bc5240a963433ee60..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/AlphabeticValidatorTest.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class AlphabeticValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\AlphabeticValidator::class; - - /** - * @return array - */ - public function validDataProviderWithoutWhitespace() - { - return [ - 'ascii without spaces' => ['thisismyinput'], - 'accents without spaces' => ['éóéà èò'], - 'umlauts without spaces' => ['üöä'], - 'empty string' => [''] - ]; - } - - /** - * @return array - */ - public function validDataProviderWithWhitespace() - { - return [ - 'ascii with spaces' => ['This is my input'], - 'accents with spaces' => ['Sigur Rós'], - 'umlauts with spaces' => ['Hürriyet Daily News'], - 'space' => [' '], - 'empty string' => [''] - ]; - } - - /** - * @return array - */ - public function invalidDataProviderWithoutWhitespace() - { - return [ - 'ascii with dash' => ['my-name'], - 'accents with underscore' => ['Sigur_Rós'], - 'umlauts with periods' => ['Hürriyet.Daily.News'], - 'space' => [' '], - ]; - } - - /** - * @return array - */ - public function invalidDataProviderWithWhitespace() - { - return [ - 'ascii with spaces and dashes' => ['This is my-name'], - 'accents with spaces and underscores' => ['Listen to Sigur_Rós_Band'], - 'umlauts with spaces and periods' => ['Go get the Hürriyet.Daily.News'] - ]; - } - - /** - * @param string $input - * @test - * @dataProvider validDataProviderWithoutWhitespace - */ - public function validateForValidInputWithoutAllowedWhitespaceHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider validDataProviderWithWhitespace - */ - public function validateForValidInputWithWhitespaceAllowedHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error'), 'allowWhiteSpace' => true]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider invalidDataProviderWithoutWhitespace - */ - public function validateForInvalidInputWithoutAllowedWhitespaceHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider invalidDataProviderWithWhitespace - */ - public function validateForInvalidInputWithWhitespaceAllowedHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error'), 'allowWhiteSpace' => true]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/AlphanumericValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/AlphanumericValidatorTest.php deleted file mode 100644 index 697c8b33187c55c75e8ea84a93d4f3aa2127fe91..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/AlphanumericValidatorTest.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class AlphanumericValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\AlphanumericValidator::class; - - /** - * @return array - */ - public function validDataProviderWithoutWhitespace() - { - return [ - 'ascii without spaces' => ['thisismyinput4711'], - 'accents without spaces' => ['éóéà èò4711'], - 'umlauts without spaces' => ['üöä4711'], - 'empty string' => [''] - ]; - } - - /** - * @return array - */ - public function validDataProviderWithWhitespace() - { - return [ - 'ascii with spaces' => ['This is my input 4711'], - 'accents with spaces' => ['Sigur Rós 4711'], - 'umlauts with spaces' => ['Hürriyet Daily News 4711'], - 'space' => [' '], - 'empty string' => [''] - ]; - } - - /** - * @return array - */ - public function invalidDataProviderWithoutWhitespace() - { - return [ - 'ascii with dash' => ['my-name-4711'], - 'accents with underscore' => ['Sigur_Rós_4711'], - 'umlauts with periods' => ['Hürriyet.Daily.News.4711'], - 'space' => [' '], - ]; - } - - /** - * @return array - */ - public function invalidDataProviderWithWhitespace() - { - return [ - 'ascii with spaces and dashes' => ['This is my-name 4711'], - 'accents with spaces and underscores' => ['Listen to Sigur_Rós_Band 4711'], - 'umlauts with spaces and periods' => ['Go get the Hürriyet.Daily.News 4711'] - ]; - } - - /** - * @param string $input - * @test - * @dataProvider validDataProviderWithoutWhitespace - */ - public function validateForValidInputWithoutAllowedWhitespaceHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider validDataProviderWithWhitespace - */ - public function validateForValidInputWithAllowedWhitespaceHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error'), 'allowWhiteSpace' => true]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider invalidDataProviderWithoutWhitespace - */ - public function validateForInvalidInputWithoutAllowedWhitespaceHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @param string $input - * @test - * @dataProvider invalidDataProviderWithWhitespace - */ - public function validateForInvalidInputWithAllowedWhitespaceHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error'), 'allowWhiteSpace' => true]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/BetweenValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/BetweenValidatorTest.php deleted file mode 100644 index a641096f5854b72212c4f6b86d61920a8a7c2845..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/BetweenValidatorTest.php +++ /dev/null @@ -1,146 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class BetweenValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\BetweenValidator::class; - - /** - * @return array - */ - public function validNonInclusiveDataProvider() - { - return [ - '3 < 5 < 7' => [[3, 5, 7]], - '0 < 10 < 20' => [[0, 10, 20]], - '-10 < 0 < 10' => [[-10, 0, 10]], - '-20 < -10 < 0' => [[-20, -10, 0]], - '1 < 2 < 3' => [[1, 2, 3]], - '1 < 1.01 < 1.1' => [[1, 1.01, 1.1]], - ]; - } - - /** - * @return array - */ - public function invalidNonInclusiveDataProvider() - { - return [ - '1 < 1 < 2' => [[1, 1, 2]], - '1 < 2 < 2' => [[1, 2, 2]], - '1.1 < 1.1 < 1.2' => [[1.1, 1.1, 1.2]], - '1.1 < 1.2 < 1.2' => [[1.1, 1.2, 1.2]], - '-10.1234 < -10.12340 < 10' => [[-10.1234, -10.12340, 10]], - '100 < 0 < -100' => [[100, 0, -100]] - ]; - } - - /** - * @return array - */ - public function validInclusiveDataProvider() - { - return [ - '1 ≤ 1 ≤ 1' => [[1, 1, 1]], - '-10.1234 ≤ -10.12340 ≤ 10' => [[-10.1234, -10.12340, 10]], - '-10.1234 ≤ -10 ≤ 10' => [[-10.1234, -10.12340, 10]], - ]; - } - - public function invalidInclusiveDataProvider() - { - return [ - '-10.1234 ≤ -10.12345 ≤ 10' => [[-10.1234, -10.12345, 10]], - '100 ≤ 0 ≤ -100' => [[100, 0, -100]] - ]; - } - - /** - * @param array $input - * @test - * @dataProvider validNonInclusiveDataProvider - */ - public function validateWithValidInputAndWithoutInclusiveHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[2]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @param array $input - * @test - * @dataProvider validInclusiveDataProvider - */ - public function validateWithValidInputAndWithInclusiveHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[2]; - $options['inclusive'] = true; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @param array $input - * @test - * @dataProvider invalidNonInclusiveDataProvider - */ - public function validateWithInvalidInputAndWithoutInclusiveHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[2]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @param array $input - * @test - * @dataProvider invalidInclusiveDataProvider - */ - public function validateWithInvalidInputAndWithInclusiveHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[2]; - $options['inclusive'] = true; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/DateValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/DateValidatorTest.php deleted file mode 100644 index 38df7a6cd472f2e7e8e90e1ca041c07789df8448..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/DateValidatorTest.php +++ /dev/null @@ -1,86 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class DateValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\DateValidator::class; - - /** - * @return array - */ - public function validDateProvider() - { - return [ - '28-03-2012' => [['%e-%m-%Y', '28-03-2012']], - '8-03-2012' => [['%e-%m-%Y', '8-03-2012']], - '29-02-2012' => [['%d-%m-%Y', '29-02-2012']] - ]; - } - - /** - * @return array - */ - public function invalidDateProvider() - { - return [ - '32-03-2012' => [['%d-%m-%Y', '32-03-2012']], - '31-13-2012' => [['%d-%m-%Y', '31-13-2012']], - '29-02-2011' => [['%d-%m-%Y', '29-02-2011']] - ]; - } - - /** - * @test - * @dataProvider validDateProvider - * @param array $input - */ - public function validateForValidInputHasEmptyErrorResult(array $input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['format'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidDateProvider - * @param array $input - */ - public function validateForInvalidInputHasNotEmptyErrorResult(array $input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['format'] = $input[0]; - $subject = $this->createSubject($options); - - $subject->expects($this->once()) - ->method('humanReadableDateFormat') - ->willReturnArgument(0); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/DigitValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/DigitValidatorTest.php deleted file mode 100644 index b4973e2aa9cee5ff3509c6e044c5cdd097584f4b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/DigitValidatorTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class DigitValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\DigitValidator::class; - - /** - * @return array - */ - public function validDigitProvider() - { - return [ - 'stringified integer' => ['2012'], - 'stringified integer with leading zeros' => ['0002'], - ]; - } - - /** - * @return array - */ - public function invalidDigitProvider() - { - return [ - 'stringified float' => ['0.2012'], - 'stringified scientific' => ['1.9E+11'] - ]; - } - - /** - * @test - * @dataProvider validDigitProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidDigitProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/EmailValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/EmailValidatorTest.php deleted file mode 100644 index 9eea1514afdda1b4e412706d923b86ec5df49e1b..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/EmailValidatorTest.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class EmailValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\EmailValidator::class; - - /** - * @return array - */ - public function validEmailProvider() - { - return [ - 'a@b.de' => ['a@b.de'], - 'somebody@mymac.local' => ['somebody@mymac.local'], - 'empty value' => [''], - 'unexpected value' => [[]], - ]; - } - - /** - * @return array - */ - public function invalidEmailProvider() - { - return [ - 'myemail@' => ['myemail@'], - 'myemail' => ['myemail'], - 'somebody@localhost' => ['somebody@localhost'], - ]; - } - - /** - * @test - * @dataProvider validEmailProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidEmailProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/EqualsValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/EqualsValidatorTest.php deleted file mode 100644 index 1baee2ebc077595b1606ae22321dec784652519a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/EqualsValidatorTest.php +++ /dev/null @@ -1,80 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class EqualsValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\EqualsValidator::class; - - /** - * @return array - */ - public function validPairProvider() - { - return [ - 'something === something' => [['something', 'something']], - '4 === 4' => [[4, 4]] - ]; - } - - /** - * @return array - */ - public function invalidPairProvider() - { - return [ - 'somethingElse !== something' => [['somethingElse', 'something']], - '4 !== 3' => [[4, 3]] - ]; - } - - /** - * @test - * @dataProvider validPairProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['field'] = uniqid('field'); - $subject = $this->createSubject($options); - $subject->setRawArgument([$options['field'] => $input[0]]); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidPairProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['field'] = uniqid('field'); - $subject = $this->createSubject($options); - $subject->setRawArgument([$options['field'] => $input[0]]); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/FileAllowedTypesValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/FileAllowedTypesValidatorTest.php deleted file mode 100644 index 776bfba43ff067cc591bf480422d3146ec03f45f..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/FileAllowedTypesValidatorTest.php +++ /dev/null @@ -1,114 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class FileAllowedTypesValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\FileAllowedTypesValidator::class; - - /** - * @return array - */ - public function validTypesProvider() - { - return [ - 'pdf in (pdf)' => [ - 'application/pdf', - [ - 'type' => 'application/pdf', - ], - ], - 'pdf in (pdf, json)' => [ - 'application/pdf, application/json', - [ - 'type' => 'application/pdf', - ], - ], - ]; - } - - /** - * @return array - */ - public function invalidTypesProvider() - { - return [ - 'xml in (pdf, json)' => [ - 'application/pdf, application/json', - [ - 'type' => 'application/xml', - ], - ], - 'xml in (pdf)' => [ - 'application/pdf', - [ - 'type' => 'application/xml', - ], - ], - 'empty mimetype' => [ - 'application/pdf, application/json', - [ - 'type' => '', - ], - ], - 'empty value' => [ - 'application/pdf, application/json', - '', - ], - ]; - } - - /** - * @test - * @param string $types - * @param array $value - * @dataProvider validTypesProvider - */ - public function validateForValidInputHasEmptyErrorResult($types, $value) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - 'types' => $types, - ]; - $subject = $this->createSubject($options); - - $this->assertEmpty($subject->validate($value)->getErrors()); - } - - /** - * @test - * @param string $types - * @param array $value - * @dataProvider invalidTypesProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($types, $value) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - 'types' => $types, - ]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty($subject->validate($value)->getErrors()); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/FileMaximumSizeValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/FileMaximumSizeValidatorTest.php deleted file mode 100644 index 5dff12f007436ca2e445a6dd8bc5949233435493..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/FileMaximumSizeValidatorTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class FileMaximumSizeValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\FileMaximumSizeValidator::class; - - protected function setUp() - { - $this->markTestSkipped('validate() instead of isValid() needs to be used'); - } - - public function validSizesProvider() - { - return [ - '11B for max. 12B' => [[12, 11]], - '12B for max. 12B' => [[12, 12]] - ]; - } - - public function invalidSizesProvider() - { - return [ - '12B for max. 11B' => [[11, 12]] - ]; - } - - /** - * @test - * @dataProvider validSizesProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['maximum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider inValidSizesProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['maximum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/FileMinimumSizeValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/FileMinimumSizeValidatorTest.php deleted file mode 100644 index 7b50869bcd554c89ad4fcf91bd0c8eaf639e936c..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/FileMinimumSizeValidatorTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class FileMinimumSizeValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\FileMinimumSizeValidator::class; - - protected function setUp() - { - $this->markTestSkipped('validate() instead of isValid() needs to be used'); - } - - public function validSizesProvider() - { - return [ - '12B for min. 11B' => [[11, 12]], - '12B for min. 12B' => [[12, 12]] - ]; - } - - public function invalidSizesProvider() - { - return [ - '11B for min. 12B' => [[12, 11]] - ]; - } - - /** - * @test - * @dataProvider validSizesProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidSizesProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/FloatValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/FloatValidatorTest.php deleted file mode 100644 index 5cfc288cb42e89ed7adb9502875d52322b63ca35..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/FloatValidatorTest.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class FloatValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\FloatValidator::class; - - /** - * @return array - */ - public function validFloatProvider() - { - return [ - '12.1 for en_US locale' => [ - '12.1', - 'en_US.utf8', - ], - '12,1 for de_DE locale' => [ - '12,1', - 'de_DE.utf8', - ], - ]; - } - - /** - * @test - * @dataProvider validFloatProvider - */ - public function validateForValidInputHasEmptyErrorResult($inputValue, $locale) - { - try { - $this->setLocale(LC_NUMERIC, $locale); - } catch (\PHPUnit_Framework_Exception $e) { - $this->markTestSkipped('Locale ' . $locale . ' is not available.'); - } - - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($inputValue)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/GreaterThanValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/GreaterThanValidatorTest.php deleted file mode 100644 index a30d1168d87479e6644bc16e5fe412be15c10a87..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/GreaterThanValidatorTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class GreaterThanValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\GreaterThanValidator::class; - - /** - * @return array - */ - public function validNumberProvider() - { - return [ - '13 > 12' => [[12, 13]], - ]; - } - - /** - * @return array - */ - public function invalidNumberProvider() - { - return [ - '(int)12.1 > 12' => [[12, 12.1]], - '(int)12 > 12' => [[12, 12]], - '(int)11.99 > 12' => [[12, 11.99]] - ]; - } - - /** - * @test - * @dataProvider validNumberProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidNumberProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/InArrayValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/InArrayValidatorTest.php deleted file mode 100644 index 40a8be95ad19e12c97b285112657d73d8dd2b775..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/InArrayValidatorTest.php +++ /dev/null @@ -1,800 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ -use TYPO3\CMS\Form\Domain\Validator\InArrayValidator; - -/** - * Test case - */ -class InArrayValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = InArrayValidator::class; - - /** - * used for tests with valid input - * will result in no errors returned - * - * @return array - */ - public function validArrayForStringConfigurationProvider() - { - return [ - '12 in (12, 13, 14)' => [ - '12', - '12,13,14', - ], - '1 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - '1', - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - 'Pizza in (Pizza, Lasange, Strogonvo)' => [ - 'Pizza', - 'Pizza,Lasange,Strogonvo', - ], - 'Rißtissen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'Rißtissen', - 'Rißtissen,Überligen,Karlsruhe', - ], - - '[12 and 14] in (12, 13, 14)' => [ - ['12', '14'], - '12,13,14', - ], - '[1 and ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - ['1', 'ssd'], - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - '[Pizza and Strogonvo] in (Pizza, Lasange, Strogonvo)' => [ - ['Pizza', 'Strogonvo'], - 'Pizza,Lasange,Strogonvo', - ], - '[Rißtissen and Karlsruhe] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['Rißtissen', 'Karlsruhe'], - 'Rißtissen,Überligen,Karlsruhe', - ], - ]; - } - - /** - * used for tests with valid input - * will result in no errors returned - * - * @return array - */ - public function validArrayForArrayConfigurationProvider() - { - return [ - '12 in [12, 13, 14]' => [ - '12', - ['12', '13', '14'], - ], - '1 in [5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa]' => [ - '1', - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - 'Pizza in [Pizza, Lasange, Strogonvo]' => [ - ['Pizza', 'Strogonvo'], - ['Pizza', 'Lasange', 'Strogonvo'], - ], - 'Rißtissen in [Rißtissen, Überligen, Karlsruhe]' => [ - ['Rißtissen', 'Karlsruhe'], - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - - '[12 and 14] in [12, 13, 14]' => [ - ['12', '14'], - ['12', '13', '14'], - ], - '[1 and ssd] in [5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa]' => [ - ['1', 'ssd'], - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - '[Pizza and Strogonvo] in [Pizza, Lasange, Strogonvo]' => [ - 'Pizza', - ['Pizza', 'Lasange', 'Strogonvo'], - ], - '[Rißtissen and Karlsruhe] in [Rißtissen, Überligen, Karlsruhe]' => [ - 'Rißtissen', - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - ]; - } - - /** - * used for test with invalid input - * will result in errors returned - * - * @return array - */ - public function invalidArrayForStringConfigurationProvider() - { - return [ - '12 in (11, 13, 14)' => [ - '12', - '11,13,14', - ], - '1 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 333434, 1234, ssd, ysdfsa)' => [ - '1', - '5,3234,oOIUoi8,3434,343,34,3,333434,1234,ssd,ysdfsa', - ], - 'pizza in (Pizza, Lasange, Strogonvo)' => [ - 'pizza', - 'Pizza,Lasange,Strogonvo', - ], - 'Eimeldingen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'Eimeldingen', - 'Rißtissen,Überligen,Karlsruhe', - ], - 'überligen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'überligen', - 'Rißtissen,Überligen,Karlsruhe', - ], - - '[12 and 14] in (11, 13, 14)' => [ - ['12', '14'], - '11,13,14', - ], - '[1 and ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 333434, 1234, ssd, ysdfsa)' => [ - ['1', 'ssd'], - '5,3234,oOIUoi8,3434,343,34,3,333434,1234,ssd,ysdfsa', - ], - '[pizza and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizza', 'Lasange'], - 'Pizza,Lasange,Strogonvo', - ], - '[Eimeldingen and Überligen] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['Eimeldingen', 'Überligen'], - 'Rißtissen,Überligen,Karlsruhe', - ], - '[Eimeldingen and überligen] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['Eimeldingen', 'überligen'], - 'Rißtissen,Überligen,Karlsruhe', - ], - ]; - } - - /** - * used for test with invalid input - * will result in errors returned - * - * @return array - */ - public function invalidArrayForArrayConfigurationProvider() - { - return [ - '12 in (11, 13, 14)' => [ - '12', - ['11', '13', '14'], - ], - '1 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 333434, 1234, ssd, ysdfsa)' => [ - '1', - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '333434', '1234', 'ssd', 'ysdfsa'], - ], - 'pizza in (Pizza, Lasange, Strogonvo)' => [ - 'pizza', - ['Pizza', 'Lasange', 'Strogonvo'], - ], - 'Eimeldingen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'Eimeldingen', - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - 'überligen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'überligen', - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - - '[12 and 14] in (11, 13, 14)' => [ - ['12', '14'], - ['11', '13', '14'], - ], - '[1 and ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 333434, 1234, ssd, ysdfsa)' => [ - ['1', 'ssd'], - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '333434', '1234', 'ssd', 'ysdfsa'], - ], - '[pizza and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizza', 'Lasange'], - ['Pizza', 'Lasange', 'Strogonvo'], - ], - '[Eimeldingen and Überligen] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['Eimeldingen', 'Überligen'], - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - '[Eimeldingen and überligen] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['Eimeldingen', 'überligen'], - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - ]; - } - - /** - * used for tests with valid input - * ignorecase is set to true - * results in no errors returned - * - * @return array - */ - public function validArrayForStringConfigurationIgnoreCaseProvider() - { - return [ - '12 in (12, 13, 14)' => [ - '12', - '12,13,14', - ], - '1 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - '1', - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - 'pizza in (Pizza, Lasange, Strogonvo)' => [ - 'pizza', - 'Pizza,Lasange,Strogonvo', - ], - 'Pizza in (pizza, lasange, strogonvo)' => [ - 'Pizza', - 'pizza,lasange,strogonvo', - ], - 'Rißtissen in (rißtissen, Überligen, Karlsruhe)' => [ - 'Rißtissen', - 'rißtissen,Überligen,Karlsruhe', - ], - 'überligen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'überligen', - 'Rißtissen,Überligen,Karlsruhe', - ], - - '[12 and 14] in (12, 13, 14)' => [ - ['12', '14'], - '12,13,14', - ], - '[1 and Ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - ['1', 'Ssd'], - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - '[pizza and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizza', 'Lasange'], - 'Pizza,Lasange,Strogonvo', - ], - '[Pizza and lasange] in (pizza, lasange, strogonvo)' => [ - ['Pizza', 'lasange'], - 'pizza,lasange,strogonvo', - ], - '[Rißtissen and Karlsruhe] in (rißtissen, Überligen, Karlsruhe)' => [ - ['Rißtissen', 'Karlsruhe'], - 'rißtissen,Überligen,Karlsruhe', - ], - '[überligen and Karlsruhe] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['überligen', 'Karlsruhe'], - 'Rißtissen,Überligen,Karlsruhe', - ], - ]; - } - - /** - * used for tests with valid input - * ignorecase is set to true - * results in no errors returned - * - * @return array - */ - public function validArrayForArrayConfigurationIgnoreCaseProvider() - { - return [ - '12 in [12, 13, 14]' => [ - '12', - ['12', '13', '14'], - ], - '1 in [5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa]' => [ - '1', - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - 'pizza in [Pizza, Lasange, Strogonvo]' => [ - 'pizza', - ['Pizza', 'Lasange', 'Strogonvo'], - ], - 'Pizza in [pizza, lasange, strogonvo]' => [ - 'Pizza', - ['pizza', 'lasange', 'strogonvo'], - ], - 'Rißtissen in (rißtissen, Überligen, Karlsruhe)' => [ - 'Rißtissen', - ['rißtissen', 'Überligen', 'Karlsruhe'], - ], - 'überligen in (Rißtissen, Überligen, Karlsruhe)' => [ - 'überligen', - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - - '[12 and 14] in (12, 13, 14)' => [ - ['12', '14'], - ['12', '13', '14'], - ], - '[1 and Ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - ['1', 'Ssd'], - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - '[pizza and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizza', 'Lasange'], - ['Pizza', 'Lasange', 'Strogonvo'], - ], - '[Pizza and lasange] in (pizza, lasange, strogonvo)' => [ - ['Pizza', 'lasange'], - ['pizza', 'lasange', 'strogonvo'], - ], - '[Rißtissen and Karlsruhe] in (rißtissen, Überligen, Karlsruhe)' => [ - ['Rißtissen', 'Karlsruhe'], - ['rißtissen', 'Überligen', 'Karlsruhe'], - ], - '[überligen and Karlsruhe] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['überligen', 'Karlsruhe'], - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - ]; - } - - /** - * used for tests with invalid input - * ignorecase is set to true - * results in errors returned - * - * @return array - */ - public function invalidArrayForStringConfigurationIgnoreCaseProvider() - { - return [ - 'zwölf in (12, 13, 14)' => [ - 'zwölf', - '12,13,14', - ], - '7 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - '7', - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - 'riss in (Rißtissen, Überligen, Karlsruhe)' => [ - 'riss', - 'Rißtissen,Überligen,Karlsruhe', - ], - 'pizzas in (Pizza, Lasange, Strogonvo)' => [ - 'pizzas', - 'Pizza,Lasange,Strogonvo', - ], - 'lusange in (Pizza, Lasange, Strogonvo)' => [ - 'lusange', - 'Pizza,Lasange,Strogonvo', - ], - - '[zwölf and 14] in (12, 13, 14)' => [ - ['zwölf', '14'], - '12,13,14', - ], - '[7 and Ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - ['7', 'Ssd'], - '5,3234,oOIUoi8,3434,343,34,3,1,333434,1234,ssd,ysdfsa', - ], - '[riss and Karlsruhe] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['riss', 'Karlsruhe'], - 'Rißtissen,Überligen,Karlsruhe', - ], - '[pizzas and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizzas', 'Lasange'], - 'Pizza,Lasange,Strogonvo', - ], - '[lusange and Strogonvo] in (Pizza, Lasange, Strogonvo)' => [ - ['lusange', 'Strogonvo'], - 'Pizza,Lasange,Strogonvo', - ], - ]; - } - - /** - * used for tests with invalid input - * ignorecase is set to true - * results in errors returned - * - * @return array - */ - public function invalidArrayForArrayConfigurationIgnoreCaseProvider() - { - return [ - 'zwölf in (12, 13, 14)' => [ - 'zwölf', - ['12', '13', '14'], - ], - '7 in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - '7', - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - 'riss in (Rißtissen, Überligen, Karlsruhe)' => [ - 'riss', - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - 'pizzas in (Pizza, Lasange, Strogonvo)' => [ - 'pizzas', - ['Pizza', 'Lasange', 'Strogonvo'], - ], - 'lusange in (Pizza, Lasange, Strogonvo)' => [ - 'lusange', - ['Pizza', 'Lasange', 'Strogonvo'], - ], - - '[zwölf and 14] in (12, 13, 14)' => [ - ['zwölf', '14'], - ['12', '13', '14'], - ], - '[7 and Ssd] in (5, 3234, oOIUoi8, 3434, 343, 34, 3, 1, 333434, 1234, ssd, ysdfsa)' => [ - ['7', 'Ssd'], - ['5', '3234', 'oOIUoi8', '3434', '343', '34', '3', '1', '333434', '1234', 'ssd', 'ysdfsa'], - ], - '[riss and Karlsruhe] in (Rißtissen, Überligen, Karlsruhe)' => [ - ['riss', 'Karlsruhe'], - ['Rißtissen', 'Überligen', 'Karlsruhe'], - ], - '[pizzas and Lasange] in (Pizza, Lasange, Strogonvo)' => [ - ['pizzas', 'Lasange'], - ['Pizza', 'Lasange', 'Strogonvo'], - ], - '[lusange and Strogonvo] in (Pizza, Lasange, Strogonvo)' => [ - ['lusange', 'Strogonvo'], - ['Pizza', 'Lasange', 'Strogonvo'], - ], - ]; - } - - /** - * @test - * @dataProvider validArrayForStringConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnStringConfigurationReturnsNoErrors($value, $allowedOptionsString) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - - $options['array'] = $allowedOptionsString; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForArrayConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnArrayConfigurationReturnsNoErrors($value, $allowedOptionsString) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForStringConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnStringConfigurationReturnsErrors($value, $allowedOptionsString) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForArrayConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnArrayConfigurationReturnsErrors($value, $allowedOptionsString) - { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForStringConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnStringConfigurationWithStrictComparisonReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForArrayConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnArrayConfigurationWithStrictComparisonReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForStringConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnStringConfigurationWithStrictComparisonReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForArrayConfigurationProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnArrayConfigurationWithStrictComparisonReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForStringConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnStringConfigurationWithIgnoreCaseReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['ignorecase'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForArrayConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnArrayConfigurationWithIgnoreCaseReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['ignorecase'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForStringConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnStringConfigurationWithIgnoreCaseReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['ignorecase'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForArrayConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnArrayConfigurationWithIgnoreCaseReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['ignorecase'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForStringConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnStringConfigurationWithIgnoreCaseAndStrictReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['ignorecase'] = true; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider validArrayForArrayConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForValidInputOnArrayConfigurationWithIgnoreCaseAndStrictReturnsNoErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['ignorecase'] = true; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertFalse($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForStringConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnStringConfigurationWithIgnoreCaseAndStrictReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array'] = $allowedOptionsString; - $options['ignorecase'] = true; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } - - /** - * @test - * @dataProvider invalidArrayForArrayConfigurationIgnoreCaseProvider - * - * @param string $value - * @param string $allowedOptionsString - */ - public function validateForInvalidInputOnArrayConfigurationWithIgnoreCaseAndStrictReturnsErrors( - $value, - $allowedOptionsString - ) { - $options = [ - 'element' => uniqid('test'), - 'errorMessage' => uniqid('error'), - ]; - $options['array.'] = $allowedOptionsString; - $options['ignorecase'] = true; - $options['strict'] = true; - $subject = $this->createSubject($options); - - $this->assertTrue($subject->validate($value)->hasErrors()); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/IntegerValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/IntegerValidatorTest.php deleted file mode 100644 index db8e2f167429930279580523b94ca54af9363e69..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/IntegerValidatorTest.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class IntegerValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\IntegerValidator::class; - - public function validateForValidInputHasEmptyErrorResultDataProvider() - { - return [ - '12 for de locale' => [ - 12, - 'de_DE.utf8' - ], - ]; - } - - /** - * @test - * @dataProvider validateForValidInputHasEmptyErrorResultDataProvider - */ - public function validateForValidInputHasEmptyErrorResult($value, $locale) - { - try { - $this->setLocale(LC_NUMERIC, $locale); - } catch (\PHPUnit_Framework_Exception $e) { - $this->markTestSkipped('Locale ' . $locale . ' is not available.'); - } - - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($value)->getErrors() - ); - } - - public function validateForInvalidInputHasNotEmptyErrorResultDataProvider() - { - return [ - '12.1 for en_US locale' => [ - 12.1, - 'en_US.utf8' - ], - '12,1 for de_DE locale' => [ - '12,1', - 'de_DE.utf8' - ], - ]; - } - - /** - * @test - * @dataProvider validateForInvalidInputHasNotEmptyErrorResultDataProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($value, $locale) - { - try { - $this->setLocale(LC_NUMERIC, $locale); - } catch (\PHPUnit_Framework_Exception $e) { - $this->markTestSkipped('Locale ' . $locale . ' is not available.'); - } - - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($value)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/IpValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/IpValidatorTest.php deleted file mode 100644 index 1c1f0bf398327d65eddc5ed9359e0fc807d8d322..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/IpValidatorTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class IpValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\IpValidator::class; - - /** - * @return array - */ - public function validIpv4Provider() - { - return [ - '127.0.0.1' => ['127.0.0.1'], - '10.0.0.4' => ['10.0.0.4'], - '192.168.0.4' => ['192.168.0.4'], - '0.0.0.0' => ['0.0.0.0'] - ]; - } - - /** - * @return array - */ - public function invalidIpv4Provider() - { - return [ - '127.0.0.256' => ['127.0.0.256'], - '256.0.0.2' => ['256.0.0.2'] - ]; - } - - /** - * @test - * @dataProvider validIpv4Provider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidIpv4Provider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/LengthValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/LengthValidatorTest.php deleted file mode 100644 index d78086ab6026a8b892fe4453f085f40906fe6d12..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/LengthValidatorTest.php +++ /dev/null @@ -1,127 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use Prophecy\Argument; -use TYPO3\CMS\Core\Charset\CharsetConverter; -use TYPO3\CMS\Form\Domain\Validator\LengthValidator; - -/** - * Test case - */ -class LengthValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\LengthValidator::class; - - /** - * @var \Prophecy\Prophecy\ObjectProphecy - */ - protected $charsetConverterProphecy; - - /** - * Set up - */ - protected function setUp() - { - parent::setUp(); - $this->charsetConverterProphecy = $this->prophesize(CharsetConverter::class); - $this->charsetConverterProphecy - ->strlen(Argument::cetera()) - ->will(function ($arguments) { - return mb_strlen($arguments[1], $arguments[0]); - }); - } - - protected function tearDown() - { - parent::tearDown(); - unset($this->charsetConverterProphecy); - } - - /** - * @return array - */ - public function validLengthProvider() - { - return [ - '4 ≤ length(myString) ≤ 8' => [ - [4, 8, 'mäString'] - ], - '8 ≤ length(myString) ≤ 8' => [ - [8, 8, 'möString'] - ], - '4 ≤ length(myString)' => [ - [4, null, 'myString'] - ], - '4 ≤ length(asdf) ≤ 4' => [ - [4, 4, 'asdf'] - ], - ]; - } - - /** - * @test - * @dataProvider validLengthProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[1]; - /** @var LengthValidator $subject */ - $subject = $this->createSubject($options); - $subject->injectCharsetConverter($this->charsetConverterProphecy->reveal()); - - $this->assertEmpty( - $subject->validate($input[2])->getErrors() - ); - } - - /** - * @return array - */ - public function invalidLengthProvider() - { - return [ - '4 ≤ length(my) ≤ 12' => [ - [4, 12, 'my'] - ], - '4 ≤ length(my long string) ≤ 12' => [ - [4, 12, 'my long string'] - ], - ]; - } - - /** - * @test - * @dataProvider invalidLengthProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['minimum'] = $input[0]; - $options['maximum'] = $input[1]; - /** @var LengthValidator $subject */ - $subject = $this->createSubject($options); - $subject->injectCharsetConverter($this->charsetConverterProphecy->reveal()); - - $this->assertNotEmpty( - $subject->validate($input[2])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/LessThanValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/LessThanValidatorTest.php deleted file mode 100644 index e665e6058ced7c3c6da670c7798788965b805c8a..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/LessThanValidatorTest.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class LessThanValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\LessThanValidator::class; - - /** - * @return array - */ - public function validValueProvider() - { - return [ - '4 < 8' => [[8, 4]], - '7.9 < 8' => [[8, 7.9]], - ]; - } - - /** - * @return array - */ - public function invalidValueProvider() - { - return [ - '8 < 4' => [[4, 8]], - '8 < 8' => [[8, 8]], - '8.1 < 8' => [[8, 8.1]], - ]; - } - - /** - * @test - * @dataProvider validValueProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['maximum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidValueProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['maximum'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/RegExpValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/RegExpValidatorTest.php deleted file mode 100644 index 4e3708bfec4405703c015138fcc927f8487ed11e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/RegExpValidatorTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class RegExpValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\RegExpValidator::class; - - /** - * @return array - */ - public function validDataProvider() - { - return [ - '/^a/ matches a' => [['/^a/', 'a']], - ]; - } - - /** - * @return array - */ - public function invalidDataProvider() - { - return [ - '/[^\d]/ matches 8' => [['/[^\d]/', 8]], - ]; - } - - /** - * @test - * @dataProvider validDataProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['expression'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input[1])->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidDataProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $options['expression'] = $input[0]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input[1])->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/RequiredValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/RequiredValidatorTest.php deleted file mode 100644 index 13ab0612468947e765be2fd5f60c5e7013a1774e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/RequiredValidatorTest.php +++ /dev/null @@ -1,87 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class RequiredValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\RequiredValidator::class; - - /** - * @return array - */ - public function validDataProvider() - { - return [ - 'string "a"' => ['a'], - 'string "a b"' => ['a b'], - 'string "0"' => ['0'], - 'value 0' => [0], - 'array with string "a"' => [['a']], - 'array with string "a b"' => [['a b']], - 'array with string "0"' => [['0']], - 'array with value 0' => [[0]], - 'array with strings "a" and "b"' => [['a', 'b']], - 'array with empty string and "a"' => [['', 'a']], - 'array with empty string and "0"' => [['', '0']], - 'array with empty string and 0' => [['', 0]], - ]; - } - - /** - * @return array - */ - public function invalidDataProvider() - { - return [ - 'empty string' => [''], - 'array with empty string' => [['']], - 'array with empty strings' => [['', '']] - ]; - } - - /** - * @test - * @dataProvider validDataProvider - */ - public function validateForValidDataHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidDataProvider - */ - public function validateForInvalidDataHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/Validator/UriValidatorTest.php b/typo3/sysext/form/Tests/Unit/Validator/UriValidatorTest.php deleted file mode 100644 index 6367b8000427ed855b408db02f81fa60f585eb5e..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/Tests/Unit/Validator/UriValidatorTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -namespace TYPO3\CMS\Form\Tests\Unit\Validator; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -/** - * Test case - */ -class UriValidatorTest extends AbstractValidatorTest -{ - /** - * @var string - */ - protected $subjectClassName = \TYPO3\CMS\Form\Domain\Validator\UriValidator::class; - - /** - * @return array - */ - public function validDataProvider() - { - return [ - 'http://example.net' => ['http://example.net'], - 'https://example.net' => ['https://example.net'], - 'http://a:b@example.net' => ['http://a:b@example.net'], - ]; - } - - /** - * @return array - */ - public function invalidDataProvider() - { - return [ - 'index.php' => ['index.php'] - ]; - } - - /** - * @test - * @dataProvider validDataProvider - */ - public function validateForValidInputHasEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertEmpty( - $subject->validate($input)->getErrors() - ); - } - - /** - * @test - * @dataProvider invalidDataProvider - */ - public function validateForInvalidInputHasNotEmptyErrorResult($input) - { - $options = ['element' => uniqid('test'), 'errorMessage' => uniqid('error')]; - $subject = $this->createSubject($options); - - $this->assertNotEmpty( - $subject->validate($input)->getErrors() - ); - } -} diff --git a/typo3/sysext/form/Tests/Unit/ViewHelpers/Form/DatePickerViewHelperTest.php b/typo3/sysext/form/Tests/Unit/ViewHelpers/Form/DatePickerViewHelperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..edb28f043f6cdfaa4c2ddac04bed30dfd5ed52fb --- /dev/null +++ b/typo3/sysext/form/Tests/Unit/ViewHelpers/Form/DatePickerViewHelperTest.php @@ -0,0 +1,143 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Form\Tests\Unit\ViewHelpers\Form; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Form\ViewHelpers\Form\DatePickerViewHelper; + +/** + * Test case + */ +class DatePickerViewHelperTest extends UnitTestCase +{ + + /** + * @var \TYPO3\CMS\Form\ViewHelpers\Form\DatePickerViewHelper + */ + protected $subject = null; + + /** + * Set up + * + * @return void + */ + protected function setUp() + { + $this->subject = $this->getAccessibleMock(DatePickerViewHelper::class, [ + 'dummy' + ], [], '', false); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat01() + { + $input = 'd'; + $expected = 'dd'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat02() + { + $input = 'D'; + $expected = 'D'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat03() + { + $input = 'j'; + $expected = 'o'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat04() + { + $input = 'l'; + $expected = 'DD'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat05() + { + $input = 'F'; + $expected = 'MM'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat06() + { + $input = 'm'; + $expected = 'mm'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat07() + { + $input = 'M'; + $expected = 'M'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat08() + { + $input = 'n'; + $expected = 'm'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat09() + { + $input = 'Y'; + $expected = 'yy'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } + + /** + * @test + */ + public function convertDateFormatToDatePickerFormatReturnsTransformedFormat10() + { + $input = 'y'; + $expected = 'y'; + $this->assertSame($expected, $this->subject->_call('convertDateFormatToDatePickerFormat', $input)); + } +} diff --git a/typo3/sysext/form/composer.json b/typo3/sysext/form/composer.json index 33e88b4a256d6cf2ac484c83f540d9feffacc262..532111b80b2766e25b4e792142fcde7379554d38 100644 --- a/typo3/sysext/form/composer.json +++ b/typo3/sysext/form/composer.json @@ -1,31 +1,31 @@ { - "name": "typo3/cms-form", - "type": "typo3-cms-framework", - "description": "TYPO3 Core", - "homepage": "https://typo3.org", - "license": ["GPL-2.0+"], + "name": "typo3/cms-form", + "type": "typo3-cms-framework", + "description": "Extensible and flexible API and editor for building web forms", + "homepage": "https://typo3.org", + "license": ["GPL-2.0+"], - "require": { - "typo3/cms-core": "*" - }, - "replace": { - "form": "*" - }, - "extra": { - "typo3/cms": { - "Package": { - "partOfFactoryDefault": true - } - } - }, - "autoload": { - "psr-4": { - "TYPO3\\CMS\\Form\\": "Classes/" - } - }, - "autoload-dev": { - "psr-4": { - "TYPO3\\CMS\\Form\\Tests\\": "Tests/" - } - } + "require": { + "typo3/cms-core": "*" + }, + "replace": { + "form": "*" + }, + "extra": { + "typo3/cms": { + "Package": { + "partOfFactoryDefault": true + } + } + }, + "autoload": { + "psr-4": { + "TYPO3\\CMS\\Form\\": "Classes/" + } + }, + "autoload-dev": { + "psr-4": { + "TYPO3\\CMS\\Form\\Tests\\": "Tests/" + } + } } diff --git a/typo3/sysext/form/ext_emconf.php b/typo3/sysext/form/ext_emconf.php index 22ce0118f67104432bcde81b596d1b189d9b3bb8..08321e979ce597f3cea7385f8c71c9750b3f784c 100644 --- a/typo3/sysext/form/ext_emconf.php +++ b/typo3/sysext/form/ext_emconf.php @@ -1,14 +1,14 @@ <?php $EM_CONF[$_EXTKEY] = [ 'title' => 'Form', - 'description' => 'Form Library, Plugin and Wizard', - 'category' => 'plugin', + 'description' => 'Form Library, Plugin and Editor', + 'category' => 'misc', 'state' => 'beta', 'uploadfolder' => 0, 'createDirs' => '', 'clearCacheOnLoad' => 1, - 'author' => 'Patrick Broens, Ralf Zimmermann', - 'author_email' => 'patrick@patrickbroens.nl, ralf.zimmermann@tritum.de', + 'author' => 'Form Team', + 'author_email' => '', 'author_company' => '', 'version' => '8.5.0', 'constraints' => [ diff --git a/typo3/sysext/form/ext_localconf.php b/typo3/sysext/form/ext_localconf.php index 511c41d247fd82e4ed30494768b038c070cdfa9d..0be93ed71c1e27129a7c0ec0a6fd4f782de6d1ef 100644 --- a/typo3/sysext/form/ext_localconf.php +++ b/typo3/sysext/form/ext_localconf.php @@ -1,47 +1,66 @@ <?php defined('TYPO3_MODE') or die(); -if (TYPO3_MODE === 'BE') { - // Apply PageTSconfig +call_user_func(function () { + // Register FE plugin + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( + 'TYPO3.CMS.Form', + 'Formframework', + ['FormFrontend' => 'render, perform'], + ['FormFrontend' => 'perform'], + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT + ); + + // Add new content element wizard entry \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPageTSConfig( '<INCLUDE_TYPOSCRIPT: source="FILE:EXT:form/Configuration/PageTS/modWizards.ts">' ); - // Add default User TS Config FORM configuration - \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addUserTSConfig( - '<INCLUDE_TYPOSCRIPT: source="FILE:EXT:form/Configuration/UserTSconfig/userTSConfig.txt">' + // FE file upload processing + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerTypeConverter( + \TYPO3\CMS\Form\Mvc\Property\TypeConverter\UploadedFileReferenceConverter::class ); - // Backend view - $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']['mailform'] = - \TYPO3\CMS\Form\Hooks\PageLayoutView\MailformPreviewRenderer::class; - - $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1440772316] = [ - 'nodeName' => 'formwizard', - 'priority' => 40, - 'class' => \TYPO3\CMS\Form\View\Wizard\Element\FormWizardElement::class, - ]; -} - -// Extbase handling -\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerTypeConverter( - \TYPO3\CMS\Form\Domain\Property\TypeConverter\ArrayToValidationElementConverter::class -); - -\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( - 'TYPO3.CMS.Form', - 'Form', - ['Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess'], - ['Frontend' => 'show, confirmation, dispatchConfirmationButtonClick, process, afterProcess'] -); + // Hook to enrich tt_content form flex element with finisher settings and form list drop down + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][\TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools::class]['flexParsing'][ + \TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook::class + ] = \TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook::class; -\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\SignalSlot\Dispatcher::class) - ->connect( - \TYPO3\CMS\Form\Domain\Builder\FormBuilder::class, - 'txFormHandleIncomingValues', - \TYPO3\CMS\Form\Hooks\HandleIncomingFormValues::class, - 'handleIncomingFormValues' - ); + // Hook to count used forms elements in tt_content + $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['softRefParser']['formPersistenceIdentifier'] = + \TYPO3\CMS\Form\Hooks\SoftReferenceParserHook::class; -// Register the extbase plugin as shorthand for typoscript 10 = FORM -$GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects']['FORM'] = \TYPO3\CMS\Form\ContentObject\FormContentObject::class; + // Add a bunch of icons to icon registry + $iconIdentifiers = [ + 'advanced-password', + 'checkbox', + 'content-element', + 'date-picker', + 'duplicate', + 'fieldset', + 'file-upload', + 'finisher', + 'image-upload', + 'insert-after', + 'insert-in', + 'multi-checkbox', + 'multi-select', + 'page', + 'password', + 'radio-button', + 'single-select', + 'static-text', + 'summary-page', + 'text', + 'textarea', + 'validator' + ]; + $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class); + foreach ($iconIdentifiers as $iconIdentifier) { + $iconRegistry->registerIcon( + 't3-form-icon-' . $iconIdentifier, + \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + ['source' => 'EXT:form/Resources/Public/Images/' . $iconIdentifier . '.svg'] + ); + } +}); diff --git a/typo3/sysext/form/ext_tables.php b/typo3/sysext/form/ext_tables.php new file mode 100644 index 0000000000000000000000000000000000000000..c036107a9a71588387fa913a939e4a8b14c0f318 --- /dev/null +++ b/typo3/sysext/form/ext_tables.php @@ -0,0 +1,21 @@ +<?php +defined('TYPO3_MODE') or die(); + +// Register the backend module Web->Forms +\TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerModule( + 'TYPO3.CMS.Form', + 'web', + 'formbuilder', + '', + [ + 'FormManager' => 'index, show, create, duplicate, references, delete', + 'FormEditor' => 'index, saveForm, renderFormPage, renderRenderableOptions', + ], + [ + 'access' => 'user,group', + 'icon' => 'EXT:form/Resources/Public/Icons/Extension.png', + 'labels' => 'LLL:EXT:form/Resources/Private/Language/locallang_module.xlf', + 'navigationComponentId' => '', + 'inheritNavigationComponentFromMainModule' => false + ] +); diff --git a/typo3/sysext/form/ext_tables.sql b/typo3/sysext/form/ext_tables.sql deleted file mode 100644 index 3fe240733fd62bd95eeb60d24b72eea83dec2ff4..0000000000000000000000000000000000000000 --- a/typo3/sysext/form/ext_tables.sql +++ /dev/null @@ -1,6 +0,0 @@ -# -# Table structure for table 'tt_content' -# -CREATE TABLE tt_content ( - tx_form_predefinedform varchar(255) DEFAULT '' NOT NULL -); diff --git a/typo3/sysext/form/ext_typoscript_setup.txt b/typo3/sysext/form/ext_typoscript_setup.txt new file mode 100644 index 0000000000000000000000000000000000000000..a47e55edca49d728e06e86519dcf96d860d03d7b --- /dev/null +++ b/typo3/sysext/form/ext_typoscript_setup.txt @@ -0,0 +1,2 @@ +<INCLUDE_TYPOSCRIPT: source="FILE:EXT:form/Configuration/TypoScript/setup.txt"> +<INCLUDE_TYPOSCRIPT: source="FILE:EXT:form/Configuration/TypoScript/backend.txt"> \ No newline at end of file