From df120133abfcf68b4fa54343276d7380ef877b8b Mon Sep 17 00:00:00 2001 From: Maxime Rainville Date: Thu, 11 Jun 2020 19:53:46 +1200 Subject: [PATCH] Move confirm folder logic to a dedicated controller --- _config.php | 5 + client/dist/js/userforms-cms.js | 2 +- client/src/bundles/ConfirmFolder.js | 4 +- code/Control/UserDefinedFormAdmin.php | 342 ++++++++++++++++++++++++++ 4 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 code/Control/UserDefinedFormAdmin.php diff --git a/_config.php b/_config.php index b3d9bbc..b189904 100644 --- a/_config.php +++ b/_config.php @@ -1 +1,6 @@ ');var r=e(this).closest("tr").data("id");t.data("id",r),e("body").append(t),t.open()}}}),e("#confirm-folder__dialog-wrapper").entwine({onunmatch:function(){this._clearModal()},open:function(){this._renderModal(!0)},close:function(t){if(!t){var r=e("#confirm-folder__dialog-wrapper").data("id");e(".ss-gridfield-item[data-id='"+r+"'] .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='0']").val("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableTextField")}this._renderModal(!1)},_renderModal:function(t){var r=this,o=function(){return r._handleHideModal.apply(r,arguments)},s=function(){return r._handleSubmitModal.apply(r,arguments)},a=i.default._t("UserForms.FILE_CONFIRMATION_TITLE","Select file upload folder"),l=e(this).data("id"),h=m.default.parse("UserDefinedFormController/confirmfolderformschema"),c=F.default.parse(h.query);c.ID=l;var f=m.default.format(n({},h,{search:F.default.stringify(c)}));d.default.render(u.default.createElement(g,{title:a,isOpen:t,onSubmit:s,onClosed:o,schemaUrl:f,bodyClassName:"modal__dialog",className:"confirm-folder-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"UserForms.ConfirmFolder"}),this[0])},_clearModal:function(){d.default.unmountComponentAtNode(this[0])},_handleHideModal:function(){return this.close()},_handleSubmitModal:function(t,r,o){var n=this;return o().then(function(){l.default.noticeAdd({text:i.default._t("UserForms.FILE_CONFIRMATION_CONFIRMATION","Folder confirmed successfully."),stay:!1,type:"success"}),n.close(!0),e("#Form_EditForm_action_save").trigger("click")}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e("#Form_ConfirmFolderForm_action_cancel").entwine({onclick:function(){e("#confirm-folder__dialog-wrapper").close()}})})},"./client/src/bundles/FieldEditor.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t=null;e(".uf-field-editor .ss-gridfield-items").entwine({onmatch:function(){var r=0,o=0,n=e(".uf-field-editor .ss-gridfield-buttonrow").addClass("sticky-buttons"),s=e(".cms-content-header.north").first().height()+parseInt(e(".sticky-buttons").css("padding-top"),10),i=e(".uf-field-editor");this._super(),this.find(".ss-gridfield-item").each(function(t,n){switch(e(n).data("class")){case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep":return void(o=0);case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroup":o+=1,r=o;break;case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd":r=o,o-=1;break;default:r=o}e(n).toggleClass("infieldgroup",r>0);for(var s=1;s<=5;s++)e(n).toggleClass("infieldgroup-level-"+s,r>=s)}),t=setInterval(function(){var e=i.offset().top;n.width("100%"),e>s||0===e?n.removeClass("sticky-buttons"):n.addClass("sticky-buttons")},300)},onunmatch:function(){this._super(),clearInterval(t)}}),e(".uf-field-editor .ss-gridfield-buttonrow .action").entwine({onclick:function(e){this._super(e),this.trigger("addnewinline")}}),e(".uf-field-editor").entwine({onmatch:function(){var t=this;this._super(),this.on("addnewinline",function(){t.one("reload",function(){var r=t.find(".ss-gridfield-item").last(),o=null;"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd"===r.attr("data-class")?(o=r,o.prev().find(".col-Title input").focus(),r=o.add(o.prev()),o.css("visibility","hidden")):r.find(".col-Title input").focus(),r.addClass("flashBackground");var n=e(".cms-content-fields");n.length>0&&n.scrollTop(n[0].scrollHeight),o&&o.css("visibility","visible")})})},onummatch:function(){this._super()}})})},"./client/src/bundles/Recipient.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t={updateFormatSpecificFields:function(){var t=e('input[name="SendPlain"]').is(":checked");e(".field.toggle-html-only")[t?"hide":"show"](),e(".field.toggle-plain-only")[t?"show":"hide"]()}};e("#Form_ItemEditForm .EmailRecipientForm").entwine({onmatch:function(){t.updateFormatSpecificFields()},onunmatch:function(){(void 0)._super()}}),e('#Form_ItemEditForm .EmailRecipientForm input[name="SendPlain"]').entwine({onchange:function(){t.updateFormatSpecificFields()}})})},"./client/src/bundles/bundle-cms.js":function(e,t,r){"use strict";r("./client/src/bundles/FieldEditor.js"),r("./client/src/bundles/ConfirmFolder.js"),r("./client/src/bundles/Recipient.js")},"./node_modules/punycode/punycode.js":function(e,t,r){(function(e,o){var n;!function(o){function s(e){throw new RangeError(S[e])}function i(e,t){for(var r=e.length,o=[];r--;)o[r]=t(e[r]);return o}function a(e,t){var r=e.split("@"),o="";return r.length>1&&(o=r[0]+"@",e=r[1]),e=e.replace(A,"."),o+i(e.split("."),t).join(".")}function l(e){for(var t,r,o=[],n=0,s=e.length;n=55296&&t<=56319&&n65535&&(e-=65536,t+=U(e>>>10&1023|55296),e=56320|1023&e),t+=U(e)}).join("")}function u(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:_}function c(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function d(e,t,r){var o=0;for(e=r?k(e/w):e>>1,e+=k(e/t);e>q*y>>1;o+=_)e=k(e/q);return k(o+(q+1)*e/(e+j))}function f(e){var t,r,o,n,i,a,l,c,f,p,m=[],v=e.length,F=0,j=O,w=C;for(r=e.lastIndexOf(x),r<0&&(r=0),o=0;o=128&&s("not-basic"),m.push(e.charCodeAt(o));for(n=r>0?r+1:0;n=v&&s("invalid-input"),c=u(e.charCodeAt(n++)),(c>=_||c>k((g-F)/a))&&s("overflow"),F+=c*a,f=l<=w?b:l>=w+y?y:l-w,!(ck(g/p)&&s("overflow"),a*=p;t=m.length+1,w=d(F-i,t,0==i),k(F/t)>g-j&&s("overflow"),j+=k(F/t),F%=t,m.splice(F++,0,j)}return h(m)}function p(e){var t,r,o,n,i,a,h,u,f,p,m,v,F,j,w,I=[];for(e=l(e),v=e.length,t=O,r=0,i=C,a=0;a=t&&mk((g-r)/F)&&s("overflow"),r+=(h-t)*F,t=h,a=0;ag&&s("overflow"),m==t){for(u=r,f=_;p=f<=i?b:f>=i+y?y:f-i,!(u= 0x80 (not a basic code point)","invalid-input":"Invalid input"},q=_-b,k=Math.floor,U=String.fromCharCode;F={version:"1.4.1",ucs2:{decode:l,encode:h},decode:f,encode:p,toASCII:v,toUnicode:m},void 0!==(n=function(){return F}.call(t,r,t,e))&&(e.exports=n)}()}).call(t,r("./node_modules/webpack/buildin/module.js")(e),r("./node_modules/webpack/buildin/global.js"))},"./node_modules/querystring-es3/decode.js":function(e,t,r){"use strict";function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,r,s){t=t||"&",r=r||"=";var i={};if("string"!=typeof e||0===e.length)return i;var a=/\+/g;e=e.split(t);var l=1e3;s&&"number"==typeof s.maxKeys&&(l=s.maxKeys);var h=e.length;l>0&&h>l&&(h=l);for(var u=0;u=0?(c=m.substr(0,v),d=m.substr(v+1)):(c=m,d=""),f=decodeURIComponent(c),p=decodeURIComponent(d),o(i,f)?n(i[f])?i[f].push(p):i[f]=[i[f],p]:i[f]=p}return i};var n=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},"./node_modules/querystring-es3/encode.js":function(e,t,r){"use strict";function o(e,t){if(e.map)return e.map(t);for(var r=[],o=0;o",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(f),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),F=["/","?","#"],g=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},j={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=r("./node_modules/querystring-es3/index.js");o.prototype.parse=function(e,t,r){if(!h.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),n=-1!==o&&o127?M+="x":M+=U[R];if(!M.match(g)){var H=q.slice(0,x),T=q.slice(x+1),D=U.match(_);D&&(H.push(D[1]),T.unshift(D[2])),T.length&&(a="/"+T.join(".")+a),this.hostname=H.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),S||(this.hostname=l.toASCII(this.hostname));var P=this.port?":"+this.port:"",L=this.hostname||"";this.host=L+P,this.href+=this.host,S&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==a[0]&&(a="/"+a))}if(!b[p])for(var x=0,k=m.length;x0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return r.search=e.search,r.query=e.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var x=w.slice(-1)[0],I=(r.host||e.host||w.length>1)&&("."===x||".."===x)||""===x,E=0,A=w.length;A>=0;A--)x=w[A],"."===x?w.splice(A,1):".."===x?(w.splice(A,1),E++):E&&(w.splice(A,1),E--);if(!_&&!b)for(;E--;E)w.unshift("..");!_||""===w[0]||w[0]&&"/"===w[0].charAt(0)||w.unshift(""),I&&"/"!==w.join("/").substr(-1)&&w.push("");var S=""===w[0]||w[0]&&"/"===w[0].charAt(0);if(C){r.hostname=r.host=S?"":w.length?w.shift():"";var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return _=_||r.host&&w.length,_&&!S&&w.unshift(""),w.length?r.pathname=w.join("/"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=c.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},"./node_modules/url/util.js":function(e,t,r){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},"./node_modules/webpack/buildin/global.js":function(e,t){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(r=window)}e.exports=r},"./node_modules/webpack/buildin/module.js":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=Injector},2:function(e,t){e.exports=React},3:function(e,t){e.exports=ReactDom},4:function(e,t){e.exports=i18n},5:function(e,t){e.exports=qs}}); \ No newline at end of file +!function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={i:o,l:!1,exports:{}};return e[o].call(n.exports,n,n.exports,t),n.l=!0,n.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,o){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle-cms.js")}({"./client/src/bundles/ConfirmFolder.js":function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var n=Object.assign||function(e){for(var t=1;t');var r=e(this).closest("tr").data("id");t.data("id",r),e("body").append(t),t.open()}}}),e("#confirm-folder__dialog-wrapper").entwine({onunmatch:function(){this._clearModal()},open:function(){this._renderModal(!0)},close:function(t){if(!t){var r=e("#confirm-folder__dialog-wrapper").data("id");e(".ss-gridfield-item[data-id='"+r+"'] .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='0']").val("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableTextField")}this._renderModal(!1)},_renderModal:function(t){var r=this,o=function(){return r._handleHideModal.apply(r,arguments)},s=function(){return r._handleSubmitModal.apply(r,arguments)},a=i.default._t("UserForms.FILE_CONFIRMATION_TITLE","Select file upload folder"),l=e(this).data("id"),h=m.default.parse("admin/user-forms/confirmfolderformschema"),c=F.default.parse(h.query);c.ID=l;var f=m.default.format(n({},h,{search:F.default.stringify(c)}));d.default.render(u.default.createElement(g,{title:a,isOpen:t,onSubmit:s,onClosed:o,schemaUrl:f,bodyClassName:"modal__dialog",className:"confirm-folder-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"UserForms.ConfirmFolder"}),this[0])},_clearModal:function(){d.default.unmountComponentAtNode(this[0])},_handleHideModal:function(){return this.close()},_handleSubmitModal:function(t,r,o){var n=this;return o().then(function(){l.default.noticeAdd({text:i.default._t("UserForms.FILE_CONFIRMATION_CONFIRMATION","Folder confirmed successfully."),stay:!1,type:"success"}),n.close(!0),e("[name=action_doSave], [name=action_save]").click()}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e("#Form_ConfirmFolderForm_action_cancel").entwine({onclick:function(){e("#confirm-folder__dialog-wrapper").close()}})})},"./client/src/bundles/FieldEditor.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t=null;e(".uf-field-editor .ss-gridfield-items").entwine({onmatch:function(){var r=0,o=0,n=e(".uf-field-editor .ss-gridfield-buttonrow").addClass("sticky-buttons"),s=e(".cms-content-header.north").first().height()+parseInt(e(".sticky-buttons").css("padding-top"),10),i=e(".uf-field-editor");this._super(),this.find(".ss-gridfield-item").each(function(t,n){switch(e(n).data("class")){case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep":return void(o=0);case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroup":o+=1,r=o;break;case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd":r=o,o-=1;break;default:r=o}e(n).toggleClass("infieldgroup",r>0);for(var s=1;s<=5;s++)e(n).toggleClass("infieldgroup-level-"+s,r>=s)}),t=setInterval(function(){var e=i.offset().top;n.width("100%"),e>s||0===e?n.removeClass("sticky-buttons"):n.addClass("sticky-buttons")},300)},onunmatch:function(){this._super(),clearInterval(t)}}),e(".uf-field-editor .ss-gridfield-buttonrow .action").entwine({onclick:function(e){this._super(e),this.trigger("addnewinline")}}),e(".uf-field-editor").entwine({onmatch:function(){var t=this;this._super(),this.on("addnewinline",function(){t.one("reload",function(){var r=t.find(".ss-gridfield-item").last(),o=null;"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd"===r.attr("data-class")?(o=r,o.prev().find(".col-Title input").focus(),r=o.add(o.prev()),o.css("visibility","hidden")):r.find(".col-Title input").focus(),r.addClass("flashBackground");var n=e(".cms-content-fields");n.length>0&&n.scrollTop(n[0].scrollHeight),o&&o.css("visibility","visible")})})},onummatch:function(){this._super()}})})},"./client/src/bundles/Recipient.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t={updateFormatSpecificFields:function(){var t=e('input[name="SendPlain"]').is(":checked");e(".field.toggle-html-only")[t?"hide":"show"](),e(".field.toggle-plain-only")[t?"show":"hide"]()}};e("#Form_ItemEditForm .EmailRecipientForm").entwine({onmatch:function(){t.updateFormatSpecificFields()},onunmatch:function(){(void 0)._super()}}),e('#Form_ItemEditForm .EmailRecipientForm input[name="SendPlain"]').entwine({onchange:function(){t.updateFormatSpecificFields()}})})},"./client/src/bundles/bundle-cms.js":function(e,t,r){"use strict";r("./client/src/bundles/FieldEditor.js"),r("./client/src/bundles/ConfirmFolder.js"),r("./client/src/bundles/Recipient.js")},"./node_modules/punycode/punycode.js":function(e,t,r){(function(e,o){var n;!function(o){function s(e){throw new RangeError(E[e])}function i(e,t){for(var r=e.length,o=[];r--;)o[r]=t(e[r]);return o}function a(e,t){var r=e.split("@"),o="";return r.length>1&&(o=r[0]+"@",e=r[1]),e=e.replace(A,"."),o+i(e.split("."),t).join(".")}function l(e){for(var t,r,o=[],n=0,s=e.length;n=55296&&t<=56319&&n65535&&(e-=65536,t+=U(e>>>10&1023|55296),e=56320|1023&e),t+=U(e)}).join("")}function u(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:_}function c(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function d(e,t,r){var o=0;for(e=r?k(e/w):e>>1,e+=k(e/t);e>q*y>>1;o+=_)e=k(e/q);return k(o+(q+1)*e/(e+j))}function f(e){var t,r,o,n,i,a,l,c,f,p,m=[],v=e.length,F=0,j=O,w=C;for(r=e.lastIndexOf(x),r<0&&(r=0),o=0;o=128&&s("not-basic"),m.push(e.charCodeAt(o));for(n=r>0?r+1:0;n=v&&s("invalid-input"),c=u(e.charCodeAt(n++)),(c>=_||c>k((g-F)/a))&&s("overflow"),F+=c*a,f=l<=w?b:l>=w+y?y:l-w,!(ck(g/p)&&s("overflow"),a*=p;t=m.length+1,w=d(F-i,t,0==i),k(F/t)>g-j&&s("overflow"),j+=k(F/t),F%=t,m.splice(F++,0,j)}return h(m)}function p(e){var t,r,o,n,i,a,h,u,f,p,m,v,F,j,w,I=[];for(e=l(e),v=e.length,t=O,r=0,i=C,a=0;a=t&&mk((g-r)/F)&&s("overflow"),r+=(h-t)*F,t=h,a=0;ag&&s("overflow"),m==t){for(u=r,f=_;p=f<=i?b:f>=i+y?y:f-i,!(u= 0x80 (not a basic code point)","invalid-input":"Invalid input"},q=_-b,k=Math.floor,U=String.fromCharCode;F={version:"1.4.1",ucs2:{decode:l,encode:h},decode:f,encode:p,toASCII:v,toUnicode:m},void 0!==(n=function(){return F}.call(t,r,t,e))&&(e.exports=n)}()}).call(t,r("./node_modules/webpack/buildin/module.js")(e),r("./node_modules/webpack/buildin/global.js"))},"./node_modules/querystring-es3/decode.js":function(e,t,r){"use strict";function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,r,s){t=t||"&",r=r||"=";var i={};if("string"!=typeof e||0===e.length)return i;var a=/\+/g;e=e.split(t);var l=1e3;s&&"number"==typeof s.maxKeys&&(l=s.maxKeys);var h=e.length;l>0&&h>l&&(h=l);for(var u=0;u=0?(c=m.substr(0,v),d=m.substr(v+1)):(c=m,d=""),f=decodeURIComponent(c),p=decodeURIComponent(d),o(i,f)?n(i[f])?i[f].push(p):i[f]=[i[f],p]:i[f]=p}return i};var n=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},"./node_modules/querystring-es3/encode.js":function(e,t,r){"use strict";function o(e,t){if(e.map)return e.map(t);for(var r=[],o=0;o",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(f),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),F=["/","?","#"],g=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},j={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=r("./node_modules/querystring-es3/index.js");o.prototype.parse=function(e,t,r){if(!h.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),n=-1!==o&&o127?M+="x":M+=U[R];if(!M.match(g)){var H=q.slice(0,x),T=q.slice(x+1),D=U.match(_);D&&(H.push(D[1]),T.unshift(D[2])),T.length&&(a="/"+T.join(".")+a),this.hostname=H.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),E||(this.hostname=l.toASCII(this.hostname));var P=this.port?":"+this.port:"",L=this.hostname||"";this.host=L+P,this.href+=this.host,E&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==a[0]&&(a="/"+a))}if(!b[p])for(var x=0,k=m.length;x0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return r.search=e.search,r.query=e.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var x=w.slice(-1)[0],I=(r.host||e.host||w.length>1)&&("."===x||".."===x)||""===x,S=0,A=w.length;A>=0;A--)x=w[A],"."===x?w.splice(A,1):".."===x?(w.splice(A,1),S++):S&&(w.splice(A,1),S--);if(!_&&!b)for(;S--;S)w.unshift("..");!_||""===w[0]||w[0]&&"/"===w[0].charAt(0)||w.unshift(""),I&&"/"!==w.join("/").substr(-1)&&w.push("");var E=""===w[0]||w[0]&&"/"===w[0].charAt(0);if(C){r.hostname=r.host=E?"":w.length?w.shift():"";var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return _=_||r.host&&w.length,_&&!E&&w.unshift(""),w.length?r.pathname=w.join("/"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=c.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},"./node_modules/url/util.js":function(e,t,r){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},"./node_modules/webpack/buildin/global.js":function(e,t){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(r=window)}e.exports=r},"./node_modules/webpack/buildin/module.js":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=Injector},2:function(e,t){e.exports=React},3:function(e,t){e.exports=ReactDom},4:function(e,t){e.exports=i18n},5:function(e,t){e.exports=qs}}); \ No newline at end of file diff --git a/client/src/bundles/ConfirmFolder.js b/client/src/bundles/ConfirmFolder.js index f59c9a2..cba1de9 100644 --- a/client/src/bundles/ConfirmFolder.js +++ b/client/src/bundles/ConfirmFolder.js @@ -140,7 +140,7 @@ jQuery.entwine('ss', ($) => { const editableFileFieldID = $(this).data('id'); // Build schema url - const parsedURL = url.parse('UserDefinedFormController/confirmfolderformschema'); + const parsedURL = url.parse('admin/user-forms/confirmfolderformschema'); const parsedQs = qs.parse(parsedURL.query); parsedQs.ID = editableFileFieldID; const schemaUrl = url.format({ ...parsedURL, search: qs.stringify(parsedQs) }); @@ -177,7 +177,7 @@ jQuery.entwine('ss', ($) => { .then(() => { jQuery.noticeAdd({ text: i18n._t('UserForms.FILE_CONFIRMATION_CONFIRMATION', 'Folder confirmed successfully.'), stay: false, type: 'success' }); this.close(true); - $('#Form_EditForm_action_save').trigger('click'); + $('[name=action_doSave], [name=action_save]').click(); }) .catch((error) => { jQuery.noticeAdd({ text: error.message, stay: false, type: 'error' }); diff --git a/code/Control/UserDefinedFormAdmin.php b/code/Control/UserDefinedFormAdmin.php new file mode 100644 index 0000000..79af220 --- /dev/null +++ b/code/Control/UserDefinedFormAdmin.php @@ -0,0 +1,342 @@ + 'CMS_ACCESS_CMSMain', + 'ConfirmFolderForm' => 'CMS_ACCESS_CMSMain', + 'confirmfolder' => 'CMS_ACCESS_CMSMain', + 'getfoldergrouppermissions' => 'CMS_ACCESS_CMSMain', + ]; + + private static $url_segment = 'user-forms'; + + /** + * @var string The name of the folder where form submissions will be placed by default + */ + private static $form_submissions_folder = 'Form-submissions'; + + /** + * Returns a TextField for entering a folder name. + * @param string $folder The current folder to set the field to + * @param string $title The title of the text field + * @return TextField + */ + private static function getRestrictedAccessField(string $folder, string $title) + { + /** @var TextField $textField */ + $textField = TextField::create('CreateFolder', ''); + + /** @var Folder $formSubmissionsFolder */ + $formSubmissionsFolder = Folder::find($folder); + $textField->setDescription(EditableFileField::getFolderPermissionString($formSubmissionsFolder)); + $textField->addExtraClass('pt-2'); + $textField->setSchemaData([ + 'data' => [ + 'prefix' => static::config()->get('form_submissions_folder') . '/', + ], + 'attributes' => [ + 'placeholder' => $title + ] + ]); + + return $textField; + } + + public function index($request) + { + return $this->httpError(404); + } + + /** + * This returns a Confirm Folder form used to verify the upload folder for EditableFileFields + * @param HTTPRequest $request + * @return HTTPResponse + */ + public function confirmfolderformschema(HTTPRequest $request) + { + // Retrieve editable form field by its ID + $id = $request->requestVar('ID'); + if (!$id) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + $editableFormField = EditableFormField::get()->byID($id); + if (!$editableFormField) { + $editableFormField = Versioned::get_by_stage(EditableFormField::class, Versioned::DRAFT) + ->byID($id); + } + if (!$editableFormField) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + + // Retrieve the editable form fields Parent + $userForm = $editableFormField->Parent(); + if (!$userForm) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + if (!$userForm->canEdit()) { + throw new PermissionFailureException(); + } + + // Get the folder we want to associate to this EditableFileField + $folderId = 0; + if ($editableFormField instanceof EditableFileField) { + $folderId = $editableFormField->FolderID; + } + /** @var Folder $folder */ + $folder = Folder::get()->byID($folderId); + if (!$folder) { + $folder = $this->getFormSubmissionFolder(); + } + + $form = $this->buildConfirmFolderForm( + $userForm->Title ?: '', + EditableFileField::getFolderPermissionString($folder) + ); + $form->loadDataFrom(['FolderID' => $folderId, 'ID' => $id]); + + // Convert the EditableFormField to an EditableFileField if it's not already one. + if (!$editableFormField instanceof EditableFileField) { + $editableFormField = $editableFormField->newClassInstance(EditableFileField::class); + $editableFormField->write(); + } + + // create the schema response + $parts = $this->getRequest()->getHeader(static::SCHEMA_HEADER); + $schemaID = $this->getRequest()->getURL(); + $data = FormSchema::singleton()->getMultipartSchema($parts, $schemaID, $form); + + // return the schema response + $response = HTTPResponse::create(json_encode($data)); + $response->addHeader('Content-Type', 'application/json'); + return $response; + } + + public function ConfirmFolderForm(): Form + { + return $this->buildConfirmFolderForm(); + } + + private function buildConfirmFolderForm(string $suggestedFolderName = '', string $permissionFolderString = ''): Form + { + // Build our Field list for the Form we will return to the front end. + $fields = FieldList::create( + LiteralField::create( + 'LabelA', + _t(__CLASS__.'.CONFIRM_FOLDER_LABEL_A', 'Files that your users upload should be stored carefully to reduce the risk of exposing sensitive data. Ensure the folder you select can only be viewed by appropriate parties. Folder permissions can be managed within the Files area.') + )->addExtraClass(' mb-2'), + LiteralField::create( + 'LabelB', + _t(__CLASS__.'.CONFIRM_FOLDER_LABEL_B', 'The folder selected will become the default for this form. This can be changed on an individual basis in the File upload field.') + )->addExtraClass(' mb-3'), + static::getRestrictedAccessField($this->config()->get('form_submissions_folder'), $suggestedFolderName), + OptionsetField::create('FolderOptions', _t(__CLASS__.'.FOLDER_OPTIONS_TITLE', 'Form folder options'), [ + "new" => _t(__CLASS__.'.FOLDER_OPTIONS_NEW', 'Create a new folder (recommended)'), + "existing" => _t(__CLASS__.'.FOLDER_OPTIONS_EXISTING', 'Use an existing folder') + ], "new"), + TreeDropdownField::create('FolderID', '', Folder::class) + ->addExtraClass('pt-1') + ->setDescription($permissionFolderString) + , + HiddenField::create('ID') + ); + + $actions = FieldList::create( + FormAction::create('confirmfolder', _t(__CLASS__.'.FORM_ACTION_CONFIRM', 'Save and continue')) + ->setUseButtonTag(false) + ->addExtraClass('btn btn-primary'), + FormAction::create("cancel", _t(CMSMain::class . '.Cancel', "Cancel")) + ->addExtraClass('btn btn-secondary') + ->setUseButtonTag(true) + ); + + return Form::create($this, 'ConfirmFolderForm', $fields, $actions, RequiredFields::create('ID')) + ->setFormAction('UserDefinedFormController/ConfirmFolderForm') + ->setFormAction($this->Link('ConfirmFolderForm')) + ->addExtraClass('form--no-dividers'); + } + + /** + * Sets the selected folder as the upload folder for an EditableFileField + * @return HTTPResponse + * @param HTTPRequest $request + * @throws ValidationException + */ + public function confirmfolder(array $data, Form $form, HTTPRequest $request) + { + if (!Permission::checkMember(null, "CMS_ACCESS_AssetAdmin")) { + throw new PermissionFailureException(); + } + + // retrieve the EditableFileField + $id = $data['ID']; + if (!$id) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + /** @var EditableFileField $editableFileField */ + $editableFormField = EditableFormField::get()->byID($id); + if (!$editableFormField) { + $editableFormField = Versioned::get_by_stage(EditableFormField::class, Versioned::DRAFT)->byID($id); + } + if (!$editableFormField) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + // change the class if it is incorrect + if (!$editableFormField instanceof EditableFileField) { + $editableFormField = $editableFormField->newClassInstance(EditableFileField::class); + } + if (!$editableFormField) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + $editableFileField = $editableFormField; + + if (!$editableFileField->canEdit()) { + throw new PermissionFailureException(); + } + + // check if we're creating a new folder or using an existing folder + $option = $data['FolderOptions']; + if ($option === 'existing') { + // set existing folder + $folderID = $data['FolderID']; + if ($folderID != 0) { + $folder = Folder::get()->byID($folderID); + if (!$folder) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + } + } else { + // create the folder + $createFolder = isset($data['CreateFolder']) ? $data['CreateFolder'] : $editableFormField->Parent()->Title; + $folder = $this->getFormSubmissionFolder($createFolder); + } + + // assign the folder + $editableFileField->FolderID = isset($folder) ? $folder->ID : 0; + $editableFileField->write(); + + // respond + return HTTPResponse::create(json_encode([]))->addHeader('Content-Type', 'application/json'); + } + + /** + * @return HTTPResponse + */ + public function getfoldergrouppermissions() + { + $folderID = $this->getRequest()->requestVar('FolderID'); + if ($folderID) { + /** @var Folder $folder */ + $folder = Folder::get()->byID($folderID); + if (!$folder) { + throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400); + } + if (!$folder->canView()) { + throw new PermissionFailureException(); + } + } else { + $folder = null; + } + + // respond + $response = HTTPResponse::create(json_encode(EditableFileField::getFolderPermissionString($folder))); + $response->addHeader('Content-Type', 'application/json'); + return $response; + } + + /** + * @throws ValidationException + */ + private static function updateFormSubmissionFolderPermissions() + { + // ensure the FormSubmissions folder is only accessible to Administrators + $formSubmissionsFolder = Folder::find(self::config()->get('form_submissions_folder')); + $formSubmissionsFolder->CanViewType = InheritedPermissions::ONLY_THESE_USERS; + $formSubmissionsFolder->ViewerGroups()->removeAll(); + $formSubmissionsFolder->ViewerGroups()->add(Group::get_one(Group::class, ['"Code"' => 'administrators'])); + $formSubmissionsFolder->write(); + } + + /** + * Returns the form submission folder or a sub folder if provided. + * Creates the form submission folder if it doesn't exist. + * Updates the form submission folder permissions if it is created. + * @param string $subFolder Sub-folder to be created or returned. + * @return Folder + * @throws ValidationException + */ + public static function getFormSubmissionFolder(string $subFolder = null): ?Folder + { + $folderPath = self::config()->get('form_submissions_folder'); + if ($subFolder) { + $folderPath .= '/' . $subFolder; + } + $formSubmissionsFolderExists = !!Folder::find(self::config()->get('form_submissions_folder')); + $folder = Folder::find_or_make($folderPath); + + // Set default permissions if this is the first time we create the form submission folder + if (!$formSubmissionsFolderExists) { + self::updateFormSubmissionFolderPermissions(); + // Make sure we return the folder with the latest permission + $folder = Folder::find($folderPath); + } + + return $folder; + } +}