Quiz And Survey Master < 9.0.2 - Contributor+ SQLi
Description
The Quiz and Survey Master (QSM) WordPress plugin before 9.0.2 is vulnerable does not validate and escape the question_id parameter in the qsm_bulk_delete_question_from_database AJAX action, leading to a SQL injection exploitable by Contributors and above role
Affected products
2- Range: <9.0.2
Patches
144a25300c5c4Merge pull request #2565 from QuizandSurveyMaster/pre-release
47 files changed · +1420 −1201
blocks/build/answer-option/index.asset.php+1 −1 modified@@ -1,4 +1,4 @@ <?php return array( 'dependencies' => array( 'react', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-escape-html', 'wp-html-entities', 'wp-i18n', 'wp-notices', 'wp-primitives', 'wp-url' ), - 'version' => '2d3f4bd22446647134b1', + 'version' => 'af71d6d7cef3818c8dad', );
blocks/build/answer-option/index.js+1 −1 modified@@ -1 +1 @@ -(()=>{"use strict";const e=window.wp.blocks,t=window.wp.element,n=window.wp.i18n,i=window.wp.htmlEntities,o=window.wp.escapeHtml,a=window.wp.blockEditor,l=window.wp.data,r=window.wp.url,c=window.wp.components,s=window.wp.blob,u=window.React,m=window.wp.primitives,d=(0,u.createElement)(m.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg"},(0,u.createElement)(m.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})),p=window.wp.notices,w=e=>null==e||""===e,g=e=>{var t=document.createElement("textarea");return t.innerHTML=e,t.value},E=e=>{let t=document.createElement("div");return t.innerHTML=g(e),t.innerText},h=function({url:e="",caption:i="",alt:o="",setURLCaption:r}){const u=["image"],[m,g]=(0,t.useState)(null),[E,h]=(0,t.useState)(),{imageDefaultSize:x,mediaUpload:f}=((0,t.useRef)(),(0,l.useSelect)((e=>{const{getSettings:t}=e(a.store),n=t();return{imageDefaultSize:n.imageDefaultSize,mediaUpload:n.mediaUpload}}),[])),{createErrorNotice:_}=(0,l.useDispatch)(p.store);function v(e){_(e,{type:"snackbar"}),r(void 0,void 0),h(void 0)}function q(e){if(!e||!e.url)return void r(void 0,void 0);if((0,s.isBlobURL)(e.url))return void h(e.url);h();let t=((e,t)=>{const n=Object.fromEntries(Object.entries(null!=e?e:{}).filter((([e])=>["alt","id","link","caption"].includes(e))));return n.url=e?.sizes?.[t]?.url||e?.media_details?.sizes?.[t]?.source_url||e.url,n})(e,x);g(t.id),r(t.url,t.caption)}function b(t){t!==e&&r(t,i)}let z=((e,t)=>!e&&(0,s.isBlobURL)(t))(m,e);(0,t.useEffect)((()=>{if(!z)return;const t=(0,s.getBlobByURL)(e);t&&f({filesList:[t],onFileChange:([e])=>{q(e)},allowedTypes:u,onError:e=>{z=!1,v(e)}})}),[]),(0,t.useEffect)((()=>{z?h(e):(0,s.revokeBlobURL)(E)}),[z,e]);const R=((e,t)=>t&&!e&&!(0,s.isBlobURL)(t))(m,e)?e:void 0,L=!!e&&(0,t.createElement)("img",{alt:(0,n.__)("Edit image"),title:(0,n.__)("Edit image"),className:"edit-image-preview",src:e});let B=(0,t.createElement)(t.Fragment,null,(0,t.createElement)("img",{src:E||e,alt:"",className:"qsm-answer-option-image",style:{width:"200",height:"auto"}}),E&&(0,t.createElement)(c.Spinner,null));return(0,t.createElement)("figure",null,w(e)?(0,t.createElement)(a.MediaPlaceholder,{icon:(0,t.createElement)(a.BlockIcon,{icon:d}),onSelect:q,onSelectURL:b,onError:v,accept:"image/*",allowedTypes:u,value:{id:m,src:R},mediaPreview:L,disableMediaButtons:E||e}):(0,t.createElement)(t.Fragment,null,(0,t.createElement)(a.BlockControls,{group:"other"},(0,t.createElement)(a.MediaReplaceFlow,{mediaId:m,mediaURL:e,allowedTypes:u,accept:"image/*",onSelect:q,onSelectURL:b,onError:v})),(0,t.createElement)("div",null,B)))},x=JSON.parse('{"u2":"qsm/quiz-answer-option"}');(0,e.registerBlockType)(x.u2,{icon:()=>(0,t.createElement)(c.Icon,{icon:()=>(0,t.createElement)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,t.createElement)("rect",{width:"24",height:"24",rx:"4.21657",fill:"#ADADAD"}),(0,t.createElement)("path",{d:"M8.96182 17.2773H7.33619L10.9889 7.12707H12.7583L16.411 17.2773H14.7853L11.9157 8.97077H11.8364L8.96182 17.2773ZM9.23441 13.3025H14.5078V14.5911H9.23441V13.3025Z",fill:"white"}))}),__experimentalLabel(e,{context:t}){const{content:n}=e,i=e?.metadata?.name;if("list-view"===t&&(i||n?.length>0))return i||n},merge:(e,t)=>({content:(e.content||"")+(t.content||"")}),edit:function(s){if("undefined"==typeof qsmBlockData)return null;const{className:u,attributes:m,setAttributes:d,isSelected:p,clientId:x,context:f,mergeBlocks:_,onReplace:v,onRemove:q}=s,b=(f["quiz-master-next/quizID"],f["quiz-master-next/pageID"],f["quiz-master-next/questionID"],f["quiz-master-next/questionType"]),z=f["quiz-master-next/answerType"],R=f["quiz-master-next/questionChanged"],L="qsm/quiz-answer-option",{optionID:B,content:k,caption:S,points:C,isCorrect:y}=m,{selectBlock:U}=(0,l.useDispatch)(a.store),{updateBlockAttributes:T}=(0,l.useDispatch)(a.store),D=(0,l.useSelect)((e=>{let t=e(a.store).getBlockParentsByBlockName(x,"qsm/quiz-question",!0);return w(t)?"":t[0]}),[x]);(0,t.useEffect)((()=>{let e=!0;return e&&p&&!w(D)&&!1===R&&T(D,{isChanged:!0}),()=>{e=!1}}),[k,S,C,y]),(0,t.useEffect)((()=>{let e=!0;return e&&(w(k)||!(0,r.isURL)(k)||-1===k.indexOf("https://")&&-1===k.indexOf("http://")||!["rich","text"].includes(z)||d({content:"",caption:""})),()=>{e=!1}}),[z]);const I=(0,a.useBlockProps)({className:p?" is-highlighted ":""}),A=["4","10"].includes(b)?"checkbox":"radio";return(0,t.createElement)(t.Fragment,null,(0,t.createElement)(a.InspectorControls,null,(0,t.createElement)(c.PanelBody,{title:(0,n.__)("Settings","quiz-master-next"),initialOpen:!0},"image"===z&&(0,t.createElement)(c.TextControl,{type:"text",label:(0,n.__)("Caption","quiz-master-next"),value:S,onChange:e=>d({caption:(0,o.escapeAttribute)(e)})}),(0,t.createElement)(c.TextControl,{type:"number",label:(0,n.__)("Points","quiz-master-next"),help:(0,n.__)("Answer points","quiz-master-next"),value:C,onChange:e=>d({points:e})}),["0","4","1","10","2"].includes(b)&&(0,t.createElement)(c.ToggleControl,{label:(0,n.__)("Correct","quiz-master-next"),checked:!w(y)&&"1"==y,onChange:()=>d({isCorrect:w(y)||"1"!=y?1:0})}))),(0,t.createElement)("div",{...I},(0,t.createElement)(c.__experimentalHStack,{className:"edit-post-document-actions__title",spacing:1,justify:"left"},(0,t.createElement)("input",{type:A,disabled:!0,readOnly:!0,tabIndex:"-1"}),!["rich","image"].includes(z)&&(0,t.createElement)(a.RichText,{tagName:"p",title:(0,n.__)("Answer options","quiz-master-next"),"aria-label":(0,n.__)("Question answer","quiz-master-next"),placeholder:(0,n.__)("Your Answer","quiz-master-next"),value:E((0,i.decodeEntities)(k)),onChange:e=>d({content:E((0,i.decodeEntities)(e))}),onSplit:(t,n)=>{let i;(n||t)&&(i={...m,content:t});const o=(0,e.createBlock)(L,i);return n&&(o.clientId=x),o},onMerge:_,onReplace:v,onRemove:q,allowedFormats:[],withoutInteractiveFormatting:!0,className:"qsm-question-answer-option",identifier:"text"}),"rich"===z&&(0,t.createElement)(a.RichText,{tagName:"p",title:(0,n.__)("Answer options","quiz-master-next"),"aria-label":(0,n.__)("Question answer","quiz-master-next"),placeholder:(0,n.__)("Your Answer","quiz-master-next"),value:g((0,i.decodeEntities)(k)),onChange:e=>d({content:e}),onSplit:(t,n)=>{let i;(n||t)&&(i={...m,content:t});const o=(0,e.createBlock)(L,i);return n&&(o.clientId=x),o},onMerge:_,onReplace:v,onRemove:q,className:"qsm-question-answer-option",identifier:"text",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),"image"===z&&(0,t.createElement)(h,{url:(0,r.isURL)(k)?k:"",caption:S,setURLCaption:(e,t)=>d({content:(0,r.isURL)(e)?e:"",caption:t})}))))}})})(); \ No newline at end of file +(()=>{"use strict";const e=window.wp.blocks,t=window.wp.element,n=window.wp.i18n,i=window.wp.htmlEntities,a=window.wp.escapeHtml,o=window.wp.blockEditor,l=window.wp.data,r=window.wp.url,s=window.wp.components,c=window.wp.blob,u=window.React,m=window.wp.primitives,d=(0,u.createElement)(m.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg"},(0,u.createElement)(m.Path,{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.5h14c.3 0 .5.2.5.5v8.4l-3-2.9c-.3-.3-.8-.3-1 0L11.9 14 9 12c-.3-.2-.6-.2-.8 0l-3.6 2.6V5c-.1-.3.1-.5.4-.5zm14 15H5c-.3 0-.5-.2-.5-.5v-2.4l4.1-3 3 1.9c.3.2.7.2.9-.1L16 12l3.5 3.4V19c0 .3-.2.5-.5.5z"})),p=window.wp.notices,w=e=>null==e||""===e,g=function({url:e="",caption:i="",alt:a="",setURLCaption:r}){const u=["image"],[m,g]=(0,t.useState)(null),[h,E]=(0,t.useState)(),{imageDefaultSize:x,mediaUpload:f}=((0,t.useRef)(),(0,l.useSelect)((e=>{const{getSettings:t}=e(o.store),n=t();return{imageDefaultSize:n.imageDefaultSize,mediaUpload:n.mediaUpload}}),[])),{createErrorNotice:_}=(0,l.useDispatch)(p.store);function q(e){_(e,{type:"snackbar"}),r(void 0,void 0),E(void 0)}function v(e){if(!e||!e.url)return void r(void 0,void 0);if((0,c.isBlobURL)(e.url))return void E(e.url);E();let t=((e,t)=>{const n=Object.fromEntries(Object.entries(null!=e?e:{}).filter((([e])=>["alt","id","link","caption"].includes(e))));return n.url=e?.sizes?.[t]?.url||e?.media_details?.sizes?.[t]?.source_url||e.url,n})(e,x);g(t.id),r(t.url,t.caption)}function b(t){t!==e&&r(t,i)}let z=((e,t)=>!e&&(0,c.isBlobURL)(t))(m,e);(0,t.useEffect)((()=>{if(!z)return;const t=(0,c.getBlobByURL)(e);t&&f({filesList:[t],onFileChange:([e])=>{v(e)},allowedTypes:u,onError:e=>{z=!1,q(e)}})}),[]),(0,t.useEffect)((()=>{z?E(e):(0,c.revokeBlobURL)(h)}),[z,e]);const R=((e,t)=>t&&!e&&!(0,c.isBlobURL)(t))(m,e)?e:void 0,B=!!e&&(0,t.createElement)("img",{alt:(0,n.__)("Edit image"),title:(0,n.__)("Edit image"),className:"edit-image-preview",src:e});let L=(0,t.createElement)(t.Fragment,null,(0,t.createElement)("img",{src:h||e,alt:"",className:"qsm-answer-option-image",style:{width:"200",height:"auto"}}),h&&(0,t.createElement)(s.Spinner,null));return(0,t.createElement)("figure",null,w(e)?(0,t.createElement)(o.MediaPlaceholder,{icon:(0,t.createElement)(o.BlockIcon,{icon:d}),onSelect:v,onSelectURL:b,onError:q,accept:"image/*",allowedTypes:u,value:{id:m,src:R},mediaPreview:B,disableMediaButtons:h||e}):(0,t.createElement)(t.Fragment,null,(0,t.createElement)(o.BlockControls,{group:"other"},(0,t.createElement)(o.MediaReplaceFlow,{mediaId:m,mediaURL:e,allowedTypes:u,accept:"image/*",onSelect:v,onSelectURL:b,onError:q})),(0,t.createElement)("div",null,L)))},h=JSON.parse('{"u2":"qsm/quiz-answer-option"}');(0,e.registerBlockType)(h.u2,{icon:()=>(0,t.createElement)(s.Icon,{icon:()=>(0,t.createElement)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,t.createElement)("rect",{width:"24",height:"24",rx:"4.21657",fill:"#ADADAD"}),(0,t.createElement)("path",{d:"M8.96182 17.2773H7.33619L10.9889 7.12707H12.7583L16.411 17.2773H14.7853L11.9157 8.97077H11.8364L8.96182 17.2773ZM9.23441 13.3025H14.5078V14.5911H9.23441V13.3025Z",fill:"white"}))}),__experimentalLabel(e,{context:t}){const{content:n}=e,i=e?.metadata?.name;if("list-view"===t&&(i||n?.length>0))return i||n},merge:(e,t)=>({content:(e.content||"")+(t.content||"")}),edit:function(c){if("undefined"==typeof qsmBlockData)return null;const{className:u,attributes:m,setAttributes:d,isSelected:p,clientId:h,context:E,mergeBlocks:x,onReplace:f,onRemove:_}=c,q=(E["quiz-master-next/quizID"],E["quiz-master-next/pageID"],E["quiz-master-next/questionID"],E["quiz-master-next/questionType"]),v=E["quiz-master-next/answerType"],b=E["quiz-master-next/questionChanged"],z="qsm/quiz-answer-option",{optionID:R,content:B,caption:L,points:k,isCorrect:S}=m,{selectBlock:C}=(0,l.useDispatch)(o.store),{updateBlockAttributes:y}=(0,l.useDispatch)(o.store),U=(0,l.useSelect)((e=>{let t=e(o.store).getBlockParentsByBlockName(h,"qsm/quiz-question",!0);return w(t)?"":t[0]}),[h]);(0,t.useEffect)((()=>{let e=!0;return e&&p&&!w(U)&&!1===b&&y(U,{isChanged:!0}),()=>{e=!1}}),[B,L,k,S]),(0,t.useEffect)((()=>{let e=!0;return e&&(w(B)||!(0,r.isURL)(B)||-1===B.indexOf("https://")&&-1===B.indexOf("http://")||!["rich","text"].includes(v)||d({content:"",caption:""})),()=>{e=!1}}),[v]);const A=(0,o.useBlockProps)({className:p?" is-highlighted ":""}),D=["4","10"].includes(q)?"checkbox":"radio";return(0,t.createElement)(t.Fragment,null,(0,t.createElement)(o.InspectorControls,null,(0,t.createElement)(s.PanelBody,{title:(0,n.__)("Settings","quiz-master-next"),initialOpen:!0},"image"===v&&(0,t.createElement)(s.TextControl,{type:"text",label:(0,n.__)("Caption","quiz-master-next"),value:L,onChange:e=>d({caption:(0,a.escapeAttribute)(e)})}),(0,t.createElement)(s.TextControl,{type:"number",label:(0,n.__)("Points","quiz-master-next"),help:(0,n.__)("Answer points","quiz-master-next"),value:k,onChange:e=>d({points:e})}),["0","4","1","10","2"].includes(q)&&(0,t.createElement)(s.ToggleControl,{label:(0,n.__)("Correct","quiz-master-next"),checked:!w(S)&&"1"==S,onChange:()=>d({isCorrect:w(S)||"1"!=S?1:0})}))),(0,t.createElement)("div",{...A},(0,t.createElement)(s.__experimentalHStack,{className:"edit-post-document-actions__title",spacing:1,justify:"left"},(0,t.createElement)("input",{type:D,disabled:!0,readOnly:!0,tabIndex:"-1"}),!["rich","image"].includes(v)&&(0,t.createElement)(o.RichText,{tagName:"p",title:(0,n.__)("Answer options","quiz-master-next"),"aria-label":(0,n.__)("Question answer","quiz-master-next"),placeholder:(0,n.__)("Your Answer","quiz-master-next"),value:(0,a.escapeAttribute)(B),onChange:e=>d({content:(0,a.escapeAttribute)(e)}),onSplit:(t,n)=>{let i;(n||t)&&(i={...m,content:t});const a=(0,e.createBlock)(z,i);return n&&(a.clientId=h),a},onMerge:x,onReplace:f,onRemove:_,allowedFormats:[],withoutInteractiveFormatting:!0,className:"qsm-question-answer-option",identifier:"text"}),"rich"===v&&(0,t.createElement)(o.RichText,{tagName:"p",title:(0,n.__)("Answer options","quiz-master-next"),"aria-label":(0,n.__)("Question answer","quiz-master-next"),placeholder:(0,n.__)("Your Answer","quiz-master-next"),value:(I=(0,i.decodeEntities)(B),T=document.createElement("textarea"),T.innerHTML=I,T.value),onChange:e=>d({content:e}),onSplit:(t,n)=>{let i;(n||t)&&(i={...m,content:t});const a=(0,e.createBlock)(z,i);return n&&(a.clientId=h),a},onMerge:x,onReplace:f,onRemove:_,className:"qsm-question-answer-option",identifier:"text",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),"image"===v&&(0,t.createElement)(g,{url:(0,r.isURL)(B)?B:"",caption:L,setURLCaption:(e,t)=>d({content:(0,r.isURL)(e)?e:"",caption:t})}))));var I,T}})})(); \ No newline at end of file
blocks/build/index.asset.php+2 −2 modified@@ -1,4 +1,4 @@ <?php return array( - 'dependencies' => array( 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-editor', 'wp-element', 'wp-html-entities', 'wp-i18n', 'wp-notices' ), - 'version' => '9ae62c1e6dbc6a16c846', + 'dependencies' => array( 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-editor', 'wp-element', 'wp-escape-html', 'wp-html-entities', 'wp-i18n', 'wp-notices' ), + 'version' => '194eb18b1a1c7b4d3601', );
blocks/build/index.js+1 −1 modified@@ -1 +1 @@ -(()=>{"use strict";var e,t={818:(e,t,n)=>{const a=window.wp.blocks,s=window.wp.element,i=window.wp.i18n,r=window.wp.apiFetch;var o=n.n(r);const l=window.wp.htmlEntities,u=window.wp.blockEditor,c=window.wp.notices,m=window.wp.data,p=window.wp.editor,d=window.wp.components,q=e=>null==e||""===e,g=e=>{var t=document.createElement("textarea");return t.innerHTML=e,t.value},_=e=>{let t=document.createElement("div");return t.innerHTML=g(e),t.innerText},h=(e=!1)=>{let t=new FormData;if(t.append("qsm_block_api_call","1"),!1!==e)for(let n in e)e.hasOwnProperty(n)&&t.append(n,e[n]);return t},z=e=>{let t="";const n=new Uint8Array(e);window.crypto.getRandomValues(n);for(let a=0;a<e;a++)t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[n[a]%62];return t},b=(e="",t=!1)=>`${e}${z(8)}${t?`.${z(7)}`:""}`,f=(e,t="")=>q(e)?t:e,v=()=>{};function w({className:e="",quizAttr:t,setAttributes:n,data:a,onChangeFunc:i=v}){var r,o,l,u,c;const m=(()=>{if(a.defaultvalue=a.default,!q(a?.options))switch(a.type){case"checkbox":1===a.options.length&&(a.type="toggle"),a.label=a.options[0].label;break;case"radio":1==a.options.length?(a.label=a.options[0].label,a.type="toggle"):a.type="select"}return a.label=q(a.label)?"":_(a.label),a.help=q(a.help)?"":_(a.help),a})(),{id:p,label:g="",type:h,help:z="",options:b=[],defaultvalue:f}=m;return(0,s.createElement)(s.Fragment,null,"toggle"===h&&(0,s.createElement)(d.ToggleControl,{label:g,help:z,checked:!q(t[p])&&"1"==t[p],onChange:()=>i(q(t[p])||"1"!=t[p]?1:0,p)}),"select"===h&&(0,s.createElement)(d.SelectControl,{label:g,value:null!==(r=t[p])&&void 0!==r?r:f,options:b,onChange:e=>i(e,p),help:z,__nextHasNoMarginBottom:!0}),"number"===h&&(0,s.createElement)(d.TextControl,{type:"number",label:g,value:null!==(o=t[p])&&void 0!==o?o:f,onChange:e=>i(e,p),help:z,__nextHasNoMarginBottom:!0}),"text"===h&&(0,s.createElement)(d.TextControl,{type:"text",label:g,value:null!==(l=t[p])&&void 0!==l?l:f,onChange:e=>i(e,p),help:z,__nextHasNoMarginBottom:!0}),"textarea"===h&&(0,s.createElement)(d.TextareaControl,{label:g,value:null!==(u=t[p])&&void 0!==u?u:f,onChange:e=>i(e,p),help:z,__nextHasNoMarginBottom:!0}),"checkbox"===h&&(0,s.createElement)(d.CheckboxControl,{label:g,help:z,checked:!q(t[p])&&"1"==t[p],onChange:()=>i(q(t[p])||"1"!=t[p]?1:0,p)}),"radio"===h&&(0,s.createElement)(d.RadioControl,{label:g,help:z,selected:null!==(c=t[p])&&void 0!==c?c:f,options:b,onChange:e=>i(e,p)}))}const E=()=>(0,s.createElement)(d.Icon,{icon:()=>(0,s.createElement)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,s.createElement)("rect",{width:"24",height:"24",rx:"3",fill:"black"}),(0,s.createElement)("path",{d:"M17.8146 17.8349C19.3188 16.3426 20.25 14.2793 20.25 12C20.2485 7.44425 16.5267 3.75 11.9348 3.75C7.34282 3.75 3.62109 7.44425 3.62109 12C3.62109 16.5558 7.34282 20.25 11.9348 20.25H18.9988C19.4682 20.25 19.7074 19.7112 19.3813 19.3885L17.8146 17.8334V17.8349ZM11.8753 17.5195C8.72666 17.5195 6.17388 15.0737 6.17388 12.0569C6.17388 9.04022 8.72666 6.59442 11.8753 6.59442C15.024 6.59442 17.5768 9.04022 17.5768 12.0569C17.5768 15.0737 15.024 17.5195 11.8753 17.5195Z",fill:"white"}))});window.wp.compose,(0,a.registerBlockType)("qsm/quiz",{icon:E,edit:function(e){if("undefined"==typeof qsmBlockData)return null;const{className:t,attributes:n,setAttributes:a,isSelected:r,clientId:_,context:z}=e,v=z.postId,{createNotice:y}=(0,m.useDispatch)(c.store),k=qsmBlockData.globalQuizsetting,{quizID:x,postID:D,quizAttr:I=k}=n,[C,B]=(0,s.useState)(qsmBlockData.QSMQuizList),[S,N]=(0,s.useState)({error:!1,msg:""}),[O,A]=(0,s.useState)(!1),[P,T]=(0,s.useState)(!1),[M,Q]=(0,s.useState)(!1),[H,F]=(0,s.useState)([]),j=qsmBlockData.quizOptions,L=(0,m.useSelect)((e=>{const{isAutosavingPost:t,isSavingPost:n}=e(p.store);return n()&&!t()}),[]),K=(0,m.useSelect)((e=>e("core/editor")),[]),{getBlock:R}=(0,m.useSelect)(u.store);(0,s.useEffect)((()=>{let e=!0;if(e&&("0"==qsmBlockData.is_pro_activated&&setTimeout((()=>{V()}),100),!q(x)&&0<x)){let e=!1;C.forEach((t=>{if(x==t.value)return e=!0,!0})),e?$(x):(a({quizID:void 0}),N({error:!0,msg:(0,i.__)("Quiz not found. Please select an existing quiz or create a new one.","quiz-master-next")}))}return()=>{e=!1}}),[]);const V=()=>{let e=document.getElementById("modal-advanced-question-type");q(e)&&o()({path:"/quiz-survey-master/v1/quiz/advance-ques-type-upgrade-popup",method:"POST"}).then((e=>{let t=document.getElementById("wpbody-content");q(t)||"success"!=e.status||t.insertAdjacentHTML("afterbegin",e.result)})).catch((e=>{console.log("error",e)}))},$=e=>{!q(e)&&0<e&&o()({path:"/quiz-survey-master/v1/quiz/structure",method:"POST",data:{quizID:e}}).then((t=>{if("success"==t.status){N({error:!1,msg:""});let n=t.result;if(a({quizID:parseInt(e),postID:n.post_id,quizAttr:{...I,...n}}),!q(n.qpages)){let e=[];n.qpages.forEach((t=>{let n=[];q(t.question_arr)||t.question_arr.forEach((e=>{if(!q(e)){let t=[];!q(e.answers)&&0<e.answers.length&&e.answers.forEach(((e,n)=>{t.push(["qsm/quiz-answer-option",{optionID:n,content:e[0],points:e[1],isCorrect:e[2],caption:f(e[3])}])})),n.push(["qsm/quiz-question",{questionID:e.question_id,type:e.question_type_new,answerEditor:e.settings.answerEditor,title:e.settings.question_title,description:e.question_name,required:e.settings.required,hint:e.hints,answers:e.answers,correctAnswerInfo:e.question_answer_info,category:e.category,multicategories:e.multicategories,commentBox:e.comments,matchAnswer:e.settings.matchAnswer,featureImageID:e.settings.featureImageID,featureImageSrc:e.settings.featureImageSrc,settings:e.settings},t])}})),e.push(["qsm/quiz-page",{pageID:t.id,pageKey:t.pagekey,hidePrevBtn:t.hide_prevbtn,quizID:t.quizID},n])})),F(e)}}else console.log("error "+t.msg)})).catch((e=>{console.log("error",e)}))},Z=(e,t)=>{let n=I;n[t]=e,a({quizAttr:{...n}})};(0,s.useEffect)((()=>{if(L){let e=(()=>{let e=R(_);if(q(e))return!1;e=e.innerBlocks;let t={quiz_id:I.quiz_id,post_id:I.post_id,quiz:{},pages:[],qpages:[],questions:[]},n=0;return e.forEach((e=>{if("qsm/quiz-page"===e.name){let a=e.attributes.pageID,s=[];!q(e.innerBlocks)&&0<e.innerBlocks.length&&e.innerBlocks.forEach((e=>{if("qsm/quiz-question"!==e.name)return!0;let a=e.attributes,i=f(a?.answerEditor,"text"),r=[];!q(e.innerBlocks)&&0<e.innerBlocks.length&&e.innerBlocks.forEach((e=>{if("qsm/quiz-answer-option"!==e.name)return!0;let t=e.attributes,n=f(t?.content);q(a?.answerEditor)||"rich"!==a.answerEditor||(n=g((0,l.decodeEntities)(n)));let s=[n,f(t?.points),f(t?.isCorrect)];"image"!==i||q(t?.caption)||s.push(t?.caption),r.push(s)})),s.push(a.questionID),a.isChanged&&t.questions.push({id:a.questionID,quizID:I.quiz_id,postID:I.post_id,answerEditor:i,type:f(a?.type,"0"),name:g(f(a?.description)),question_title:f(a?.title),answerInfo:g(f(a?.correctAnswerInfo)),comments:f(a?.commentBox,"1"),hint:f(a?.hint),category:f(a?.category),multicategories:f(a?.multicategories,[]),required:f(a?.required,0),answers:r,featureImageID:f(a?.featureImageID),featureImageSrc:f(a?.featureImageSrc),page:n,other_settings:{...f(a?.settings,{}),required:f(a?.required,0)}})})),t.pages.push(s),t.qpages.push({id:a,quizID:I.quiz_id,pagekey:q(e.attributes.pageKey)?b():e.attributes.pageKey,hide_prevbtn:e.attributes.hidePrevBtn,questions:s}),n++}})),t.quiz={quiz_name:I.quiz_name,quiz_id:I.quiz_id,post_id:I.post_id},M&&["form_type","system","timer_limit","pagination","enable_contact_form","enable_pagination_quiz","show_question_featured_image_in_result","progress_bar","require_log_in","disable_first_page","comment_section"].forEach((e=>{void 0!==I[e]&&null!==I[e]&&(t.quiz[e]=I[e])})),t})();T(!0);let t="publish";q(K)||(t=K.getEditedPostAttribute("status")),q(t)&&(t="publish"),e=h({save_entire_quiz:"1",quizData:JSON.stringify(e),qsm_block_quiz_nonce:qsmBlockData.nonce,page_post_id:q(v)?0:v,post_status:t,nonce:qsmBlockData.saveNonce}),o()({path:"/quiz-survey-master/v1/quiz/save_quiz",method:"POST",body:e}).then((e=>{y(e.status,e.msg,{isDismissible:!0,type:"snackbar"})})).catch((e=>{console.log("error",e),y("error",e.message,{isDismissible:!0,type:"snackbar"})}))}}),[L]);const J=(0,u.useBlockProps)(),U=(0,u.useInnerBlocksProps)(J,{template:H,allowedBlocks:["qsm/quiz-page"]});return(0,s.createElement)(s.Fragment,null,(0,s.createElement)(u.InspectorControls,null,(0,s.createElement)(d.PanelBody,{title:(0,i.__)("Quiz settings","quiz-master-next"),initialOpen:!0},(0,s.createElement)("label",{className:"qsm-inspector-label"},(0,i.__)("Status","quiz-master-next")+":",(0,s.createElement)("span",{className:"qsm-inspector-label-value"},I.post_status)),(0,s.createElement)(d.TextControl,{label:(0,i.__)("Quiz Name *","quiz-master-next"),help:(0,i.__)("Enter a name for this Quiz","quiz-master-next"),value:I?.quiz_name||"",onChange:e=>Z(e,"quiz_name"),className:"qsm-no-mb"}),(!q(x)||"0"!=x)&&(0,s.createElement)("p",null,(0,s.createElement)(d.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+x+"&tab=options"},(0,i.__)("Advance Quiz Settings","quiz-master-next"))))),q(x)||"0"==x?(0,s.createElement)("div",{...J}," ",(0,s.createElement)(d.Placeholder,{className:"qsm-placeholder-wrapper",icon:E,label:(0,i.__)("Quiz And Survey Master","quiz-master-next"),instructions:(0,i.__)("Easily and quickly add quizzes and surveys inside the block editor.","quiz-master-next")},(0,s.createElement)(s.Fragment,null,!q(C)&&0<C.length&&(0,s.createElement)("div",{className:"qsm-placeholder-select-create-quiz"},(0,s.createElement)(d.SelectControl,{label:(0,i.__)("","quiz-master-next"),value:x,options:C,onChange:e=>$(e),disabled:O,__nextHasNoMarginBottom:!0}),(0,s.createElement)("span",null,(0,i.__)("OR","quiz-master-next")),(0,s.createElement)(d.Button,{variant:"link",onClick:()=>A(!O)},(0,i.__)("Add New","quiz-master-next"))),(q(C)||O)&&(0,s.createElement)(d.__experimentalVStack,{spacing:"3",className:"qsm-placeholder-quiz-create-form"},(0,s.createElement)(d.TextControl,{label:(0,i.__)("Quiz Name *","quiz-master-next"),help:(0,i.__)("Enter a name for this Quiz","quiz-master-next"),value:I?.quiz_name||"",onChange:e=>Z(e,"quiz_name")}),(0,s.createElement)(d.Button,{variant:"link",onClick:()=>Q(!M)},(0,i.__)("Advance options","quiz-master-next")),(0,s.createElement)("div",{className:"qsm-advance-settings"},M&&j.map((e=>(0,s.createElement)(w,{key:"qsm-settings"+e.id,data:e,quizAttr:I,setAttributes:a,onChangeFunc:Z})))),(0,s.createElement)(d.Button,{variant:"primary",disabled:P||q(I.quiz_name),onClick:()=>(()=>{if(q(I.quiz_name))return void console.log("empty quiz_name");T(!0);let e=h({quiz_name:I.quiz_name,qsm_new_quiz_nonce:qsmBlockData.qsm_new_quiz_nonce});["form_type","system","timer_limit","pagination","enable_contact_form","enable_pagination_quiz","show_question_featured_image_in_result","progress_bar","require_log_in","disable_first_page","comment_section"].forEach((t=>void 0===I[t]||null===I[t]?"":e.append(t,I[t]))),o()({path:"/quiz-survey-master/v1/quiz/create_quiz",method:"POST",body:e}).then((e=>{if(T(!1),"success"==e.status){let t=h({id:null,quizID:e.quizID,answerEditor:"text",type:"0",name:"",question_title:"",answerInfo:"",comments:"1",hint:"",category:"",required:0,answers:[],page:0});o()({path:"/quiz-survey-master/v1/questions",method:"POST",body:t}).then((t=>{if("success"==t.status){let n=t.id,a=h({action:qsmBlockData.save_pages_action,quiz_id:e.quizID,nonce:qsmBlockData.saveNonce,post_id:e.quizPostID});a.append("pages[0][]",n),a.append("qpages[0][id]",1),a.append("qpages[0][quizID]",e.quizID),a.append("qpages[0][pagekey]",b()),a.append("qpages[0][hide_prevbtn]",0),a.append("qpages[0][questions][]",n),o()({url:qsmBlockData.ajax_url,method:"POST",body:a}).then((t=>{"success"==t.status&&$(e.quizID)}))}})).catch((e=>{console.log("error",e),y("error",e.message,{isDismissible:!0,type:"snackbar"})}))}y(e.status,e.msg,{isDismissible:!0,type:"snackbar"})})).catch((e=>{console.log("error",e),y("error",e.message,{isDismissible:!0,type:"snackbar"})}))})()},(0,i.__)("Create Quiz","quiz-master-next"))),S.error&&(0,s.createElement)("p",{className:"qsm-error-text"},S.msg)))," "):(0,s.createElement)("div",{...U}))},save:e=>null})}},n={};function a(e){var s=n[e];if(void 0!==s)return s.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,a),i.exports}a.m=t,e=[],a.O=(t,n,s,i)=>{if(!n){var r=1/0;for(c=0;c<e.length;c++){for(var[n,s,i]=e[c],o=!0,l=0;l<n.length;l++)(!1&i||r>=i)&&Object.keys(a.O).every((e=>a.O[e](n[l])))?n.splice(l--,1):(o=!1,i<r&&(r=i));if(o){e.splice(c--,1);var u=s();void 0!==u&&(t=u)}}return t}i=i||0;for(var c=e.length;c>0&&e[c-1][2]>i;c--)e[c]=e[c-1];e[c]=[n,s,i]},a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={826:0,431:0};a.O.j=t=>0===e[t];var t=(t,n)=>{var s,i,[r,o,l]=n,u=0;if(r.some((t=>0!==e[t]))){for(s in o)a.o(o,s)&&(a.m[s]=o[s]);if(l)var c=l(a)}for(t&&t(n);u<r.length;u++)i=r[u],a.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return a.O(c)},n=globalThis.webpackChunkqsm=globalThis.webpackChunkqsm||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})();var s=a.O(void 0,[431],(()=>a(818)));s=a.O(s)})(); \ No newline at end of file +(()=>{"use strict";var e,t={550:(e,t,n)=>{const a=window.wp.blocks,s=window.wp.element,i=window.wp.i18n,r=window.wp.apiFetch;var o=n.n(r);const l=window.wp.htmlEntities,u=window.wp.blockEditor,c=window.wp.notices,m=window.wp.data,p=window.wp.editor,d=window.wp.components,q=e=>null==e||""===e,g=e=>{var t=document.createElement("textarea");return t.innerHTML=e,t.value},_=(e=!1)=>{let t=new FormData;if(t.append("qsm_block_api_call","1"),!1!==e)for(let n in e)e.hasOwnProperty(n)&&t.append(n,e[n]);return t},h=e=>{let t="";const n=new Uint8Array(e);window.crypto.getRandomValues(n);for(let a=0;a<e;a++)t+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"[n[a]%62];return t},z=(e="",t=!1)=>`${e}${h(8)}${t?`.${h(7)}`:""}`,b=(e,t="")=>q(e)?t:e,w=window.wp.escapeHtml,f=()=>{};function v({className:e="",quizAttr:t,setAttributes:n,data:a,onChangeFunc:i=f}){var r,o,l,u,c;const m=(()=>{if(a.defaultvalue=a.default,!q(a?.options))switch(a.type){case"checkbox":1===a.options.length&&(a.type="toggle"),a.label=a.options[0].label;break;case"radio":1==a.options.length?(a.label=a.options[0].label,a.type="toggle"):a.type="select"}return a.label=q(a.label)?"":(0,w.escapeAttribute)(a.label),a.help=q(a.help)?"":(0,w.escapeAttribute)(a.help),a})(),{id:p,label:g="",type:_,help:h="",options:z=[],defaultvalue:b}=m;return(0,s.createElement)(s.Fragment,null,"toggle"===_&&(0,s.createElement)(d.ToggleControl,{label:g,help:h,checked:!q(t[p])&&"1"==t[p],onChange:()=>i(q(t[p])||"1"!=t[p]?1:0,p)}),"select"===_&&(0,s.createElement)(d.SelectControl,{label:g,value:null!==(r=t[p])&&void 0!==r?r:b,options:z,onChange:e=>i(e,p),help:h,__nextHasNoMarginBottom:!0}),"number"===_&&(0,s.createElement)(d.TextControl,{type:"number",label:g,value:null!==(o=t[p])&&void 0!==o?o:b,onChange:e=>i(e,p),help:h,__nextHasNoMarginBottom:!0}),"text"===_&&(0,s.createElement)(d.TextControl,{type:"text",label:g,value:null!==(l=t[p])&&void 0!==l?l:b,onChange:e=>i(e,p),help:h,__nextHasNoMarginBottom:!0}),"textarea"===_&&(0,s.createElement)(d.TextareaControl,{label:g,value:null!==(u=t[p])&&void 0!==u?u:b,onChange:e=>i(e,p),help:h,__nextHasNoMarginBottom:!0}),"checkbox"===_&&(0,s.createElement)(d.CheckboxControl,{label:g,help:h,checked:!q(t[p])&&"1"==t[p],onChange:()=>i(q(t[p])||"1"!=t[p]?1:0,p)}),"radio"===_&&(0,s.createElement)(d.RadioControl,{label:g,help:h,selected:null!==(c=t[p])&&void 0!==c?c:b,options:z,onChange:e=>i(e,p)}))}const y=()=>(0,s.createElement)(d.Icon,{icon:()=>(0,s.createElement)("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,s.createElement)("rect",{width:"24",height:"24",rx:"3",fill:"black"}),(0,s.createElement)("path",{d:"M17.8146 17.8349C19.3188 16.3426 20.25 14.2793 20.25 12C20.2485 7.44425 16.5267 3.75 11.9348 3.75C7.34282 3.75 3.62109 7.44425 3.62109 12C3.62109 16.5558 7.34282 20.25 11.9348 20.25H18.9988C19.4682 20.25 19.7074 19.7112 19.3813 19.3885L17.8146 17.8334V17.8349ZM11.8753 17.5195C8.72666 17.5195 6.17388 15.0737 6.17388 12.0569C6.17388 9.04022 8.72666 6.59442 11.8753 6.59442C15.024 6.59442 17.5768 9.04022 17.5768 12.0569C17.5768 15.0737 15.024 17.5195 11.8753 17.5195Z",fill:"white"}))});window.wp.compose,(0,a.registerBlockType)("qsm/quiz",{icon:y,edit:function(e){if("undefined"==typeof qsmBlockData)return null;const{className:t,attributes:n,setAttributes:a,isSelected:r,clientId:h,context:w}=e,f=w.postId,{createNotice:E}=(0,m.useDispatch)(c.store),k=qsmBlockData.globalQuizsetting,{quizID:x,postID:D,quizAttr:I=k}=n,[C,B]=(0,s.useState)(qsmBlockData.QSMQuizList),[S,A]=(0,s.useState)({error:!1,msg:""}),[N,O]=(0,s.useState)(!1),[P,T]=(0,s.useState)(!1),[M,Q]=(0,s.useState)(!1),[H,F]=(0,s.useState)([]),j=qsmBlockData.quizOptions,L=(0,m.useSelect)((e=>{const{isAutosavingPost:t,isSavingPost:n}=e(p.store);return n()&&!t()}),[]),K=(0,m.useSelect)((e=>e("core/editor")),[]),{getBlock:R}=(0,m.useSelect)(u.store);(0,s.useEffect)((()=>{let e=!0;if(e&&("0"==qsmBlockData.is_pro_activated&&setTimeout((()=>{V()}),100),!q(x)&&0<x)){let e=!1;C.forEach((t=>{if(x==t.value)return e=!0,!0})),e?$(x):(a({quizID:void 0}),A({error:!0,msg:(0,i.__)("Quiz not found. Please select an existing quiz or create a new one.","quiz-master-next")}))}return()=>{e=!1}}),[]);const V=()=>{let e=document.getElementById("modal-advanced-question-type");q(e)&&o()({path:"/quiz-survey-master/v1/quiz/advance-ques-type-upgrade-popup",method:"POST"}).then((e=>{let t=document.getElementById("wpbody-content");q(t)||"success"!=e.status||t.insertAdjacentHTML("afterbegin",e.result)})).catch((e=>{console.log("error",e)}))},$=e=>{!q(e)&&0<e&&o()({path:"/quiz-survey-master/v1/quiz/structure",method:"POST",data:{quizID:e}}).then((t=>{if("success"==t.status){A({error:!1,msg:""});let n=t.result;if(a({quizID:parseInt(e),postID:n.post_id,quizAttr:{...I,...n}}),!q(n.qpages)){let e=[];n.qpages.forEach((t=>{let n=[];q(t.question_arr)||t.question_arr.forEach((e=>{if(!q(e)){let t=[];!q(e.answers)&&0<e.answers.length&&e.answers.forEach(((e,n)=>{t.push(["qsm/quiz-answer-option",{optionID:n,content:e[0],points:e[1],isCorrect:e[2],caption:b(e[3])}])})),n.push(["qsm/quiz-question",{questionID:e.question_id,type:e.question_type_new,answerEditor:e.settings.answerEditor,title:e.settings.question_title,description:e.question_name,required:e.settings.required,hint:e.hints,answers:e.answers,correctAnswerInfo:e.question_answer_info,category:e.category,multicategories:e.multicategories,commentBox:e.comments,matchAnswer:e.settings.matchAnswer,featureImageID:e.settings.featureImageID,featureImageSrc:e.settings.featureImageSrc,settings:e.settings},t])}})),e.push(["qsm/quiz-page",{pageID:t.id,pageKey:t.pagekey,hidePrevBtn:t.hide_prevbtn,quizID:t.quizID},n])})),F(e)}}else console.log("error "+t.msg)})).catch((e=>{console.log("error",e)}))},Z=(e,t)=>{let n=I;n[t]=e,a({quizAttr:{...n}})};(0,s.useEffect)((()=>{if(L){let e=(()=>{let e=R(h);if(q(e))return!1;e=e.innerBlocks;let t={quiz_id:I.quiz_id,post_id:I.post_id,quiz:{},pages:[],qpages:[],questions:[]},n=0;return e.forEach((e=>{if("qsm/quiz-page"===e.name){let a=e.attributes.pageID,s=[];!q(e.innerBlocks)&&0<e.innerBlocks.length&&e.innerBlocks.forEach((e=>{if("qsm/quiz-question"!==e.name)return!0;let a=e.attributes,i=b(a?.answerEditor,"text"),r=[];!q(e.innerBlocks)&&0<e.innerBlocks.length&&e.innerBlocks.forEach((e=>{if("qsm/quiz-answer-option"!==e.name)return!0;let t=e.attributes,n=b(t?.content);q(a?.answerEditor)||"rich"!==a.answerEditor||(n=g((0,l.decodeEntities)(n)));let s=[n,b(t?.points),b(t?.isCorrect)];"image"!==i||q(t?.caption)||s.push(t?.caption),r.push(s)})),s.push(a.questionID),a.isChanged&&t.questions.push({id:a.questionID,quizID:I.quiz_id,postID:I.post_id,answerEditor:i,type:b(a?.type,"0"),name:g(b(a?.description)),question_title:b(a?.title),answerInfo:g(b(a?.correctAnswerInfo)),comments:b(a?.commentBox,"1"),hint:b(a?.hint),category:b(a?.category),multicategories:b(a?.multicategories,[]),required:b(a?.required,0),answers:r,featureImageID:b(a?.featureImageID),featureImageSrc:b(a?.featureImageSrc),page:n,other_settings:{...b(a?.settings,{}),required:b(a?.required,0)}})})),t.pages.push(s),t.qpages.push({id:a,quizID:I.quiz_id,pagekey:q(e.attributes.pageKey)?z():e.attributes.pageKey,hide_prevbtn:e.attributes.hidePrevBtn,questions:s}),n++}})),t.quiz={quiz_name:I.quiz_name,quiz_id:I.quiz_id,post_id:I.post_id},M&&["form_type","system","timer_limit","pagination","enable_contact_form","enable_pagination_quiz","show_question_featured_image_in_result","progress_bar","require_log_in","disable_first_page","comment_section"].forEach((e=>{void 0!==I[e]&&null!==I[e]&&(t.quiz[e]=I[e])})),t})();T(!0);let t="publish";q(K)||(t=K.getEditedPostAttribute("status")),q(t)&&(t="publish"),e=_({save_entire_quiz:"1",quizData:JSON.stringify(e),qsm_block_quiz_nonce:qsmBlockData.nonce,page_post_id:q(f)?0:f,post_status:t,nonce:qsmBlockData.saveNonce}),o()({path:"/quiz-survey-master/v1/quiz/save_quiz",method:"POST",body:e}).then((e=>{E(e.status,e.msg,{isDismissible:!0,type:"snackbar"})})).catch((e=>{console.log("error",e),E("error",e.message,{isDismissible:!0,type:"snackbar"})}))}}),[L]);const J=(0,u.useBlockProps)(),U=(0,u.useInnerBlocksProps)(J,{template:H,allowedBlocks:["qsm/quiz-page"]});return(0,s.createElement)(s.Fragment,null,(0,s.createElement)(u.InspectorControls,null,(0,s.createElement)(d.PanelBody,{title:(0,i.__)("Quiz settings","quiz-master-next"),initialOpen:!0},(0,s.createElement)("label",{className:"qsm-inspector-label"},(0,i.__)("Status","quiz-master-next")+":",(0,s.createElement)("span",{className:"qsm-inspector-label-value"},I.post_status)),(0,s.createElement)(d.TextControl,{label:(0,i.__)("Quiz Name *","quiz-master-next"),help:(0,i.__)("Enter a name for this Quiz","quiz-master-next"),value:I?.quiz_name||"",onChange:e=>Z(e,"quiz_name"),className:"qsm-no-mb"}),(!q(x)||"0"!=x)&&(0,s.createElement)("p",null,(0,s.createElement)(d.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+x+"&tab=options"},(0,i.__)("Advance Quiz Settings","quiz-master-next"))))),q(x)||"0"==x?(0,s.createElement)("div",{...J}," ",(0,s.createElement)(d.Placeholder,{className:"qsm-placeholder-wrapper",icon:y,label:(0,i.__)("Quiz And Survey Master","quiz-master-next"),instructions:(0,i.__)("Easily and quickly add quizzes and surveys inside the block editor.","quiz-master-next")},(0,s.createElement)(s.Fragment,null,!q(C)&&0<C.length&&(0,s.createElement)("div",{className:"qsm-placeholder-select-create-quiz"},(0,s.createElement)(d.SelectControl,{label:(0,i.__)("","quiz-master-next"),value:x,options:C,onChange:e=>$(e),disabled:N,__nextHasNoMarginBottom:!0}),(0,s.createElement)("span",null,(0,i.__)("OR","quiz-master-next")),(0,s.createElement)(d.Button,{variant:"link",onClick:()=>O(!N)},(0,i.__)("Add New","quiz-master-next"))),(q(C)||N)&&(0,s.createElement)(d.__experimentalVStack,{spacing:"3",className:"qsm-placeholder-quiz-create-form"},(0,s.createElement)(d.TextControl,{label:(0,i.__)("Quiz Name *","quiz-master-next"),help:(0,i.__)("Enter a name for this Quiz","quiz-master-next"),value:I?.quiz_name||"",onChange:e=>Z(e,"quiz_name")}),(0,s.createElement)(d.Button,{variant:"link",onClick:()=>Q(!M)},(0,i.__)("Advance options","quiz-master-next")),(0,s.createElement)("div",{className:"qsm-advance-settings"},M&&j.map((e=>(0,s.createElement)(v,{key:"qsm-settings"+e.id,data:e,quizAttr:I,setAttributes:a,onChangeFunc:Z})))),(0,s.createElement)(d.Button,{variant:"primary",disabled:P||q(I.quiz_name),onClick:()=>(()=>{if(q(I.quiz_name))return void console.log("empty quiz_name");T(!0);let e=_({quiz_name:I.quiz_name,qsm_new_quiz_nonce:qsmBlockData.qsm_new_quiz_nonce});["form_type","system","timer_limit","pagination","enable_contact_form","enable_pagination_quiz","show_question_featured_image_in_result","progress_bar","require_log_in","disable_first_page","comment_section"].forEach((t=>void 0===I[t]||null===I[t]?"":e.append(t,I[t]))),o()({path:"/quiz-survey-master/v1/quiz/create_quiz",method:"POST",body:e}).then((e=>{if(T(!1),"success"==e.status){let t=_({id:null,quizID:e.quizID,answerEditor:"text",type:"0",name:"",question_title:"",answerInfo:"",comments:"1",hint:"",category:"",required:0,answers:[],page:0});o()({path:"/quiz-survey-master/v1/questions",method:"POST",body:t}).then((t=>{if("success"==t.status){let n=t.id,a=_({action:qsmBlockData.save_pages_action,quiz_id:e.quizID,nonce:qsmBlockData.saveNonce,post_id:e.quizPostID});a.append("pages[0][]",n),a.append("qpages[0][id]",1),a.append("qpages[0][quizID]",e.quizID),a.append("qpages[0][pagekey]",z()),a.append("qpages[0][hide_prevbtn]",0),a.append("qpages[0][questions][]",n),o()({url:qsmBlockData.ajax_url,method:"POST",body:a}).then((t=>{"success"==t.status&&$(e.quizID)}))}})).catch((e=>{console.log("error",e),E("error",e.message,{isDismissible:!0,type:"snackbar"})}))}E(e.status,e.msg,{isDismissible:!0,type:"snackbar"})})).catch((e=>{console.log("error",e),E("error",e.message,{isDismissible:!0,type:"snackbar"})}))})()},(0,i.__)("Create Quiz","quiz-master-next"))),S.error&&(0,s.createElement)("p",{className:"qsm-error-text"},S.msg)))," "):(0,s.createElement)("div",{...U}))},save:e=>null})}},n={};function a(e){var s=n[e];if(void 0!==s)return s.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,a),i.exports}a.m=t,e=[],a.O=(t,n,s,i)=>{if(!n){var r=1/0;for(c=0;c<e.length;c++){for(var[n,s,i]=e[c],o=!0,l=0;l<n.length;l++)(!1&i||r>=i)&&Object.keys(a.O).every((e=>a.O[e](n[l])))?n.splice(l--,1):(o=!1,i<r&&(r=i));if(o){e.splice(c--,1);var u=s();void 0!==u&&(t=u)}}return t}i=i||0;for(var c=e.length;c>0&&e[c-1][2]>i;c--)e[c]=e[c-1];e[c]=[n,s,i]},a.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return a.d(t,{a:t}),t},a.d=(e,t)=>{for(var n in t)a.o(t,n)&&!a.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},a.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={826:0,431:0};a.O.j=t=>0===e[t];var t=(t,n)=>{var s,i,[r,o,l]=n,u=0;if(r.some((t=>0!==e[t]))){for(s in o)a.o(o,s)&&(a.m[s]=o[s]);if(l)var c=l(a)}for(t&&t(n);u<r.length;u++)i=r[u],a.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return a.O(c)},n=globalThis.webpackChunkqsm=globalThis.webpackChunkqsm||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})();var s=a.O(void 0,[431],(()=>a(550)));s=a.O(s)})(); \ No newline at end of file
blocks/build/question/index.asset.php+2 −2 modified@@ -1,4 +1,4 @@ <?php return array( - 'dependencies' => array( 'wp-api-fetch', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices' ), - 'version' => '45906d9cb21e070d8451', + 'dependencies' => array( 'wp-api-fetch', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-escape-html', 'wp-hooks', 'wp-i18n', 'wp-notices' ), + 'version' => '5e548fd7e3646043ca1e', );
blocks/build/question/index.js+2 −2 modified@@ -1,5 +1,5 @@ -(()=>{"use strict";var e={n:t=>{var a=t&&t.__esModule?()=>t.default:()=>t;return e.d(a,{a}),a},d:(t,a)=>{for(var n in a)e.o(a,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:a[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.blocks,a=window.wp.element,n=window.wp.i18n,r=window.wp.apiFetch;var l=e.n(r);const i=window.wp.blockEditor,o=window.wp.notices,s=window.wp.data,c=window.wp.components,m=(window.wp.hooks,window.wp.blob),u=window.wp.coreData,d=e=>null==e||""===e,_=e=>d(e)||!Array.isArray(e)?e:e.filter(((e,t,a)=>a.indexOf(e)===t)),p=e=>{var t=document.createElement("textarea");return t.innerHTML=e,t.value},g=e=>{let t=document.createElement("div");return t.innerHTML=p(e),t.innerText},h=(e=!1)=>{let t=new FormData;if(t.append("qsm_block_api_call","1"),!1!==e)for(let a in e)e.hasOwnProperty(a)&&t.append(a,e[a]);return t},q=(e,t="")=>d(e)?t:e,E=["image"],f=(0,n.__)("Featured image"),w=(0,n.__)("Set featured image"),x=(0,a.createElement)("p",null,(0,n.__)("To edit the featured image, you need permission to upload media.")),C=({featureImageID:e,onUpdateImage:t,onRemoveImage:r})=>{const{createNotice:l}=(0,s.useDispatch)(o.store),_=(0,a.useRef)(),[p,g]=(0,a.useState)(!1),[h,q]=(0,a.useState)(void 0),{mediaFeature:C,mediaUpload:b}=(0,s.useSelect)((t=>{const{getMedia:a}=t(u.store);return{mediaFeature:d(h)&&!d(e)&&a(e),mediaUpload:t(i.store).getSettings().mediaUpload}}),[]);function y(e){b({allowedTypes:["image"],filesList:e,onFileChange([e]){(0,m.isBlobURL)(e?.url)?g(!0):(t(e),g(!1))},onError(e){l("error",e,{isDismissible:!0,type:"snackbar"})}})}return(0,a.useEffect)((()=>{let t=!0;return t&&(d(C)||"object"!=typeof C||q({id:e,width:C.media_details.width,height:C.media_details.height,url:C.source_url,alt_text:C.alt_text,slug:C.slug})),()=>{t=!1}}),[C]),(0,a.createElement)("div",{className:"editor-post-featured-image"},h&&(0,a.createElement)("div",{id:`editor-post-featured-image-${e}-describedby`,className:"hidden"},h.alt_text&&(0,n.sprintf)( +(()=>{"use strict";var e={n:t=>{var a=t&&t.__esModule?()=>t.default:()=>t;return e.d(a,{a}),a},d:(t,a)=>{for(var n in a)e.o(a,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:a[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.blocks,a=window.wp.element,n=window.wp.i18n,r=window.wp.escapeHtml,l=window.wp.apiFetch;var i=e.n(l);const o=window.wp.blockEditor,s=window.wp.notices,c=window.wp.data,m=window.wp.components,u=(window.wp.hooks,window.wp.blob),d=window.wp.coreData,p=e=>null==e||""===e,_=e=>p(e)||!Array.isArray(e)?e:e.filter(((e,t,a)=>a.indexOf(e)===t)),g=e=>{var t=document.createElement("textarea");return t.innerHTML=e,t.value},h=(e=!1)=>{let t=new FormData;if(t.append("qsm_block_api_call","1"),!1!==e)for(let a in e)e.hasOwnProperty(a)&&t.append(a,e[a]);return t},q=(e,t="")=>p(e)?t:e,E=["image"],f=(0,n.__)("Featured image"),w=(0,n.__)("Set featured image"),x=(0,a.createElement)("p",null,(0,n.__)("To edit the featured image, you need permission to upload media.")),C=({featureImageID:e,onUpdateImage:t,onRemoveImage:r})=>{const{createNotice:l}=(0,c.useDispatch)(s.store),i=(0,a.useRef)(),[_,g]=(0,a.useState)(!1),[h,q]=(0,a.useState)(void 0),{mediaFeature:C,mediaUpload:b}=(0,c.useSelect)((t=>{const{getMedia:a}=t(d.store);return{mediaFeature:p(h)&&!p(e)&&a(e),mediaUpload:t(o.store).getSettings().mediaUpload}}),[]);function y(e){b({allowedTypes:["image"],filesList:e,onFileChange([e]){(0,u.isBlobURL)(e?.url)?g(!0):(t(e),g(!1))},onError(e){l("error",e,{isDismissible:!0,type:"snackbar"})}})}return(0,a.useEffect)((()=>{let t=!0;return t&&(p(C)||"object"!=typeof C||q({id:e,width:C.media_details.width,height:C.media_details.height,url:C.source_url,alt_text:C.alt_text,slug:C.slug})),()=>{t=!1}}),[C]),(0,a.createElement)("div",{className:"editor-post-featured-image"},h&&(0,a.createElement)("div",{id:`editor-post-featured-image-${e}-describedby`,className:"hidden"},h.alt_text&&(0,n.sprintf)( // Translators: %s: The selected image alt text. (0,n.__)("Current image: %s"),h.alt_text),!h.alt_text&&(0,n.sprintf)( // Translators: %s: The selected image filename. -(0,n.__)("The current image has no alternative text. The file name is: %s"),h.slug)),(0,a.createElement)(i.MediaUploadCheck,{fallback:x},(0,a.createElement)(i.MediaUpload,{title:f,onSelect:e=>{q(e),t(e)},unstableFeaturedImageFlow:!0,allowedTypes:E,modalClass:"editor-post-featured-image__media-modal",render:({open:t})=>(0,a.createElement)("div",{className:"editor-post-featured-image__container"},(0,a.createElement)(c.Button,{ref:_,className:e?"editor-post-featured-image__preview":"editor-post-featured-image__toggle",onClick:t,"aria-label":e?(0,n.__)("Edit or replace the image"):null,"aria-describedby":e?`editor-post-featured-image-${e}-describedby`:null},!!e&&h&&(0,a.createElement)(c.ResponsiveWrapper,{naturalWidth:h.width,naturalHeight:h.height,isInline:!0},(0,a.createElement)("img",{src:h.url,alt:h.alt_text})),p&&(0,a.createElement)(c.Spinner,null),!e&&!p&&w),!!e&&(0,a.createElement)(c.__experimentalHStack,{className:"editor-post-featured-image__actions"},(0,a.createElement)(c.Button,{className:"editor-post-featured-image__action",onClick:t,"aria-hidden":"true"},(0,n.__)("Replace")),(0,a.createElement)(c.Button,{className:"editor-post-featured-image__action",onClick:()=>{r(),_.current.focus()}},(0,n.__)("Remove"))),(0,a.createElement)(c.DropZone,{onFilesDrop:y})),value:e})))},b=({isCategorySelected:e,setUnsetCatgory:t})=>{const[r,i]=(0,a.useState)(!1),[o,s]=(0,a.useState)(""),[m,u]=(0,a.useState)(0),[_,p]=(0,a.useState)(!1),[g,q]=(0,a.useState)(!1),[E,f]=(0,a.useState)(qsmBlockData?.hierarchicalCategoryList),w=e=>{let t={};return e.forEach((e=>{if(t[e.id]=e,0<e.children.length){let a=w(e.children);t={...t,...a}}})),t},[x,C]=(0,a.useState)(d(qsmBlockData?.hierarchicalCategoryList)?{}:w(qsmBlockData.hierarchicalCategoryList)),b=(0,n.__)("Add New Category ","quiz-master-next"),y=`— ${(0,n.__)("Parent Category ","quiz-master-next")} —`,k=e=>{let t=[];return e.forEach((e=>{if(t.push(e.name),0<e.children.length){let a=k(e.children);t=[...t,...a]}})),t},v=n=>n.map((n=>(0,a.createElement)("div",{key:n.id,className:"editor-post-taxonomies__hierarchical-terms-choice"},(0,a.createElement)(c.CheckboxControl,{label:n.name,checked:e(n.id),onChange:()=>t(n.id,x)}),!!n.children.length&&(0,a.createElement)("div",{className:"editor-post-taxonomies__hierarchical-terms-subchoices"},v(n.children)))));return(0,a.createElement)(c.PanelBody,{title:(0,n.__)("Categories","quiz-master-next"),initialOpen:!0},(0,a.createElement)("div",{className:"editor-post-taxonomies__hierarchical-terms-list",tabIndex:"0",role:"group","aria-label":(0,n.__)("Categories","quiz-master-next")},v(E)),(0,a.createElement)("div",{className:"qsm-ptb-1"},(0,a.createElement)(c.Button,{variant:"link",onClick:()=>i(!r)},b)),r&&(0,a.createElement)("form",{onSubmit:async e=>{e.preventDefault(),g||d(o)||_||(p(!0),l()({url:qsmBlockData.ajax_url,method:"POST",body:h({action:"save_new_category",name:o,parent:m})}).then((e=>{if(!d(e.term_id)){let a=e.term_id;l()({path:"/quiz-survey-master/v1/quiz/hierarchical-category-list",method:"POST"}).then((e=>{"success"==e.status&&(f(e.result),C(e.result),s(""),u(0),t(a,w(term.id)),p(!1))}))}})))}},(0,a.createElement)(c.Flex,{direction:"column",gap:"1"},(0,a.createElement)(c.TextControl,{__nextHasNoMarginBottom:!0,className:"editor-post-taxonomies__hierarchical-terms-input",label:(0,n.__)("Category Name","quiz-master-next"),value:o,onChange:e=>((e,t)=>{t=k(t),console.log("categories",t),t.includes(e)?q(e):(q(!1),s(e))})(e,E),required:!0}),0<E.length&&(0,a.createElement)(c.TreeSelect,{__nextHasNoMarginBottom:!0,label:(0,n.__)("Parent Category","quiz-master-next"),noOptionLabel:y,onChange:e=>u(e),selectedId:m,tree:E}),(0,a.createElement)(c.FlexItem,null,(0,a.createElement)(c.Button,{variant:"secondary",type:"submit",className:"editor-post-taxonomies__hierarchical-terms-submit",disabled:g||_},b)),(0,a.createElement)(c.FlexItem,null,(0,a.createElement)("p",{className:"qsm-error-text"},!1!==g&&(0,n.__)("Category ","quiz-master-next")+g+(0,n.__)(" already exists.","quiz-master-next"))))))},y=()=>(0,a.createElement)(c.Icon,{icon:()=>(0,a.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false"},(0,a.createElement)("path",{d:"M18 11.2h-5.2V6h-1.6v5.2H6v1.6h5.2V18h1.6v-5.2H18z"}))}),k=JSON.parse('{"u2":"qsm/quiz-question"}');(0,t.registerBlockType)(k.u2,{icon:()=>(0,a.createElement)(c.Icon,{icon:()=>(0,a.createElement)("svg",{width:"25",height:"25",viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,a.createElement)("rect",{x:"0.102539",y:"0.101562",width:"24",height:"24",rx:"4.68852",fill:"#ADADAD"}),(0,a.createElement)("path",{d:"M17.0475 17.191C17.2367 17.3683 17.3313 17.5752 17.3313 17.8117C17.3313 18.06 17.2426 18.2787 17.0653 18.4679C16.8879 18.6453 16.6751 18.734 16.4268 18.734C16.1667 18.734 15.9538 18.6512 15.7883 18.4857L14.937 17.6521C13.8492 18.4088 12.5959 18.7872 11.177 18.7872C10.0301 18.7872 9.01325 18.533 8.12646 18.0245C7.2515 17.5161 6.57163 16.8126 6.08685 15.914C5.6139 15.0035 5.37742 13.9631 5.37742 12.7925C5.37742 11.5273 5.64937 10.41 6.19327 9.44044C6.74898 8.45907 7.48206 7.70234 8.3925 7.17027C9.31475 6.6382 10.308 6.37216 11.3721 6.37216C12.4481 6.37216 13.459 6.64411 14.4049 7.18801C15.3508 7.72008 16.1075 8.46498 16.6751 9.42271C17.2426 10.3804 17.5264 11.4505 17.5264 12.6329C17.5264 14.0636 17.1007 15.3287 16.2494 16.4283L17.0475 17.191ZM11.177 17.1732C12.0874 17.1732 12.9269 16.9249 13.6955 16.4283L12.5604 15.311C12.3949 15.1454 12.3121 14.9799 12.3121 14.8144C12.3121 14.6015 12.4244 14.3887 12.6491 14.1759C12.8855 13.9631 13.122 13.8566 13.3585 13.8566C13.5122 13.8566 13.6364 13.9039 13.7309 13.9985L14.9724 15.1868C15.4927 14.4183 15.7528 13.5492 15.7528 12.5797C15.7528 11.7284 15.5518 10.9539 15.1498 10.2563C14.7596 9.54686 14.2335 8.99114 13.5713 8.58913C12.9092 8.18712 12.1998 7.98611 11.443 7.98611C10.6981 7.98611 9.99462 8.18121 9.33249 8.57139C8.67036 8.94975 8.13828 9.49956 7.73627 10.2208C7.34609 10.9421 7.15099 11.7756 7.15099 12.7216C7.15099 13.6083 7.32244 14.3887 7.66533 15.0627C8.02005 15.7366 8.49891 16.2569 9.10192 16.6234C9.71676 16.99 10.4085 17.1732 11.177 17.1732Z",fill:"white"}))}),edit:function(e){var r;if("undefined"==typeof qsmBlockData)return null;const{className:m,attributes:u,setAttributes:E,isSelected:f,clientId:w,context:x}=e,k=(0,s.useSelect)((e=>f||e("core/block-editor").hasSelectedInnerBlock(w,!0))),v=x["quiz-master-next/quizID"],{quiz_name:B,post_id:z,rest_nonce:D}=x["quiz-master-next/quizAttr"],{createNotice:I}=(x["quiz-master-next/pageID"],(0,s.useDispatch)(o.store)),{getBlockRootClientId:N,getBlockIndex:S}=(0,s.useSelect)(i.store),{insertBlock:T}=(0,s.useDispatch)(i.store),{isChanged:A=!1,questionID:M,type:L,description:P,title:F,correctAnswerInfo:O,commentBox:H,category:Q,multicategories:R=[],hint:U,featureImageID:j,featureImageSrc:V,answers:W,answerEditor:Z,matchAnswer:$,required:G,settings:J={}}=u,[K,X]=(0,a.useState)(!d(O)),[Y,ee]=(0,a.useState)(!1),te="1"==qsmBlockData.is_pro_activated,ae=e=>14<parseInt(e),ne=qsmBlockData.file_upload_type.options,re=()=>{let e=J?.file_upload_type||qsmBlockData.file_upload_type.default;return d(e)?[]:e.split(",")};(0,a.useEffect)((()=>{let e=!0;if(e&&(d(M)||"0"==M||!d(M)&&((e,t)=>{const a=(0,s.select)("core/block-editor").getClientIdsWithDescendants();return!d(a)&&a.some((a=>{const{questionID:n}=(0,s.select)("core/block-editor").getBlockAttributes(a);return t!==a&&n===e}))})(M,w))){let e=h({id:null,rest_nonce:D,quizID:v,quiz_name:B,postID:z,answerEditor:q(Z,"text"),type:q(L,"0"),name:p(q(P)),question_title:q(F),answerInfo:p(q(O)),comments:q(H,"1"),hint:q(U),category:q(Q),multicategories:[],required:q(G,0),answers:W,page:0,featureImageID:j,featureImageSrc:V,matchAnswer:null});l()({path:"/quiz-survey-master/v1/questions",method:"POST",body:e}).then((e=>{if("success"==e.status){let t=e.id;E({questionID:t})}})).catch((e=>{console.log("error",e),I("error",e.message,{isDismissible:!0,type:"snackbar"})}))}return()=>{e=!1}}),[]),(0,a.useEffect)((()=>{let e=!0;return e&&f&&!1===A&&E({isChanged:!0}),()=>{e=!1}}),[M,L,P,F,O,H,Q,R,U,j,V,W,Z,$,G,J]);const le=(0,i.useBlockProps)({className:k?" in-editing-mode is-highlighted ":""}),ie=(e,t)=>{let a=[];if(!d(t[e])&&"0"!=t[e].parent&&(e=t[e].parent,a.push(e),!d(t[e])&&"0"!=t[e].parent)){let n=ie(e,t);a=[...a,...n]}return _(a)},oe=["12","7","3","5","14"].includes(L)?(0,n.__)("Note: Add only correct answer options with their respective points score.","quiz-master-next"):"",se=()=>{if(d(e?.name))return console.log("block name not found"),!0;const a=(0,t.createBlock)(e.name);T(a,S(w)+1,N(w),!0)};return(0,a.createElement)(a.Fragment,null,(0,a.createElement)(i.BlockControls,null,(0,a.createElement)(c.ToolbarGroup,null,(0,a.createElement)(c.ToolbarButton,{icon:"plus-alt2",label:(0,n.__)("Add New Question","quiz-master-next"),onClick:()=>se()}),(0,a.createElement)(c.ToolbarButton,{icon:"welcome-add-page",label:(0,n.__)("Add New Page","quiz-master-next"),onClick:()=>(()=>{const e=(0,t.createBlock)("qsm/quiz-page"),a=N(w),n=S(a)+1,r=N(a);T(e,n,r,!0)})()}))),Y&&(0,a.createElement)(c.Modal,{contentLabel:(0,n.__)("Use QSM Editor for Advanced Question","quiz-master-next"),className:"qsm-advance-q-modal",isDismissible:!1,size:"small",__experimentalHideHeader:!0},(0,a.createElement)("div",{className:"qsm-modal-body"},(0,a.createElement)("h3",{className:"qsm-title"},(0,a.createElement)(c.Icon,{icon:()=>(0,a.createElement)("svg",{width:"54",height:"54",viewBox:"0 0 54 54",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,a.createElement)("path",{d:"M27.1855 23.223V28.0626M15.1794 32.4196C14.0618 34.3554 15.4595 36.7739 17.6934 36.7739H36.6776C38.9102 36.7739 40.3079 34.3554 39.1916 32.4196L29.7008 15.9675C28.5832 14.0317 25.7878 14.0317 24.6702 15.9675L15.1794 32.4196ZM27.1855 31.9343H27.1945V31.9446H27.1855V31.9343Z",stroke:"#B45309",strokeWidth:"1.65929",strokeLinecap:"round",strokeLinejoin:"round"}))}),(0,a.createElement)("br",null),(0,n.__)("Use QSM editor for Advanced Question","quiz-master-next")),(0,a.createElement)("p",{className:"qsm-description"},(0,n.__)("Currently, the block editor doesn't support advanced question type. We are working on it. Alternatively, you can add advanced questions from your QSM's quiz editor.","quiz-master-next")),(0,a.createElement)("div",{className:"qsm-modal-btn-wrapper"},(0,a.createElement)(c.Button,{variant:"secondary",onClick:()=>ee(!1)},(0,n.__)("Cancel","quiz-master-next")),(0,a.createElement)(c.Button,{variant:"primary",onClick:()=>{}},(0,a.createElement)(c.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+v},(0,n.__)("Add Question from quiz editor","quiz-master-next")))))),ae(L)?(0,a.createElement)(a.Fragment,null,(0,a.createElement)(i.InspectorControls,null,(0,a.createElement)(c.PanelBody,{title:(0,n.__)("Question settings","quiz-master-next"),initialOpen:!0},(0,a.createElement)("h2",{className:"block-editor-block-card__title"},(0,n.__)("ID","quiz-master-next")+": "+M),(0,a.createElement)("h3",null,(0,n.__)("Advanced Question Type","quiz-master-next")))),(0,a.createElement)("div",{...le},(0,a.createElement)("h4",{className:"qsm-question-title qsm-error-text"},(0,n.__)("Advanced Question Type : ","quiz-master-next")+F),(0,a.createElement)("p",null,(0,n.__)("Edit question in QSM ","quiz-master-next"),(0,a.createElement)(c.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+v},(0,n.__)("editor","quiz-master-next"))))):(0,a.createElement)(a.Fragment,null,(0,a.createElement)(i.InspectorControls,null,(0,a.createElement)(c.PanelBody,{title:(0,n.__)("Question settings","quiz-master-next"),initialOpen:!0},(0,a.createElement)("h2",{className:"block-editor-block-card__title"},(0,n.__)("ID","quiz-master-next")+": "+M),(0,a.createElement)(c.SelectControl,{label:qsmBlockData.question_type.label,value:L||qsmBlockData.question_type.default,onChange:e=>(e=>{if(d(MicroModal)||te||!["15","16","17"].includes(e))te&&ae(e)?ee(!0):E({type:e});else{let e=document.getElementById("modal-advanced-question-type");d(e)||MicroModal.show("modal-advanced-question-type")}})(e),help:d(qsmBlockData.question_type_description[L])?"":qsmBlockData.question_type_description[L]+" "+oe,__nextHasNoMarginBottom:!0},!d(qsmBlockData.question_type.options)&&qsmBlockData.question_type.options.map((e=>(0,a.createElement)("optgroup",{label:e.category,key:"qtypes"+e.category},e.types.map((e=>(0,a.createElement)("option",{value:e.slug,key:"qtype"+e.slug},e.name))))))),["0","4","1","10","13"].includes(L)&&(0,a.createElement)(c.SelectControl,{label:qsmBlockData.answerEditor.label,value:Z||qsmBlockData.answerEditor.default,options:qsmBlockData.answerEditor.options,onChange:e=>E({answerEditor:e}),__nextHasNoMarginBottom:!0}),(0,a.createElement)(c.ToggleControl,{label:(0,n.__)("Required","quiz-master-next"),checked:!d(G)&&"1"==G,onChange:()=>E({required:d(G)||"1"!=G?1:0})}),(0,a.createElement)(c.ToggleControl,{label:(0,n.__)("Show Correct Answer Info","quiz-master-next"),checked:K,onChange:()=>X(!K)})),"11"==L&&(0,a.createElement)(c.PanelBody,{title:(0,n.__)("File Settings","quiz-master-next"),initialOpen:!1},(0,a.createElement)(c.TextControl,{type:"number",label:qsmBlockData.file_upload_limit.heading,value:null!==(r=J?.file_upload_limit)&&void 0!==r?r:qsmBlockData.file_upload_limit.default,onChange:e=>E({settings:{...J,file_upload_limit:e}})}),(0,a.createElement)("label",{className:"qsm-inspector-label"},qsmBlockData.file_upload_type.heading),Object.keys(qsmBlockData.file_upload_type.options).map((e=>{return(0,a.createElement)(c.CheckboxControl,{key:"filetype-"+e,label:ne[e],checked:(t=e,re().includes(t)),onChange:()=>(e=>{let t=re();t.includes(e)?t=t.filter((t=>t!=e)):t.push(e),t=t.join(","),E({settings:{...J,file_upload_type:t}})})(e)});var t}))),(0,a.createElement)(b,{isCategorySelected:e=>R.includes(e),setUnsetCatgory:(e,t)=>{let a=d(R)||0===R.length?d(Q)?[]:[Q]:R;if(a.includes(e))a=a.filter((t=>t!=e)),a.forEach((n=>{ie(n,t).includes(e)&&(a=a.filter((e=>e!=n)))}));else{a.push(e);let n=ie(e,t);a=[...a,...n]}a=_(a),E({category:"",multicategories:[...a]})}}),(0,a.createElement)(c.PanelBody,{title:(0,n.__)("Hint","quiz-master-next"),initialOpen:!1},(0,a.createElement)(c.TextControl,{label:"",value:U,onChange:e=>E({hint:g(e)})})),(0,a.createElement)(c.PanelBody,{title:qsmBlockData.commentBox.heading,initialOpen:!1},(0,a.createElement)(c.SelectControl,{label:qsmBlockData.commentBox.label,value:H||qsmBlockData.commentBox.default,options:qsmBlockData.commentBox.options,onChange:e=>E({commentBox:e}),__nextHasNoMarginBottom:!0})),(0,a.createElement)(c.PanelBody,{title:(0,n.__)("Featured image","quiz-master-next"),initialOpen:!0},(0,a.createElement)(C,{featureImageID:j,onUpdateImage:e=>{E({featureImageID:e.id,featureImageSrc:e.url})},onRemoveImage:e=>{E({featureImageID:void 0,featureImageSrc:void 0})}}))),(0,a.createElement)("div",{...le},(0,a.createElement)(i.RichText,{tagName:"h4",title:(0,n.__)("Question title","quiz-master-next"),"aria-label":(0,n.__)("Question title","quiz-master-next"),placeholder:(0,n.__)("Type your question here","quiz-master-next"),value:F,onChange:e=>E({title:g(e)}),allowedFormats:[],withoutInteractiveFormatting:!0,className:"qsm-question-title"}),k&&(0,a.createElement)(a.Fragment,null,(0,a.createElement)(i.RichText,{tagName:"p",title:(0,n.__)("Question description","quiz-master-next"),"aria-label":(0,n.__)("Question description","quiz-master-next"),placeholder:(0,n.__)("Description goes here... (optional)","quiz-master-next"),value:p(P),onChange:e=>E({description:e}),className:"qsm-question-description",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),!["8","11","6","9"].includes(L)&&(0,a.createElement)(i.InnerBlocks,{allowedBlocks:["qsm/quiz-answer-option"],template:[["qsm/quiz-answer-option",{optionID:"0"}],["qsm/quiz-answer-option",{optionID:"1"}]]}),K&&(0,a.createElement)(i.RichText,{tagName:"p",title:(0,n.__)("Correct Answer Info","quiz-master-next"),"aria-label":(0,n.__)("Correct Answer Info","quiz-master-next"),placeholder:(0,n.__)("Correct answer info goes here","quiz-master-next"),value:p(O),onChange:e=>E({correctAnswerInfo:e}),className:"qsm-question-correct-answer-info",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),k&&(0,a.createElement)("div",{className:"block-editor-block-list__insertion-point-inserter qsm-add-new-ques-wrapper"},(0,a.createElement)(c.Button,{icon:y,label:(0,n.__)("Add New Question","quiz-master-next"),tooltipPosition:"bottom",onClick:()=>se(),variant:"secondary",className:"add-new-question-btn block-editor-inserter__toggle"}))))))},__experimentalLabel(e,{context:t}){const{title:a}=e,n=e?.metadata?.name;if("list-view"===t&&(n||a?.length>0))return n||a}})})(); \ No newline at end of file +(0,n.__)("The current image has no alternative text. The file name is: %s"),h.slug)),(0,a.createElement)(o.MediaUploadCheck,{fallback:x},(0,a.createElement)(o.MediaUpload,{title:f,onSelect:e=>{q(e),t(e)},unstableFeaturedImageFlow:!0,allowedTypes:E,modalClass:"editor-post-featured-image__media-modal",render:({open:t})=>(0,a.createElement)("div",{className:"editor-post-featured-image__container"},(0,a.createElement)(m.Button,{ref:i,className:e?"editor-post-featured-image__preview":"editor-post-featured-image__toggle",onClick:t,"aria-label":e?(0,n.__)("Edit or replace the image"):null,"aria-describedby":e?`editor-post-featured-image-${e}-describedby`:null},!!e&&h&&(0,a.createElement)(m.ResponsiveWrapper,{naturalWidth:h.width,naturalHeight:h.height,isInline:!0},(0,a.createElement)("img",{src:h.url,alt:h.alt_text})),_&&(0,a.createElement)(m.Spinner,null),!e&&!_&&w),!!e&&(0,a.createElement)(m.__experimentalHStack,{className:"editor-post-featured-image__actions"},(0,a.createElement)(m.Button,{className:"editor-post-featured-image__action",onClick:t,"aria-hidden":"true"},(0,n.__)("Replace")),(0,a.createElement)(m.Button,{className:"editor-post-featured-image__action",onClick:()=>{r(),i.current.focus()}},(0,n.__)("Remove"))),(0,a.createElement)(m.DropZone,{onFilesDrop:y})),value:e})))},b=({isCategorySelected:e,setUnsetCatgory:t})=>{const[r,l]=(0,a.useState)(!1),[o,s]=(0,a.useState)(""),[c,u]=(0,a.useState)(0),[d,_]=(0,a.useState)(!1),[g,q]=(0,a.useState)(!1),[E,f]=(0,a.useState)(qsmBlockData?.hierarchicalCategoryList),w=e=>{let t={};return e.forEach((e=>{if(t[e.id]=e,0<e.children.length){let a=w(e.children);t={...t,...a}}})),t},[x,C]=(0,a.useState)(p(qsmBlockData?.hierarchicalCategoryList)?{}:w(qsmBlockData.hierarchicalCategoryList)),b=(0,n.__)("Add New Category ","quiz-master-next"),y=`— ${(0,n.__)("Parent Category ","quiz-master-next")} —`,k=e=>{let t=[];return e.forEach((e=>{if(t.push(e.name),0<e.children.length){let a=k(e.children);t=[...t,...a]}})),t},v=n=>n.map((n=>(0,a.createElement)("div",{key:n.id,className:"editor-post-taxonomies__hierarchical-terms-choice"},(0,a.createElement)(m.CheckboxControl,{label:n.name,checked:e(n.id),onChange:()=>t(n.id,x)}),!!n.children.length&&(0,a.createElement)("div",{className:"editor-post-taxonomies__hierarchical-terms-subchoices"},v(n.children)))));return(0,a.createElement)(m.PanelBody,{title:(0,n.__)("Categories","quiz-master-next"),initialOpen:!0},(0,a.createElement)("div",{className:"editor-post-taxonomies__hierarchical-terms-list",tabIndex:"0",role:"group","aria-label":(0,n.__)("Categories","quiz-master-next")},v(E)),(0,a.createElement)("div",{className:"qsm-ptb-1"},(0,a.createElement)(m.Button,{variant:"link",onClick:()=>l(!r)},b)),r&&(0,a.createElement)("form",{onSubmit:async e=>{e.preventDefault(),g||p(o)||d||(_(!0),i()({url:qsmBlockData.ajax_url,method:"POST",body:h({action:"save_new_category",name:o,parent:c})}).then((e=>{if(!p(e.term_id)){let a=e.term_id;i()({path:"/quiz-survey-master/v1/quiz/hierarchical-category-list",method:"POST"}).then((e=>{"success"==e.status&&(f(e.result),C(e.result),s(""),u(0),t(a,w(term.id)),_(!1))}))}})))}},(0,a.createElement)(m.Flex,{direction:"column",gap:"1"},(0,a.createElement)(m.TextControl,{__nextHasNoMarginBottom:!0,className:"editor-post-taxonomies__hierarchical-terms-input",label:(0,n.__)("Category Name","quiz-master-next"),value:o,onChange:e=>((e,t)=>{t=k(t),console.log("categories",t),t.includes(e)?q(e):(q(!1),s(e))})(e,E),required:!0}),0<E.length&&(0,a.createElement)(m.TreeSelect,{__nextHasNoMarginBottom:!0,label:(0,n.__)("Parent Category","quiz-master-next"),noOptionLabel:y,onChange:e=>u(e),selectedId:c,tree:E}),(0,a.createElement)(m.FlexItem,null,(0,a.createElement)(m.Button,{variant:"secondary",type:"submit",className:"editor-post-taxonomies__hierarchical-terms-submit",disabled:g||d},b)),(0,a.createElement)(m.FlexItem,null,(0,a.createElement)("p",{className:"qsm-error-text"},!1!==g&&(0,n.__)("Category ","quiz-master-next")+g+(0,n.__)(" already exists.","quiz-master-next"))))))},y=()=>(0,a.createElement)(m.Icon,{icon:()=>(0,a.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false"},(0,a.createElement)("path",{d:"M18 11.2h-5.2V6h-1.6v5.2H6v1.6h5.2V18h1.6v-5.2H18z"}))}),k=JSON.parse('{"u2":"qsm/quiz-question"}');(0,t.registerBlockType)(k.u2,{icon:()=>(0,a.createElement)(m.Icon,{icon:()=>(0,a.createElement)("svg",{width:"25",height:"25",viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,a.createElement)("rect",{x:"0.102539",y:"0.101562",width:"24",height:"24",rx:"4.68852",fill:"#ADADAD"}),(0,a.createElement)("path",{d:"M17.0475 17.191C17.2367 17.3683 17.3313 17.5752 17.3313 17.8117C17.3313 18.06 17.2426 18.2787 17.0653 18.4679C16.8879 18.6453 16.6751 18.734 16.4268 18.734C16.1667 18.734 15.9538 18.6512 15.7883 18.4857L14.937 17.6521C13.8492 18.4088 12.5959 18.7872 11.177 18.7872C10.0301 18.7872 9.01325 18.533 8.12646 18.0245C7.2515 17.5161 6.57163 16.8126 6.08685 15.914C5.6139 15.0035 5.37742 13.9631 5.37742 12.7925C5.37742 11.5273 5.64937 10.41 6.19327 9.44044C6.74898 8.45907 7.48206 7.70234 8.3925 7.17027C9.31475 6.6382 10.308 6.37216 11.3721 6.37216C12.4481 6.37216 13.459 6.64411 14.4049 7.18801C15.3508 7.72008 16.1075 8.46498 16.6751 9.42271C17.2426 10.3804 17.5264 11.4505 17.5264 12.6329C17.5264 14.0636 17.1007 15.3287 16.2494 16.4283L17.0475 17.191ZM11.177 17.1732C12.0874 17.1732 12.9269 16.9249 13.6955 16.4283L12.5604 15.311C12.3949 15.1454 12.3121 14.9799 12.3121 14.8144C12.3121 14.6015 12.4244 14.3887 12.6491 14.1759C12.8855 13.9631 13.122 13.8566 13.3585 13.8566C13.5122 13.8566 13.6364 13.9039 13.7309 13.9985L14.9724 15.1868C15.4927 14.4183 15.7528 13.5492 15.7528 12.5797C15.7528 11.7284 15.5518 10.9539 15.1498 10.2563C14.7596 9.54686 14.2335 8.99114 13.5713 8.58913C12.9092 8.18712 12.1998 7.98611 11.443 7.98611C10.6981 7.98611 9.99462 8.18121 9.33249 8.57139C8.67036 8.94975 8.13828 9.49956 7.73627 10.2208C7.34609 10.9421 7.15099 11.7756 7.15099 12.7216C7.15099 13.6083 7.32244 14.3887 7.66533 15.0627C8.02005 15.7366 8.49891 16.2569 9.10192 16.6234C9.71676 16.99 10.4085 17.1732 11.177 17.1732Z",fill:"white"}))}),edit:function(e){var l;if("undefined"==typeof qsmBlockData)return null;const{className:u,attributes:d,setAttributes:E,isSelected:f,clientId:w,context:x}=e,k=(0,c.useSelect)((e=>f||e("core/block-editor").hasSelectedInnerBlock(w,!0))),v=x["quiz-master-next/quizID"],{quiz_name:B,post_id:z,rest_nonce:D}=x["quiz-master-next/quizAttr"],{createNotice:I}=(x["quiz-master-next/pageID"],(0,c.useDispatch)(s.store)),{getBlockRootClientId:N,getBlockIndex:S}=(0,c.useSelect)(o.store),{insertBlock:A}=(0,c.useDispatch)(o.store),{isChanged:T=!1,questionID:M,type:P,description:L,title:F,correctAnswerInfo:O,commentBox:H,category:Q,multicategories:R=[],hint:U,featureImageID:j,featureImageSrc:V,answers:W,answerEditor:Z,matchAnswer:$,required:G,settings:J={}}=d,[K,X]=(0,a.useState)(!p(O)),[Y,ee]=(0,a.useState)(!1),te="1"==qsmBlockData.is_pro_activated,ae=e=>14<parseInt(e),ne=qsmBlockData.file_upload_type.options,re=()=>{let e=J?.file_upload_type||qsmBlockData.file_upload_type.default;return p(e)?[]:e.split(",")};(0,a.useEffect)((()=>{let e=!0;if(e&&(p(M)||"0"==M||!p(M)&&((e,t)=>{const a=(0,c.select)("core/block-editor").getClientIdsWithDescendants();return!p(a)&&a.some((a=>{const{questionID:n}=(0,c.select)("core/block-editor").getBlockAttributes(a);return t!==a&&n===e}))})(M,w))){let e=h({id:null,rest_nonce:D,quizID:v,quiz_name:B,postID:z,answerEditor:q(Z,"text"),type:q(P,"0"),name:g(q(L)),question_title:q(F),answerInfo:g(q(O)),comments:q(H,"1"),hint:q(U),category:q(Q),multicategories:[],required:q(G,0),answers:W,page:0,featureImageID:j,featureImageSrc:V,matchAnswer:null});i()({path:"/quiz-survey-master/v1/questions",method:"POST",body:e}).then((e=>{if("success"==e.status){let t=e.id;E({questionID:t})}})).catch((e=>{console.log("error",e),I("error",e.message,{isDismissible:!0,type:"snackbar"})}))}return()=>{e=!1}}),[]),(0,a.useEffect)((()=>{let e=!0;return e&&f&&!1===T&&E({isChanged:!0}),()=>{e=!1}}),[M,P,L,F,O,H,Q,R,U,j,V,W,Z,$,G,J]);const le=(0,o.useBlockProps)({className:k?" in-editing-mode is-highlighted ":""}),ie=(e,t)=>{let a=[];if(!p(t[e])&&"0"!=t[e].parent&&(e=t[e].parent,a.push(e),!p(t[e])&&"0"!=t[e].parent)){let n=ie(e,t);a=[...a,...n]}return _(a)},oe=["12","7","3","5","14"].includes(P)?(0,n.__)("Note: Add only correct answer options with their respective points score.","quiz-master-next"):"",se=()=>{if(p(e?.name))return console.log("block name not found"),!0;const a=(0,t.createBlock)(e.name);A(a,S(w)+1,N(w),!0)};return(0,a.createElement)(a.Fragment,null,(0,a.createElement)(o.BlockControls,null,(0,a.createElement)(m.ToolbarGroup,null,(0,a.createElement)(m.ToolbarButton,{icon:"plus-alt2",label:(0,n.__)("Add New Question","quiz-master-next"),onClick:()=>se()}),(0,a.createElement)(m.ToolbarButton,{icon:"welcome-add-page",label:(0,n.__)("Add New Page","quiz-master-next"),onClick:()=>(()=>{const e=(0,t.createBlock)("qsm/quiz-page"),a=N(w),n=S(a)+1,r=N(a);A(e,n,r,!0)})()}))),Y&&(0,a.createElement)(m.Modal,{contentLabel:(0,n.__)("Use QSM Editor for Advanced Question","quiz-master-next"),className:"qsm-advance-q-modal",isDismissible:!1,size:"small",__experimentalHideHeader:!0},(0,a.createElement)("div",{className:"qsm-modal-body"},(0,a.createElement)("h3",{className:"qsm-title"},(0,a.createElement)(m.Icon,{icon:()=>(0,a.createElement)("svg",{width:"54",height:"54",viewBox:"0 0 54 54",fill:"none",xmlns:"http://www.w3.org/2000/svg"},(0,a.createElement)("path",{d:"M27.1855 23.223V28.0626M15.1794 32.4196C14.0618 34.3554 15.4595 36.7739 17.6934 36.7739H36.6776C38.9102 36.7739 40.3079 34.3554 39.1916 32.4196L29.7008 15.9675C28.5832 14.0317 25.7878 14.0317 24.6702 15.9675L15.1794 32.4196ZM27.1855 31.9343H27.1945V31.9446H27.1855V31.9343Z",stroke:"#B45309",strokeWidth:"1.65929",strokeLinecap:"round",strokeLinejoin:"round"}))}),(0,a.createElement)("br",null),(0,n.__)("Use QSM editor for Advanced Question","quiz-master-next")),(0,a.createElement)("p",{className:"qsm-description"},(0,n.__)("Currently, the block editor doesn't support advanced question type. We are working on it. Alternatively, you can add advanced questions from your QSM's quiz editor.","quiz-master-next")),(0,a.createElement)("div",{className:"qsm-modal-btn-wrapper"},(0,a.createElement)(m.Button,{variant:"secondary",onClick:()=>ee(!1)},(0,n.__)("Cancel","quiz-master-next")),(0,a.createElement)(m.Button,{variant:"primary",onClick:()=>{}},(0,a.createElement)(m.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+v},(0,n.__)("Add Question from quiz editor","quiz-master-next")))))),ae(P)?(0,a.createElement)(a.Fragment,null,(0,a.createElement)(o.InspectorControls,null,(0,a.createElement)(m.PanelBody,{title:(0,n.__)("Question settings","quiz-master-next"),initialOpen:!0},(0,a.createElement)("h2",{className:"block-editor-block-card__title"},(0,n.__)("ID","quiz-master-next")+": "+M),(0,a.createElement)("h3",null,(0,n.__)("Advanced Question Type","quiz-master-next")))),(0,a.createElement)("div",{...le},(0,a.createElement)("h4",{className:"qsm-question-title qsm-error-text"},(0,n.__)("Advanced Question Type : ","quiz-master-next")+F),(0,a.createElement)("p",null,(0,n.__)("Edit question in QSM ","quiz-master-next"),(0,a.createElement)(m.ExternalLink,{href:qsmBlockData.quiz_settings_url+"&quiz_id="+v},(0,n.__)("editor","quiz-master-next"))))):(0,a.createElement)(a.Fragment,null,(0,a.createElement)(o.InspectorControls,null,(0,a.createElement)(m.PanelBody,{title:(0,n.__)("Question settings","quiz-master-next"),initialOpen:!0},(0,a.createElement)("h2",{className:"block-editor-block-card__title"},(0,n.__)("ID","quiz-master-next")+": "+M),(0,a.createElement)(m.SelectControl,{label:qsmBlockData.question_type.label,value:P||qsmBlockData.question_type.default,onChange:e=>(e=>{if(p(MicroModal)||te||!["15","16","17"].includes(e))te&&ae(e)?ee(!0):E({type:e});else{let e=document.getElementById("modal-advanced-question-type");p(e)||MicroModal.show("modal-advanced-question-type")}})(e),help:p(qsmBlockData.question_type_description[P])?"":qsmBlockData.question_type_description[P]+" "+oe,__nextHasNoMarginBottom:!0},!p(qsmBlockData.question_type.options)&&qsmBlockData.question_type.options.map((e=>(0,a.createElement)("optgroup",{label:e.category,key:"qtypes"+e.category},e.types.map((e=>(0,a.createElement)("option",{value:e.slug,key:"qtype"+e.slug},e.name))))))),["0","4","1","10","13"].includes(P)&&(0,a.createElement)(m.SelectControl,{label:qsmBlockData.answerEditor.label,value:Z||qsmBlockData.answerEditor.default,options:qsmBlockData.answerEditor.options,onChange:e=>E({answerEditor:e}),__nextHasNoMarginBottom:!0}),(0,a.createElement)(m.ToggleControl,{label:(0,n.__)("Required","quiz-master-next"),checked:!p(G)&&"1"==G,onChange:()=>E({required:p(G)||"1"!=G?1:0})}),(0,a.createElement)(m.ToggleControl,{label:(0,n.__)("Show Correct Answer Info","quiz-master-next"),checked:K,onChange:()=>X(!K)})),"11"==P&&(0,a.createElement)(m.PanelBody,{title:(0,n.__)("File Settings","quiz-master-next"),initialOpen:!1},(0,a.createElement)(m.TextControl,{type:"number",label:qsmBlockData.file_upload_limit.heading,value:null!==(l=J?.file_upload_limit)&&void 0!==l?l:qsmBlockData.file_upload_limit.default,onChange:e=>E({settings:{...J,file_upload_limit:e}})}),(0,a.createElement)("label",{className:"qsm-inspector-label"},qsmBlockData.file_upload_type.heading),Object.keys(qsmBlockData.file_upload_type.options).map((e=>{return(0,a.createElement)(m.CheckboxControl,{key:"filetype-"+e,label:ne[e],checked:(t=e,re().includes(t)),onChange:()=>(e=>{let t=re();t.includes(e)?t=t.filter((t=>t!=e)):t.push(e),t=t.join(","),E({settings:{...J,file_upload_type:t}})})(e)});var t}))),(0,a.createElement)(b,{isCategorySelected:e=>R.includes(e),setUnsetCatgory:(e,t)=>{let a=p(R)||0===R.length?p(Q)?[]:[Q]:R;if(a.includes(e))a=a.filter((t=>t!=e)),a.forEach((n=>{ie(n,t).includes(e)&&(a=a.filter((e=>e!=n)))}));else{a.push(e);let n=ie(e,t);a=[...a,...n]}a=_(a),E({category:"",multicategories:[...a]})}}),(0,a.createElement)(m.PanelBody,{title:(0,n.__)("Hint","quiz-master-next"),initialOpen:!1},(0,a.createElement)(m.TextControl,{label:"",value:U,onChange:e=>E({hint:(0,r.escapeAttribute)(e)})})),(0,a.createElement)(m.PanelBody,{title:qsmBlockData.commentBox.heading,initialOpen:!1},(0,a.createElement)(m.SelectControl,{label:qsmBlockData.commentBox.label,value:H||qsmBlockData.commentBox.default,options:qsmBlockData.commentBox.options,onChange:e=>E({commentBox:e}),__nextHasNoMarginBottom:!0})),(0,a.createElement)(m.PanelBody,{title:(0,n.__)("Featured image","quiz-master-next"),initialOpen:!0},(0,a.createElement)(C,{featureImageID:j,onUpdateImage:e=>{E({featureImageID:e.id,featureImageSrc:e.url})},onRemoveImage:e=>{E({featureImageID:void 0,featureImageSrc:void 0})}}))),(0,a.createElement)("div",{...le},(0,a.createElement)(o.RichText,{tagName:"h4",title:(0,n.__)("Question title","quiz-master-next"),"aria-label":(0,n.__)("Question title","quiz-master-next"),placeholder:(0,n.__)("Type your question here","quiz-master-next"),value:(0,r.escapeAttribute)(F),onChange:e=>E({title:(0,r.escapeAttribute)(e)}),allowedFormats:[],withoutInteractiveFormatting:!0,className:"qsm-question-title"}),k&&(0,a.createElement)(a.Fragment,null,(0,a.createElement)(o.RichText,{tagName:"p",title:(0,n.__)("Question description","quiz-master-next"),"aria-label":(0,n.__)("Question description","quiz-master-next"),placeholder:(0,n.__)("Description goes here... (optional)","quiz-master-next"),value:g(L),onChange:e=>E({description:e}),className:"qsm-question-description",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),!["8","11","6","9"].includes(P)&&(0,a.createElement)(o.InnerBlocks,{allowedBlocks:["qsm/quiz-answer-option"],template:[["qsm/quiz-answer-option",{optionID:"0"}],["qsm/quiz-answer-option",{optionID:"1"}]]}),K&&(0,a.createElement)(o.RichText,{tagName:"p",title:(0,n.__)("Correct Answer Info","quiz-master-next"),"aria-label":(0,n.__)("Correct Answer Info","quiz-master-next"),placeholder:(0,n.__)("Correct answer info goes here","quiz-master-next"),value:g(O),onChange:e=>E({correctAnswerInfo:e}),className:"qsm-question-correct-answer-info",__unstableEmbedURLOnPaste:!0,__unstableAllowPrefixTransformations:!0}),k&&(0,a.createElement)("div",{className:"block-editor-block-list__insertion-point-inserter qsm-add-new-ques-wrapper"},(0,a.createElement)(m.Button,{icon:y,label:(0,n.__)("Add New Question","quiz-master-next"),tooltipPosition:"bottom",onClick:()=>se(),variant:"secondary",className:"add-new-question-btn block-editor-inserter__toggle"}))))))},__experimentalLabel(e,{context:t}){const{title:a}=e,n=e?.metadata?.name;if("list-view"===t&&(n||a?.length>0))return n||a}})})(); \ No newline at end of file
blocks/src/answer-option/edit.js+2 −2 modified@@ -148,8 +148,8 @@ onRemove } = props; title={ __( 'Answer options', 'quiz-master-next' ) } aria-label={ __( 'Question answer', 'quiz-master-next' ) } placeholder={ __( 'Your Answer', 'quiz-master-next' ) } - value={ qsmStripTags( decodeEntities( content ) ) } - onChange={ ( content ) => setAttributes( { content: qsmStripTags( decodeEntities( content ) ) } ) } + value={ escapeAttribute( content ) } + onChange={ ( content ) => setAttributes( { content: escapeAttribute( content ) } ) } onSplit={ ( value, isOriginal ) => { let newAttributes;
blocks/src/component/InputComponent.js+3 −2 modified@@ -1,5 +1,6 @@ import { __ } from '@wordpress/i18n'; import { useState, useEffect } from '@wordpress/element'; +import { escapeAttribute } from "@wordpress/escape-html"; import { Button, TextControl, @@ -47,8 +48,8 @@ export default function InputComponent( { break; } } - data.label = qsmIsEmpty( data.label ) ? '': qsmStripTags( data.label ); - data.help = qsmIsEmpty( data.help ) ? '': qsmStripTags( data.help ); + data.label = qsmIsEmpty( data.label ) ? '': escapeAttribute( data.label ); + data.help = qsmIsEmpty( data.help ) ? '': escapeAttribute( data.help ); return data; }
blocks/src/question/edit.js+4 −3 modified@@ -1,5 +1,6 @@ import { __ } from '@wordpress/i18n'; import { useState, useEffect } from '@wordpress/element'; +import { escapeAttribute } from "@wordpress/escape-html"; import apiFetch from '@wordpress/api-fetch'; import { InspectorControls, @@ -513,7 +514,7 @@ export default function Edit( props ) { <TextControl label='' value={ hint } - onChange={ ( hint ) => setAttributes( { hint: qsmStripTags( hint ) } ) } + onChange={ ( hint ) => setAttributes( { hint: escapeAttribute( hint ) } ) } /> </PanelBody> {/**Comment Box */} @@ -553,8 +554,8 @@ export default function Edit( props ) { title={ __( 'Question title', 'quiz-master-next' ) } aria-label={ __( 'Question title', 'quiz-master-next' ) } placeholder={ __( 'Type your question here', 'quiz-master-next' ) } - value={ title } - onChange={ ( title ) => setAttributes( { title: qsmStripTags( title ) } ) } + value={ escapeAttribute( title ) } + onChange={ ( title ) => setAttributes( { title: escapeAttribute( title ) } ) } allowedFormats={ [ ] } withoutInteractiveFormatting className={ 'qsm-question-title' }
blocks/src/render.php+0 −4 modified@@ -2,7 +2,3 @@ /** * @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render */ -?> -<p <?php echo get_block_wrapper_attributes(); ?>> - <?php esc_html_e( 'QSM Block hello from a dynamic block!', 'quiz-master-next' ); ?> -</p>
css/common.css+11 −0 modified@@ -712,4 +712,15 @@ body .ui-tooltip.ui-widget-content { .qsm-quiz-container input[type=radio] { vertical-align: top; margin-top: 5px; +} +.quiz_section fieldset { + border: none; + padding: 0; + margin: 0; +} +.mlw_qmn_hint_link { + text-decoration: none; +} +.qsm_accessibility_label { + color: transparent; } \ No newline at end of file
css/qsm-admin.css+13 −0 modified@@ -3436,4 +3436,17 @@ input#preferred-date-format-custom { min-width: 520px; background: #cccccc36; border: 1px solid #ccc; +} + +.qsm-pointer-events-none { + pointer-events: none; +} + +.display-none-notice { + display: none; +} + +#qmn-failed-submission-table-message { + padding-right: 38px; + position: relative; } \ No newline at end of file
js/jquery.ui.slider-rtl.js+2 −2 modified@@ -87,14 +87,14 @@ $.widget( "ui.slider", $.ui.mouse, { } if ( $( ".ui-slider-handle", this.element ).length === 0 ) { - $( "<a href='#'></a>" ) + $( "<span></span>" ) .appendTo( this.element ) .addClass( "ui-slider-handle" ); } if ( o.values && o.values.length ) { while ( $(".ui-slider-handle", this.element).length < o.values.length ) { - $( "<a href='#'></a>" ) + $( "<span></span>" ) .appendTo( this.element ) .addClass( "ui-slider-handle" ); }
js/qsm-admin.js+152 −0 modified@@ -3714,6 +3714,7 @@ var import_button; 'value': $(this).find('.results-page-condition-value').val() }); }); + jQuery(document).trigger('qsm_save_result_page_before', [this, page]); pages.push(page); }); let _X_validation = false; @@ -3956,3 +3957,154 @@ var import_button; qsmHandleOperatorChange('email-condition', 'condition-default-value'); }(jQuery)); + + +/** + * QSM - failed submission data table action + */ +(function ($) { + function submit_failed_submission_action_notice( res ) { + if ( 'object' !== typeof res || null === res || undefined === res.message ) { + return false; + } + let noticeEl = $( '#qmn-failed-submission-table-message' ); + if ( 0 < noticeEl.length ) { + let remove_notice_type_class = 'success' === res.status ? 'notice-error' : 'notice-success'; + noticeEl.removeClass( remove_notice_type_class ); + noticeEl.addClass( 'notice-'+res.status ); + noticeEl.find( '.notice-message' ).text( + res.message + ); + noticeEl.removeClass( 'display-none-notice' ); + } + } + + function submit_failed_submission_action_form( formData, ) { + + // check for required data + if ( undefined === formData || null === formData || -1 == formData.quiz_action || 0 === formData.post_ids.length ) { + submit_failed_submission_action_notice( { + status:"error", + message:"Missing form action or data" + } ); + return false; + } + + // quiz action + formData.action = 'qsm_action_failed_submission_table'; + + // Disable conatiner for further any action + let containerDiv = $("#qmn-failed-submission-conatiner"); + containerDiv.toggleClass('qsm-pointer-events-none'); + + // Actiion one by one + formData.post_ids.forEach( post_id => { + formData.post_id = post_id; + let action_link_wrap = $( '#action-link-'+post_id ); + let action_link_html = action_link_wrap.html(); + action_link_wrap.html( 'processing...'); + $.ajax({ + type: 'POST', + url: ajaxurl, + data: formData, + success: function (response) { + // notice. + submit_failed_submission_action_notice( response.data ); + + // enable click pointer + containerDiv.removeClass('qsm-pointer-events-none'); + + // add success icon + if ( response.success ) { + action_link_wrap.html( '<span class="dashicons dashicons-yes-alt"></span>' ); + } else { + action_link_wrap.html( 'Failed' ); + } + + // Remove row if trashed + if ( 'trash' === formData.quiz_action ) { + $( '#qsm-submission-row-'+post_id ).remove(); + } + + }, + error: function ( jqXHR, textStatus, errorThrown ) { + // undo action link + action_link_wrap.html( action_link_html ); + + // enable click pointer + containerDiv.removeClass('qsm-pointer-events-none'); + + // error notice + submit_failed_submission_action_notice( { + status:"error", + message:errorThrown + } ); + } + }); + }); + + } + + // Submit Form. + $( document ).on( 'submit', '#failed-submission-action-form', function( e ) { + e.preventDefault(); + let formData = { + qmnnonce: $('#failed-submission-action-form input[name="qmnnonce"]').val(), + post_ids: [], + quiz_action: $('#failed-submission-action-form #bulk-action-selector-top').val() + }; + // Select all checkboxes with the name attribute 'post_id[]' + let checkedCheckboxes = $('#failed-submission-action-form input[type="checkbox"][name="post_id[]"]:checked'); + + // Iterate over each checked checkbox + checkedCheckboxes.each(function() { + formData.post_ids.push( $(this).val() ); + }); + + submit_failed_submission_action_form( formData ); + } ); + + // Dismiss notification + $( document ).on( 'click', '#qmn-failed-submission-table-message .notice-dismiss', function( e ) { + e.preventDefault(); + $(this).parent().addClass( 'display-none-notice' ); + }); + + // On click retrieve link + $( document ).on( 'click', '.qmn-retrieve-failed-submission-link', function( e ) { + e.preventDefault(); + + submit_failed_submission_action_form( { + qmnnonce: $('#failed-submission-action-form input[name="qmnnonce"]').val(), + post_ids: [ $(this).attr('post-id') ], + quiz_action:'retrieve' + } ); + } ); + + // Run failed ALTER TABLE query via ajax on notification button click + $( document ).on( 'click', '.notice.qmn-database-user-incorrect-permission .check-db-fix-btn', function( e ) { + e.preventDefault(); + let dbFixBtn = $( this ); + let formData = { + action: 'qsm_check_fix_db', + qmnnonce: $( this ).attr( 'qmnnonce' ), + }; + dbFixBtn.text("processing..."); + dbFixBtn.removeClass( 'check-db-fix-btn' ); + dbFixBtn.removeClass( 'button-primary' ); + $.ajax({ + type: 'POST', + url: ajaxurl, + data: formData, + success: function (response) { + if ( undefined !== response.data ) { + dbFixBtn.text( response.data.message ); + } + }, + error: function ( jqXHR, textStatus, errorThrown ) { + console.log( "error", errorThrown ); + } + }); + } ); + +}(jQuery)); \ No newline at end of file
js/qsm-common.js+7 −5 modified@@ -102,16 +102,16 @@ create: function (event, ui){ if('answer'=== page){ jQuery(document).trigger('qsm_after_display_result',[ this, ui ]); - jQuery(this).find('a').css({'display':'flex','align-items':'center','justify-content':'center','text-decoration':'none','color':'white'}); - jQuery(this).find('a').html('<p style="margin:0;">'+value+'</p>'); + jQuery(this).find('span').css({'display':'flex','align-items':'center','justify-content':'center','text-decoration':'none','color':'white'}); + jQuery(this).find('span').html('<p style="margin:0;">'+value+'</p>'); } else if ( 'admin' === page ) { - jQuery(this).find('a').css({'display':'flex','align-items':'center','justify-content':'center','text-decoration':'none','color':'white'}); - jQuery(this).find('a').html('<p style="margin:0;">'+value+'</p>'); + jQuery(this).find('span').css({'display':'flex','align-items':'center','justify-content':'center','text-decoration':'none','color':'white'}); + jQuery(this).find('span').html('<p style="margin:0;">'+value+'</p>'); } else { qsmPolarSliderQuestionCreate(questionID ); } if ( isNaN(value) ){ - jQuery(this).find('a').hide(); + jQuery(this).find('span').hide(); } } @@ -175,6 +175,7 @@ jQuery('.question-section-id-'+questionID+' .question-type-polar-s').find( '.right-polar-title img').css('opacity', "0.8"); } + jQuery(document).trigger('qsm_polar_slider_change_after', [ui,questionID, answer1, answer2, value , isReverse]); } function qsmPolarSliderQuestionCreate(questionID){ @@ -187,5 +188,6 @@ '.right-polar-title').css('font-weight', '400'); jQuery('.question-section-id-'+questionID+' .question-type-polar-s img').find( '.right-polar-title img').css('opacity', "0.5"); + jQuery(document).trigger('qsm_polar_slider_create_after', [questionID]); } }(jQuery));
js/qsm-quiz.js+15 −9 modified@@ -22,6 +22,9 @@ var qsmTimerInterval = []; // Cycle through all quizzes _.each(qmn_quiz_data, function (quiz) { let quizID = parseInt(quiz.quiz_id); + if ( !qmn_quiz_data[quizID].hasOwnProperty('timer_limit') && null !== localStorage.getItem('mlw_time_quiz' + quizID) ) { + localStorage.removeItem('mlw_time_quiz' + quizID); + } if ( null == localStorage.getItem('mlw_quiz_start_date' + quizID) ) { localStorage.setItem('mlw_quiz_start_date' + quizID, qmn_ajax_object.start_date); localStorage.setItem('mlw_time_consumed_quiz' + quizID, 1); @@ -338,7 +341,7 @@ var qsmTimerInterval = []; jQuery(document).trigger('qsm_init_progressbar_after', [quizID, qmn_quiz_data]); } QSM.goToPage(quizID, 1); - jQuery(document).on('click', '.qsm-quiz-container-' + quizID + ' .qsm-pagination .qsm-next', function (event) { + jQuery(document).on('click', '.qsm-quiz-container-' + quizID + ' .qsm-next', function (event) { jQuery(document).trigger('qsm_next_button_click_before', [quizID]); event.preventDefault(); let $quizForm = QSM.getQuizForm(quizID); @@ -365,7 +368,7 @@ var qsmTimerInterval = []; } jQuery(document).trigger('qsm_next_button_click_after', [quizID]); }); - jQuery(document).on('click', '.qsm-quiz-container-' + quizID + ' .qsm-pagination .qsm-previous', function (event) { + jQuery(document).on('click', '.qsm-quiz-container-' + quizID + ' .qsm-previous', function (event) { jQuery(document).trigger('qsm_previous_button_click_before', [quizID]); event.preventDefault(); QSM.prevPage(quizID); @@ -1466,7 +1469,7 @@ jQuery(function () { }); }); - jQuery(document).on('change', '.qmn-multiple-choice-input, .qsm_dropdown' , function (e) { + jQuery(document).on('change', '.qmn-multiple-choice-input, .qsm_dropdown, .mlw_answer_date ' , function (e) { let $i_this = jQuery(this); var quizID = jQuery(this).parents('.qsm-quiz-container').find('.qmn_quiz_id').val(); var $quizForm = QSM.getQuizForm(quizID); @@ -1607,6 +1610,8 @@ jQuery(function () { $this.parent('.quiz_section').find('.qsm-file-upload-status').text('').text(obj.message); $this.parent('.quiz_section').find('.qsm-file-upload-status').show(); } + // triggers after file remove + jQuery(document).trigger('qsm_after_file_remove', [$this.parent(), obj]); } }); return false; @@ -1948,13 +1953,14 @@ function qsm_question_quick_result_js(question_id, answer, answer_type = '', sho } } -jQuery(document).on( 'click', '.qsm-quiz-container', function() { - jQuery('.qsm-quiz-container').removeClass('qsm-recently-active'); - jQuery(this).addClass('qsm-recently-active'); +jQuery(document).on('click', function(event) { + if (jQuery(event.target).closest('.qsm-quiz-container').length) { + jQuery('.qsm-quiz-container').removeClass('qsm-recently-active'); + jQuery(event.target).closest('.qsm-quiz-container').addClass('qsm-recently-active'); + } else { + jQuery('.qsm-quiz-container').removeClass('qsm-recently-active'); + } }); -if (jQuery('.qsm-quiz-container').length > 0) { - jQuery('body .qsm-quiz-container:first').addClass('qsm-recently-active'); -} jQuery(document).keydown(function(event) { if (jQuery('.qsm-quiz-container.qsm-recently-active').length) {
mlw_quizmaster2.php+120 −3 modified@@ -2,7 +2,7 @@ /** * Plugin Name: Quiz And Survey Master * Description: Easily and quickly add quizzes and surveys to your website. - * Version: 9.0.1 + * Version: 9.0.2 * Author: ExpressTech * Author URI: https://quizandsurveymaster.com/ * Plugin URI: https://expresstech.io/ @@ -43,7 +43,7 @@ class MLWQuizMasterNext { * @var string * @since 4.0.0 */ - public $version = '9.0.1'; + public $version = '9.0.2'; /** * QSM Alert Manager Object @@ -161,7 +161,14 @@ public function __construct() { $this->add_hooks(); } - //Check admin capabilities + /** + * Check admin capabilities. + * + * @since 9.0.0 + * @param string $check_permission permission type + * + * @return boolean current user has permission + */ public function qsm_is_admin( $check_permission = 'manage_options' ) { if ( ! function_exists( 'wp_get_current_user' ) && file_exists( ABSPATH . "wp-includes/pluggable.php" ) ) { require_once( ABSPATH . "wp-includes/pluggable.php" ); @@ -172,6 +179,81 @@ public function qsm_is_admin( $check_permission = 'manage_options' ) { return ( function_exists( 'wp_get_current_user' ) && function_exists( 'current_user_can' ) && current_user_can( $check_permission ) ); } + /** + * sanitize HTML data. + * HTML is saved as encoded and at ouput same as decoded. encoded html may pass though most of + * the WordPress sanitization function. This function sanitize it to remove + * unfiltered HTML content + * + * @since 9.0.3 + * @param HTML $html html data + * + * @return HTML sanitized HTML + */ + public function sanitize_html( $html = '', $kses = true ) { + if ( empty( $html ) ) { + return $html; + } + return $kses ? wp_kses_post( $html ) : sanitize_text_field( $html ); + } + + /** + * Get failed alter qmn table query list. + * + * @since 9.0.2 + * @return array alter qmn table query list + */ + public function get_failed_alter_table_queries() { + $failed_queries = get_option( 'qmn_failed_alter_table_queries', array() ); + return is_array( $failed_queries ) ? $failed_queries : array(); + } + + /** + * Execute WP db query and save query if failed to execute + * + * @since 9.0.2 + * @param string $query SQL Query + * + * @return boolean query executed or not + */ + public function wpdb_alter_table_query( $query ) { + // Check if admin or empty query. + if ( empty( $query ) || ! function_exists( 'is_admin' ) || ! is_admin() ) { + return false; + } + + global $wpdb; + $query = trim( $query ); + + // check if a query for qsm tables alter only. + if ( empty( $wpdb ) || 0 != stripos( $query, 'ALTER TABLE' ) || false === stripos( $query, 'mlw_' ) ) { + return false; + } + + // Execute query. + $res = $wpdb->query( $query ); + + // Get failed alter table query list. + $failed_queries = $this->get_failed_alter_table_queries(); + + if ( ! empty( $res ) ) { + if ( ! empty( $failed_queries ) && in_array( $query, $failed_queries, true ) ) { + // Remove failed query from list. + $failed_queries = array_diff( $failed_queries, array( $query ) ); + // Update failed queries list. + update_option( 'qmn_failed_alter_table_queries', $failed_queries ); + } + return true; + } elseif ( empty( $failed_queries ) || ! in_array( $query, $failed_queries, true ) ) { + // Add query to the list. + $failed_queries[] = $query; + // Update failed queries list. + update_option( 'qmn_failed_alter_table_queries', $failed_queries ); + } + + return false; + } + /** * Load File Dependencies * @@ -656,6 +738,10 @@ public function setup_admin_menu() { } add_submenu_page( 'options.php', __( 'Settings', 'quiz-master-next' ), __( 'Settings', 'quiz-master-next' ), 'edit_posts', 'mlw_quiz_options', 'qsm_generate_quiz_options' ); add_submenu_page( 'qsm_dashboard', __( 'Results', 'quiz-master-next' ), __( 'Results', 'quiz-master-next' ), 'moderate_comments', 'mlw_quiz_results', 'qsm_generate_admin_results_page' ); + + // Failed Submission. + add_submenu_page( 'qsm_dashboard', __( 'Failed Submission', 'quiz-master-next' ), __( 'Failed Submission', 'quiz-master-next' ), 'moderate_comments', 'mlw_quiz_failed_submission', array( $this, 'admin_failed_submission_page' ) ); + add_submenu_page( 'options.php', __( 'Result Details', 'quiz-master-next' ), __( 'Result Details', 'quiz-master-next' ), 'moderate_comments', 'qsm_quiz_result_details', 'qsm_generate_result_details' ); add_submenu_page( 'qsm_dashboard', __( 'Settings', 'quiz-master-next' ), __( 'Settings', 'quiz-master-next' ), 'manage_options', 'qmn_global_settings', array( 'QMNGlobalSettingsPage', 'display_page' ) ); add_submenu_page( 'qsm_dashboard', __( 'Tools', 'quiz-master-next' ), __( 'Tools', 'quiz-master-next' ), 'manage_options', 'qsm_quiz_tools', 'qsm_generate_quiz_tools' ); @@ -671,6 +757,26 @@ public function setup_admin_menu() { } } + /** + * Failed Submission Table + * + * Display failed submission table. + * + * @since 9.0.2 + * @return void + */ + public function admin_failed_submission_page() { + $file_path = trailingslashit( plugin_dir_path( __FILE__ ) ) . 'php/admin/class-failed-submission.php'; + if ( file_exists( $file_path ) ) { + include_once $file_path; + if ( ! class_exists( 'QmnFailedSubmissions' ) ) { + return; + } + $QmnFailedSubmissions = new QmnFailedSubmissions(); + $QmnFailedSubmissions->render_list_table(); + } + } + /** * Removes Unnecessary Admin Page * @@ -740,6 +846,17 @@ public function qsm_admin_notices() { </div> <?php } + + // Get failed alter table query list. + $failed_queries = $this->get_failed_alter_table_queries(); + if ( ! empty( $failed_queries ) && 0 < count( $failed_queries ) ) { + ?> + <div class="notice notice-warning is-dismissible qmn-database-user-incorrect-permission"> + <p><?php esc_html_e( "It seems your database user doesn't have permission to ALTER TABLE. Please ensure the necessary permissions are in place or contact your hosting provider.", "quiz-master-next" ); ?> <a href="#" qmnnonce="<?php echo esc_attr( wp_create_nonce( 'qmn_check_db' ) ); ?>" class="button button-primary check-db-fix-btn" ><?php esc_html_e( "Check If Already Fixed", "quiz-master-next" ); ?></a> </p> + </div> + <?php + } + }
php/admin/class-failed-submission.php+341 −0 added@@ -0,0 +1,341 @@ +<?php +/** + * Creates the failed submission page within the admin area + * + * @package QSM + * @since 9.0.2 + */ + +if ( ! defined( 'ABSPATH' ) ) { + exit; +} + +/** + * Abort if the class is already exists. + */ +if ( ! class_exists( 'QmnFailedSubmissions' ) && class_exists( 'WP_List_Table' ) ) { + /** + * This class display failed submission list table + * + * @since 9.0.2 + */ + class QmnFailedSubmissions extends WP_List_Table { + + /** + * meta_key name which contain failed submission data + * + * @var object + * @since 9.0.2 + */ + public $meta_key = '_qmn_log_result_insert_data'; + + /** + * Variable to check if ip is enable + * + * @var object + * @since 9.0.2 + */ + public $ip_enabled = false; + + /** + * table_data + * + * @var object + * @since 9.0.2 + */ + private $table_data = array(); + + + /** + * Error log post ids + * + * @var object + * @since 9.0.2 + */ + private $posts = array(); + + /** + * Current Tab + * + * @var object + * @since 9.0.2 + */ + private $current_tab = array(); + + + public function __construct() { + parent::__construct( + array( + 'plural' => 'submissions', + 'singular' => 'submission', + 'ajax' => true, + ) + ); + $this->current_tab = ( empty( $_GET['tab'] ) || 'retrieve' === sanitize_key( $_GET['tab'] ) ) ? 'retrieve' : 'processed'; + + // Get settings. + $settings = (array) get_option( 'qmn-settings' ); + + // ip_collection value 1 means it's disabled. + if ( empty( $settings ) || ! isset( $settings['ip_collection'] ) || '1' != $settings['ip_collection'] ) { + $this->ip_enabled = true; + } + } + + /** + * Prepares the list of items for displaying. + * + * @since 9.0.2 + * + * @return void + */ + public function prepare_items() { + // QMN Error log. + $this->posts = get_posts( + array( + 'post_type' => 'qmn_log', + 'meta_key' => $this->meta_key, + 'post_status' => 'publish', + 'fields' => 'ids', + 'posts_per_page' => -1, + ) + ); + + $this->posts = empty( $this->posts ) ? array() : $this->posts; + $per_page = 20; + if ( ! empty( $this->posts ) ) { + $current_page = intval( $this->get_pagenum() ) - 1; + $post_start_postion = $per_page * $current_page; + + foreach ( $this->posts as $index => $postID ) { + + if ( $post_start_postion > $index || $index >= ( $post_start_postion + $per_page ) ) { + continue; + } + + $data = get_post_meta( $postID, $this->meta_key, true ); + if ( empty( $data ) ) { + continue; + } + + $data = maybe_unserialize( $data ); + if ( ! is_array( $data ) || ( 'processed' === $this->current_tab && empty( $data['processed'] ) ) || ( 'retrieve' === $this->current_tab && ! empty( $data['processed'] ) ) || empty( $data['qmn_array_for_variables'] ) ) { + continue; + } + + $data['qmn_array_for_variables']['post_id'] = $postID; + $this->table_data[] = $data['qmn_array_for_variables']; + } + } + + // pagination. + $this->set_pagination_args( + array( + 'total_items' => count( $this->posts ), + 'per_page' => $per_page, + ) + ); + + // table data. + $this->items = $this->table_data; + + // table headers. + $this->_column_headers = array( + $this->get_columns(), + $this->get_hidden_columns(), + array(), // Sortable column + 'cb', // Primary column + ); + } + + /** + * Gets a list of columns. + * + * @since 9.0.2 + * + * @return array columns list + */ + public function get_columns() { + $columns = array( + 'cb' => '<input type="checkbox" />', + 'post_id' => __( 'ID', 'quiz-master-next' ), + 'quiz_name' => __( 'Quiz Name', 'quiz-master-next' ), + 'quiz_time' => __( 'Time', 'quiz-master-next' ), + 'user_name' => __( 'Name', 'quiz-master-next' ), + 'user_email' => __( 'Email', 'quiz-master-next' ), + ); + + if ( $this->ip_enabled ) { + $columns['user_ip'] = __( 'IP Address', 'quiz-master-next' ); + } + + $columns['submission_action'] = __( 'Action', 'quiz-master-next' ); + + return $columns; + } + + /** + * Gets the list of views available on this table. + * + * @since 9.0.2 + * + * @return array tabs link + */ + protected function get_views() { + $views = array( + 'retrieve' => array( + 'label' => __( 'Resubmit', 'quiz-master-next' ), + ), + 'processed' => array( + 'label' => __( 'Processed', 'quiz-master-next' ), + ), + ); + + $view_links = array(); + + foreach ( $views as $view_id => $view ) { + $view_links[ $view_id ] = '<a href="' . esc_url( admin_url( 'admin.php?page=mlw_quiz_failed_submission&tab=' . $view_id ) ) . '" class="' . ( ( $view_id === $this->current_tab ) ? 'current' : '' ) . '" >' . esc_html( $view['label'] ) . '</a>'; + } + + return $view_links; + } + + /** + * Generates content for a single row of the table. + * + * @since 9.0.2 + * + * @param object|array $submission The current item + * + * @return void + */ + public function single_row( $submission ) { + echo '<tr id="qsm-submission-row-' . esc_attr( $submission['post_id'] ) . '" >'; + $this->single_row_columns( $submission ); + echo '</tr>'; + } + + /** + * Gets a list of hidden columns. + * + * @since 9.0.2 + * + * @return array hidden column name + */ + public function get_hidden_columns() { + return array( + 'post_id', + ); + } + + /** + * Checkbox to select submissions. + * + * @since 9.0.2 + * + * @return html input checkbox + */ + public function column_cb( $submission ) { + return sprintf( + '<input type="checkbox" name="post_id[]" value="%d" /> ', + $submission['post_id'] + ); + } + + /** + * Column value + * + * @since 9.0.2 + * + * @return string specific column value + */ + public function column_default( $submission, $column_name ) { + $column_value = ''; + switch ( $column_name ) { + case 'post_id': + $column_value = $submission['post_id']; + break; + case 'quiz_name': + $column_value = $submission['quiz_name']; + break; + case 'quiz_time': + $column_value = gmdate( 'd-m-Y', strtotime( $submission['time_taken'] ) ); + break; + case 'user_name': + $column_value = $submission['user_name']; + break; + case 'user_email': + $column_value = $submission['user_email']; + break; + case 'user_ip': + $column_value = $submission['user_ip']; + break; + case 'submission_action': + $column_value = '<span id="action-link-' . esc_attr( $submission['post_id'] ) . '">'; + if ( 'processed' === $this->current_tab ) { + $column_value .= '<span class="dashicons dashicons-yes-alt"></span>'; + } else { + $column_value .= '<a href="#" post-id="' . esc_attr( $submission['post_id'] ) . '" class="qmn-retrieve-failed-submission-link" >' . __( 'Resubmit', 'quiz-master-next' ) . '</a>'; + } + $column_value .= '</span>'; + break; + default: + break; + } + + return $column_value; + } + + /** + * Bulk action + * + * @since 9.0.2 + * + * @return array actions + */ + public function get_bulk_actions() { + return array( + 'retrieve' => __( 'Resubmit', 'quiz-master-next' ), + 'trash' => __( 'Delete', 'quiz-master-next' ), + ); + } + + /** + * Render page with this table + * + * @since 9.0.2 + * + * @return HTML failed submission page + */ + public function render_list_table() { + + $this->prepare_items(); + ?> + <!-- header. --> + <div class="qmn-failed-submission wrap" id="qmn-failed-submission-conatiner" > + <!-- heading. --> + <h2 id="result_details" > <?php esc_html_e( 'Failed Submissions', 'quiz-master-next' ); ?> </h2> + <!-- body --> + <div class="qmn-body"> + <!-- Action response notice --> + <div id="qmn-failed-submission-table-message" class="notice display-none-notice" > + <button type="button" class="notice-dismiss"><span class="screen-reader-text"> <?php esc_html_e( 'Dismiss this notice.', 'quiz-master-next' ); ?> </span></button> + <p class="notice-message" ></p> + </div> + <form method='post' id='failed-submission-action-form' action=''> + <div class="submission-filter-wrapper" > + <?php + $this->views(); // render bulk action and pagination + ?> + </div> + <input type="hidden" name="qmnnonce" value="<?php echo esc_attr( wp_create_nonce( 'qmn_failed_submission' ) ); ?>" /> + <?php + $this->display(); // render table + ?> + </form> + </div> + </div> + <?php + } + } +}
php/admin/functions.php+31 −21 modified@@ -78,12 +78,12 @@ function qsm_add_author_column_in_db() { ); if ( empty( $table_col_obj ) ) { - $wpdb->query( 'ALTER TABLE ' . $table . ' ADD ' . $col_name . ' ' . $col_def ); + $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $table . ' ADD ' . $col_name . ' ' . $col_def ); } } } - update_option( 'qsm_update_db_column', '1' ); + update_option( 'qsm_update_db_column', 1 ); } // Update result db @@ -96,11 +96,13 @@ function qsm_add_author_column_in_db() { ) ); if ( empty( $table_result_col_obj ) ) { - if ( $wpdb->query( "ALTER TABLE $result_table_name ADD form_type INT NOT NULL" ) ) { - update_option( 'qsm_update_result_db_column', '1' ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $result_table_name ADD form_type INT NOT NULL" ) ) { + update_option( 'qsm_update_result_db_column', 1 ); } else { $mlwQuizMasterNext->log_manager->add( 'Error Creating Column form_type in' . $result_table_name, "Tried {$wpdb->last_query} but got {$wpdb->last_error}.", 0, 'error' ); } + }else { + update_option( 'qsm_update_result_db_column', 1 ); } } @@ -118,11 +120,13 @@ function qsm_add_author_column_in_db() { ) ); if ( ! empty( $table_quiz_col_obj ) ) { - if ( $wpdb->query( "ALTER TABLE $quiz_table_name CHANGE `system` `quiz_system` INT(11) NOT NULL;" ) ) { - update_option( 'qsm_update_quiz_db_column', '1' ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $quiz_table_name CHANGE `system` `quiz_system` INT(11) NOT NULL;" ) ) { + update_option( 'qsm_update_quiz_db_column', 1 ); } else { $mlwQuizMasterNext->log_manager->add( 'Error Changing Columns system,quiz_system in' . $quiz_table_name, "Tried {$wpdb->last_query} but got {$wpdb->last_error}.", 0, 'error' ); } + }else { + update_option( 'qsm_update_quiz_db_column', 1 ); } } @@ -140,11 +144,13 @@ function qsm_add_author_column_in_db() { ), ARRAY_A ); if ( isset( $table_quiz_result_obj['DATA_TYPE'] ) && 'text' === $table_quiz_result_obj['DATA_TYPE'] ) { - if ( $wpdb->query( "ALTER TABLE $result_table_name CHANGE `quiz_results` `quiz_results` LONGTEXT;" ) ) { - update_option( 'qsm_update_result_db_column_datatype', '1' ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $result_table_name CHANGE `quiz_results` `quiz_results` LONGTEXT;" ) ) { + update_option( 'qsm_update_result_db_column_datatype', 1 ); } else { $mlwQuizMasterNext->log_manager->add( 'Error Changing Columns quiz_results in' . $result_table_name, "Tried {$wpdb->last_query} but got {$wpdb->last_error}.", 0, 'error' ); } + }else { + update_option( 'qsm_update_result_db_column_datatype', 1 ); } } @@ -153,8 +159,7 @@ function qsm_add_author_column_in_db() { * * @since 7.0.3 */ - if ( get_option( 'qsm_add_new_column_question_table_table', '1' ) <= 3 ) { - $total_count_val = get_option( 'qsm_add_new_column_question_table_table', '1' ); + if ( 1 !== intval( get_option( 'qsm_add_new_column_question_table_table', '' ) ) ) { global $wpdb; $question_table_name = $wpdb->prefix . 'mlw_questions'; $table_result_col_obj = $wpdb->get_results( @@ -163,20 +168,21 @@ function qsm_add_author_column_in_db() { ) ); if ( empty( $table_result_col_obj ) ) { - if ( $wpdb->query( "ALTER TABLE $question_table_name ADD deleted_question_bank INT NOT NULL" ) ) { - $inc_val = $total_count_val + 1; - update_option( 'qsm_add_new_column_question_table_table', $inc_val ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $question_table_name ADD deleted_question_bank INT NOT NULL" ) ) { + update_option( 'qsm_add_new_column_question_table_table', 1); } else { $mlwQuizMasterNext->log_manager->add( 'Error Creating Columns deleted_question_bank in' . $question_table_name, "Tried {$wpdb->last_query} but got {$wpdb->last_error}.", 0, 'error' ); } + }else { + update_option( 'qsm_add_new_column_question_table_table', 1); } } /** * Add new column in the results table * * @since 7.3.7 */ - if ( get_option( 'qsm_update_result_db_column_page_url', '' ) != '1' ) { + if ( 1 !== intval( get_option( 'qsm_update_result_db_column_page_url', '' ) ) ) { global $wpdb; $result_table_name = $wpdb->prefix . 'mlw_results'; $table_result_col_obj = $wpdb->get_results( @@ -185,12 +191,14 @@ function qsm_add_author_column_in_db() { ) ); if ( empty( $table_result_col_obj ) ) { - if ( $wpdb->query( "ALTER TABLE $result_table_name ADD page_url varchar(255) NOT NULL" ) ) { - update_option( 'qsm_update_result_db_column_page_url', '1' ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $result_table_name ADD page_url varchar(255) NOT NULL" ) ) { + update_option( 'qsm_update_result_db_column_page_url', 1 ); } else { $error = $wpdb->last_error; $mlwQuizMasterNext->log_manager->add( "Error Creating Column page_url in {$result_table_name}", "Tried {$wpdb->last_query} but got {$error}.", 0, 'error' ); } + }else { + update_option( 'qsm_update_result_db_column_page_url', 1 ); } } @@ -199,7 +207,7 @@ function qsm_add_author_column_in_db() { * * @since 7.3.7 */ - if ( get_option( 'qsm_update_result_db_column_page_name', '' ) != '1' ) { + if ( 1 !== intval( get_option( 'qsm_update_result_db_column_page_name', '' ) ) ) { global $wpdb; $result_table_name = $wpdb->prefix . 'mlw_results'; $table_result_col_obj = $wpdb->get_results( @@ -208,11 +216,13 @@ function qsm_add_author_column_in_db() { ) ); if ( empty( $table_result_col_obj ) ) { - if ( $wpdb->query( "ALTER TABLE $result_table_name ADD page_name varchar(255) NOT NULL" ) ) { - update_option( 'qsm_update_result_db_column_page_name', '1' ); + if ( $mlwQuizMasterNext->wpdb_alter_table_query( "ALTER TABLE $result_table_name ADD page_name varchar(255) NOT NULL" ) ) { + update_option( 'qsm_update_result_db_column_page_name', 1 ); } else { $mlwQuizMasterNext->log_manager->add( 'Error Creating Column page_name in' . $result_table_name, "Tried {$wpdb->last_query} but got {$wpdb->last_error}.", 0, 'error' ); } + }else { + update_option( 'qsm_update_result_db_column_page_name', 1 ); } } @@ -221,7 +231,7 @@ function qsm_add_author_column_in_db() { * * @since 9.0.1 */ - if ( get_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', '' ) != 1 ) { + if ( 1 !== intval( get_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', '' ) ) ) { global $wpdb; $tables_to_convert = array( @@ -235,7 +245,7 @@ function qsm_add_author_column_in_db() { foreach ( $tables_to_convert as $table ) { $query = "ALTER TABLE $table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"; - $result = $wpdb->query($query); + $result = $mlwQuizMasterNext->wpdb_alter_table_query($query); if ( ! $result ) { $success = false;
php/admin/options-page-email-tab.php+2 −2 modified@@ -128,13 +128,13 @@ function qsm_options_emails_tab_content() { ?> <div class="popup-template-span-wrap"> <span class="qsm-text-template-span <?php echo esc_attr( $classname );?>"> - <?php if ( str_contains( $classname, 'qsm-upgrade-popup-variable') ) {?> + <?php if ( false !== strpos( $classname, 'qsm-upgrade-popup-variable') ) {?> <span class="button button-default template-variable qsm-tooltips-icon"><?php echo esc_attr( $variable_key ); ?> <span class="qsm-tooltips qsm-upgrade-tooltip"><?php echo esc_html__( 'Available in pro', 'quiz-master-next' );?></span> </span> <?php } else { ?> <span class="button button-default template-variable"><?php echo esc_attr( $variable_key ); ?></span> - <span class='button click-to-copy'>Click to Copy</span> + <span class='button click-to-copy'><?php esc_html_e('Click to Copy', 'quiz-master-next'); ?></span> <span class="temp-var-seperator"> <span class="dashicons dashicons-editor-help qsm-tooltips-icon"> <span class="qsm-tooltips"><?php echo esc_attr( $variable ); ?></span>
php/admin/options-page-questions-tab.php+45 −6 modified@@ -709,7 +709,7 @@ class="save-page-button button button-primary"><?php esc_html_e( 'Save Questions <?php if ( ! class_exists ( 'QSM_AdvancedTimer' ) ) { ?> <div class="qsm-popup-upgrade-warning"> <img src="<?php echo esc_url( QSM_PLUGIN_URL . 'php/images/info-yellow.png' ); ?>" alt="information"> - <span><?php esc_html_e( 'You can set timer in each page using Advanced Timer Add-on. ', 'quiz-master-next'); echo sprintf( '<a style="margin-right: 5px;font-weight: bolder;" href="%s" target="_blank">%s</a>', esc_url( qsm_get_plugin_link( 'downloads/wordpress-quiz-timer-advanced', 'advanced-timer-popup', 'quiz_editor', 'get_addon', 'qsm_plugin_upsell' ) ), __( 'Get this add-on ', 'quiz-master-next' ) ); esc_html_e( 'and extend your quiz features.', 'quiz-master-next' ); ?></span> + <span><?php esc_html_e( 'You can set timer in each page using Advanced Timer Add-on. ', 'quiz-master-next'); echo sprintf( '<a style="margin-right: 5px;font-weight: bolder;" href="%s" target="_blank">%s</a>', esc_url( qsm_get_plugin_link( 'downloads/wordpress-quiz-timer-advanced', 'advanced-timer-popup', 'quiz_editor', 'get_addon', 'qsm_plugin_upsell' ) ), esc_html__( 'Get this add-on ', 'quiz-master-next' ) ); esc_html_e( 'and extend your quiz features.', 'quiz-master-next' ); ?></span> </div> <?php } ?> </div> @@ -1094,19 +1094,58 @@ function qsm_delete_question_from_database() { add_action( 'wp_ajax_qsm_delete_question_from_database', 'qsm_delete_question_from_database' ); function qsm_bulk_delete_question_from_database() { + // Validate nonce. if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'delete_question_from_database' ) ) { wp_send_json_error( __( 'Nonce verification failed!', 'quiz-master-next' ) ); } - $question_id = isset( $_POST['question_id'] ) ? sanitize_text_field( wp_unslash( $_POST['question_id'] ) ) : 0; - if ( $question_id ) { - global $wpdb, $mlwQuizMasterNext; - $results = $wpdb->query( "DELETE FROM {$wpdb->prefix}mlw_questions WHERE question_id IN ($question_id)" ); + + // check Quiestion ID. + if ( empty( $_POST['question_id'] ) ) { + wp_send_json_error( __( 'Missing question ID.', 'quiz-master-next' ) ); + } + + // Global variables + global $wpdb, $mlwQuizMasterNext; + + // should have delete_published_posts capabilities. + if ( ! $mlwQuizMasterNext->qsm_is_admin( 'delete_published_posts' ) ) { + wp_send_json_error( __( 'You do not have permission to delete questions. Please contact the site administrator.', 'quiz-master-next' ) ); + } + + $question_id = sanitize_text_field( wp_unslash( $_POST['question_id'] ) ); + + $question_id = explode( ',', $question_id ); + + // filter question ids + $question_id = array_filter( $question_id, function( $questionID ) { + return is_numeric( $questionID ) && 0 < intval( $questionID ); + } ); + + // Sanitize and validate the IDs + $question_id = array_map( 'intval', $question_id ); + + if ( ! empty( $question_id ) ) { + // Generate placeholders for each ID + $placeholders = array_fill( 0, count( $question_id ), '%d' ); + + // Construct the query with placeholders + $query = sprintf( + "DELETE FROM {$wpdb->prefix}mlw_questions WHERE question_id IN (%s)", + implode( ', ', $placeholders ) + ); + + // Prepare the query + $query = $wpdb->prepare( $query, $question_id ); + + $results = $wpdb->query( $query ); if ( $results ) { wp_send_json_success( __( 'Questions removed Successfully.', 'quiz-master-next' ) ); }else { - wp_send_json_error( __( 'Question delete failed!', 'quiz-master-next' ) ); $mlwQuizMasterNext->log_manager->add( __('Error 0001 delete questions failed - question IDs:', 'quiz-master-next') . $question_id, '<br><b>Error:</b>' . $wpdb->last_error . ' from ' . $wpdb->last_query, 0, 'error' ); + wp_send_json_error( __( 'Question delete failed!', 'quiz-master-next' ) ); } + } else { + wp_send_json_error( __( 'Question delete failed! Invalid question ID.', 'quiz-master-next' ) ); } } add_action( 'wp_ajax_qsm_bulk_delete_question_from_database', 'qsm_bulk_delete_question_from_database' );
php/admin/options-page-results-page-tab.php+4 −2 modified@@ -36,6 +36,7 @@ function qsm_options_results_tab_content() { 'rest_user_nonce' => wp_create_nonce( 'wp_rest_nonce_' . $quiz_id . '_' . $user_id ), ); wp_localize_script( 'qsm_admin_js', 'qsmResultsObject', $js_data ); + do_action( 'qsm_options_results_tab_content_before' ); ?> <!-- Results Page Section --> @@ -160,13 +161,13 @@ function qsm_options_results_tab_content() { ?> <div class="popup-template-span-wrap"> <span class="qsm-text-template-span <?php echo esc_attr( $classname );?>"> - <?php if ( str_contains( $classname, 'qsm-upgrade-popup-variable') ) {?> + <?php if ( false !== strpos( $classname, 'qsm-upgrade-popup-variable') ) {?> <span class="button button-default template-variable qsm-tooltips-icon"><?php echo esc_attr( $variable_key ); ?> <span class="qsm-tooltips qsm-upgrade-tooltip"><?php echo esc_html__( 'Available in pro', 'quiz-master-next' );?></span> </span> <?php } else { ?> <span class="button button-default template-variable"><?php echo esc_attr( $variable_key ); ?></span> - <span class='button click-to-copy'>Click to Copy</span> + <span class='button click-to-copy'><?php esc_html_e('Click to Copy', 'quiz-master-next'); ?></span> <span class="temp-var-seperator"> <span class="dashicons dashicons-editor-help qsm-tooltips-icon"> <span class="qsm-tooltips"><?php echo esc_attr( $variable ); ?></span> @@ -218,6 +219,7 @@ function qsm_options_results_tab_template(){ <?php esc_html_e( 'Mark as default', 'quiz-master-next' ); ?> </label> <div class="qsm-actions-link-box"> + <?php do_action( 'qsm_add_action_links_before' ); ?> <a href="javascript:void(0)" class="qsm-delete-result-button"><span class="dashicons dashicons-trash"></span></a> <a href="javascript:void(0)" class="qsm-duplicate-result-page-button"><span class="dashicons dashicons-admin-page"></span></a> <a href="javascript:void(0)" class="qsm-toggle-result-page-button"><span class="dashicons dashicons-arrow-down-alt2"></span></a>
php/classes/class-qmn-log-manager.php+3 −6 modified@@ -96,18 +96,15 @@ private function valid_type( $type ) { * @param $type string The type of the log * @return bool|int False if error else id of the newly inserted post */ - public function add( $title = '', $message = '', $parent = 0, $type = null ) { + public function add( $title = '', $message = '', $parent = 0, $type = null, $log_meta = null ) { $log_data = array( 'post_title' => $title, 'post_content' => $message, 'post_parent' => $parent, 'log_type' => $type, ); $settings = (array) get_option( 'qmn-settings' ); - if ( ! empty( $settings['enable_qsm_log'] ) && $settings['enable_qsm_log'] ) { - return $this->insert_log( $log_data ); - } - return false; + return $this->insert_log( $log_data, $log_meta ); } /** @@ -117,7 +114,7 @@ public function add( $title = '', $message = '', $parent = 0, $type = null ) { * @param $log_data Array of data about the log including title, message, and type * @return bool|int False if error else id of the newly inserted post */ - public function insert_log( $log_data = array() ) { + public function insert_log( $log_data = array(), $log_meta = null ) { $defaults = array( 'post_type' => 'qmn_log', 'post_status' => 'publish',
php/classes/class-qmn-plugin-helper.php+72 −3 modified@@ -88,6 +88,72 @@ public function __construct() { add_filter( 'qsm_language_support', array( $this, 'qsm_language_support' ), 10, 3 ); } + /** + * Calls all class functions to check if quiz is setup properly + * + * @param int $quiz_id The ID of the quiz or survey to load. + * @return array An array which contains boolean result of has_proper_quiz, message and/or qmn_quiz_options + */ + public function has_proper_quiz( $quiz_id ) { + if ( empty( $quiz_id ) ) { + return array( + 'res' => false, + 'message' => __( 'Empty Quiz ID.', 'quiz-master-next' ), + ); + } + + $quiz_id = intval( $quiz_id ); + + // Tries to load quiz name to ensure this is a valid ID. + global $mlwQuizMasterNext, $qmn_allowed_visit, $qmn_json_data; + $qmn_json_data = array(); + $qmn_allowed_visit = true; + if ( false === $this->prepare_quiz( $quiz_id ) ) { + return array( + 'res' => false, + 'message' => __( 'It appears that this quiz is not set up correctly.', 'quiz-master-next' ), + ); + } + + $has_result_id = ( ! isset( $_GET['result_id'] ) || '' === $_GET['result_id'] ); + + if ( $has_result_id ) { + global $mlw_qmn_quiz; + $mlw_qmn_quiz = $quiz_id; + } + + $qmn_quiz_options = $mlwQuizMasterNext->quiz_settings->get_quiz_options(); + + if ( $has_result_id ) { + /** + * Filter Quiz Options before Quiz Display + */ + $qmn_quiz_options = apply_filters( 'qsm_shortcode_quiz_options', $qmn_quiz_options ); + } + + // If quiz options isn't found, stop function. + if ( is_null( $qmn_quiz_options ) || ( ! empty( $qmn_quiz_options->deleted ) && 1 == $qmn_quiz_options->deleted ) ) { + return array( + 'res' => false, + 'message' => __( 'This quiz is no longer available.', 'quiz-master-next' ), + ); + } + + // If quiz options isn't found, stop function. + if ( is_null( $qmn_quiz_options ) || empty( $qmn_quiz_options->quiz_name ) ) { + return array( + 'res' => false, + 'message' => __( 'It appears that this quiz is not set up correctly.', 'quiz-master-next' ), + ); + } + + return array( + 'res' => true, + 'message' => __( 'Quiz is setup properly.', 'quiz-master-next' ), + 'qmn_quiz_options' => $qmn_quiz_options, + ); + } + /** * Calls all class functions to initialize quiz * @@ -446,7 +512,7 @@ public function display_question( $slug, $question_id, $quiz_options ) { if ( ! empty( $categories['category_name'] ) ) { $cat_name = implode( ',', $categories['category_name'] ); ?> - <div class="quiz-cat">[<?php echo esc_html( $cat_name ); ?>]</div> + <div class="quiz-cat"><?php echo esc_html( $cat_name ); ?></div> <?php } } @@ -603,7 +669,7 @@ public static function qsm_language_support( $translation_text = '', $translatio /** * Decode HTML Special characters. */ - $translation_text = htmlspecialchars_decode( $translation_text, ENT_QUOTES ); + $translation_text = wp_kses_post( htmlspecialchars_decode( $translation_text, ENT_QUOTES ) ); $translation_slug = sanitize_title( $translation_slug ); $new_text = apply_filters( 'wpml_translate_single_string', $translation_text, $domain, $translation_slug ); if ( 'QSM Answers' === $domain && $new_text == $translation_text ) { @@ -614,7 +680,7 @@ public static function qsm_language_support( $translation_text = '', $translatio } $new_text = apply_filters( 'wpml_translate_single_string', $translation_text, $domain, $translation_slug ); } - $new_text = htmlspecialchars_decode( $new_text, ENT_QUOTES ); + $new_text = wp_kses_post( htmlspecialchars_decode( $new_text, ENT_QUOTES ) ); /** * Return translation for non-default strings. */ @@ -635,7 +701,10 @@ public static function qsm_language_support( $translation_text = '', $translatio if ( false !== $default_key && 0 === strcasecmp( $translation_text, $default_texts[ $default_key ] ) ) { return apply_filters( 'wpml_translate_single_string', $translation_text, 'QSM Defaults', 'quiz_' . $default_key ); } + } elseif ( ! empty( $translation_text ) ) { + $translation_text = wp_kses_post( $translation_text ); } + return $translation_text; }
php/classes/class-qmn-quiz-manager.php+306 −97 modified@@ -38,6 +38,14 @@ class QMNQuizManager { public $mathjax_url = QSM_PLUGIN_JS_URL . '/mathjax/tex-mml-chtml.js'; public $mathjax_version = '3.2.0'; + /** + * Holds failed submission meta_key name + * + * @var object + * @since 9.0.2 + */ + public $meta_key = '_qmn_log_result_insert_data'; + public $qsm_background_email; /** * Main Construct Function @@ -88,8 +96,174 @@ public function add_hooks() { add_action( 'init', array( $this, 'qsm_process_background_email' ) ); add_action('wp_ajax_nopriv_qsm_ajax_login', array( $this, 'qsm_ajax_login' ) ); + // Failed submission resubmit or trash + add_action( 'wp_ajax_qsm_action_failed_submission_table', array( $this, 'process_action_failed_submission_table' ) ); + + // Run failed ALTER TABLE query via ajax on notification button click + add_action( 'wp_ajax_qsm_check_fix_db', array( $this, 'has_alter_table_issue_solved' ) ); } + /** + * Check if alter table issue has been solved by trying failed alter table query + * + * @since 9.0.2 + * + * @return void + */ + public function has_alter_table_issue_solved() { + if ( empty( $_POST['qmnnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['qmnnonce'] ) ), 'qmn_check_db' ) || ! function_exists( 'is_admin' ) || ! is_admin() ) { + wp_send_json_error( + array( + 'status' => 'error', + 'message' => __( 'Unauthorized!', 'quiz-master-next' ), + ) + ); + } else { + global $mlwQuizMasterNext, $wpdb; + $wperror = ''; + // Failed Query has been saved in wrong order sometimes due to order of execution. So run twice + for ( $i = 0; $i < 2; $i++ ) { + // Get failed alter table query list. + $failed_queries = $mlwQuizMasterNext->get_failed_alter_table_queries(); + if ( ! empty( $failed_queries ) ) { + + if ( 0 === $i ) { + $failed_queries = array_reverse( $failed_queries ); + } + + foreach ( $failed_queries as $failed_query ) { + $result = $mlwQuizMasterNext->wpdb_alter_table_query( $failed_query ); + // exit loop if query failed to execute + if ( false === $result ) { + $wperror = $wpdb->last_error; + if ( false !== stripos( $wperror, 'Duplicate' ) ) { + // Remove failed query from list. + $failed_queries = array_diff( $failed_queries, array( $failed_query ) ); + // Update failed queries list. + update_option( 'qmn_failed_alter_table_queries', $failed_queries ); + } + } + } + } + } + + $failed_queries = $mlwQuizMasterNext->get_failed_alter_table_queries(); + if ( ! empty( $failed_queries ) ) { + wp_send_json_error( + array( + 'status' => 'error', + 'message' => $wperror, + ) + ); + } else { + wp_send_json_success( + array( + 'status' => 'success', + 'message' => __( 'Fixed!', 'quiz-master-next' ), + ) + ); + } + } + } + + /** + * Process Bulk action for failed submission table + * + * @since 9.0.2 + * @return void + */ + public function process_action_failed_submission_table() { + + if ( empty( $_POST['post_id'] ) || empty( $_POST['quiz_action'] ) || ! function_exists( 'is_admin' ) || ! is_admin() || empty( $_POST['qmnnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['qmnnonce'] ) ), 'qmn_failed_submission' ) ) { + wp_send_json_error( + array( + 'status' => 'error', + 'message' => __( 'Missing or incorrect input', 'quiz-master-next' ), + ) + ); + } + + $post_ids = is_array( $_POST['post_id'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['post_id'] ) ) : array( sanitize_key( wp_unslash( $_POST['post_id'] ) ) ); + $action = wp_unslash( sanitize_key( $_POST['quiz_action'] ) ); + if ( ! empty( $post_ids ) ) { + foreach ( $post_ids as $postID ) { + + $postID = intval( $postID ); + + // Continue if postID not valid + if ( 0 >= $postID ) { + continue; + } + + $data = get_post_meta( $postID, $this->meta_key, true ); + + if ( empty( $data ) ) { + wp_send_json_error( + array( + 'status' => 'error', + 'message' => __( 'Details not found', 'quiz-master-next' ), + 'data' => $data, + ) + ); + } + + $data = maybe_unserialize( $data ); + + // Retrieve action. + if ( 'retrieve' === $action ) { + $res = $this->add_quiz_results( $data ); + if ( false !== $res ) { + $data['processed'] = 1; + // Mark submission processed. + update_post_meta( $postID, $this->meta_key, maybe_serialize( $data ) ); + + // return success message. + wp_send_json_success( + array( + 'res' => $res, + 'status' => 'success', + 'message' => __( 'Quiz resubmitted successfully.', 'quiz-master-next' ), + ) + ); + } else { + // return error details. + global $wpdb; + wp_send_json_error( + array( + 'status' => 'error', + 'message' => __( 'The system generated following error while resubmitting the result:', 'quiz-master-next' ) . $wpdb->last_error, + ) + ); + } + } elseif ( 'trash' === $action ) { + + // Change Error log post status to trash. Error log contain failed submission data as a post meta + wp_update_post( + array( + 'ID' => $postID, + 'post_status' => 'trash', + ) + ); + + // return success message. + wp_send_json_success( + array( + 'status' => 'success', + 'message' => __( 'Quiz deleted successfully.', 'quiz-master-next' ), + ) + ); + } + } + } + + wp_send_json_error( + array( + 'status' => 'error', + 'message' => __( 'Missing input', 'quiz-master-next' ), + ) + ); + } + /** * @version 8.2.0 * ajax login function @@ -331,29 +505,33 @@ public function qsm_clear_audit_data() { * @return string The content for the shortcode */ public function display_shortcode( $atts ) { + global $wpdb, $mlwQuizMasterNext; $shortcode_args = shortcode_atts( array( 'quiz' => 0, 'question_amount' => 0, ), $atts ); + + // Quiz ID. $quiz = intval( $shortcode_args['quiz'] ); $question_amount = intval( $shortcode_args['question_amount'] ); + // Check, if quiz is setup properly. + $has_proper_quiz = $mlwQuizMasterNext->pluginHelper->has_proper_quiz( $quiz ); + if ( false === $has_proper_quiz['res'] ) { + return $has_proper_quiz['message']; + } + + $qmn_quiz_options = $has_proper_quiz['qmn_quiz_options']; + $return_display = ''; + ob_start(); - global $wpdb, $mlwQuizMasterNext; if ( isset( $_GET['result_id'] ) && '' !== $_GET['result_id'] ) { $result_unique_id = sanitize_text_field( wp_unslash( $_GET['result_id'] ) ); $result = $wpdb->get_row( $wpdb->prepare( "SELECT `result_id`, `quiz_id` FROM {$wpdb->prefix}mlw_results WHERE unique_id = %s", $result_unique_id ), ARRAY_A ); if ( ! empty( $result ) && isset( $result['result_id'] ) ) { - $mlwQuizMasterNext->pluginHelper->prepare_quiz( $result['quiz_id'] ); - $qmn_quiz_options = $mlwQuizMasterNext->quiz_settings->get_quiz_options(); - - // If quiz options isn't found, stop function. - if ( is_null( $qmn_quiz_options ) || 1 == $qmn_quiz_options->deleted ) { - return __( 'This quiz is no longer available.', 'quiz-master-next' ); - } wp_enqueue_style( 'qmn_quiz_common_style', $this->common_css, array(), $mlwQuizMasterNext->version ); wp_style_add_data( 'qmn_quiz_common_style', 'rtl', 'replace' ); @@ -376,34 +554,7 @@ public function display_shortcode( $atts ) { } $return_display .= ob_get_clean(); } else { - global $qmn_allowed_visit; - global $qmn_json_data; - $qmn_json_data = array(); - $qmn_allowed_visit = true; - $success = $mlwQuizMasterNext->pluginHelper->prepare_quiz( $quiz ); - if ( false === $success ) { - return __( 'It appears that this quiz is not set up correctly', 'quiz-master-next' ); - } - - global $mlw_qmn_quiz; - $mlw_qmn_quiz = $quiz; - $return_display = ''; - $qmn_quiz_options = $mlwQuizMasterNext->quiz_settings->get_quiz_options(); - // Legacy variable. - /** - * Filter Quiz Options before Quiz Display - */ - $qmn_quiz_options = apply_filters( 'qsm_shortcode_quiz_options', $qmn_quiz_options ); - - // If quiz options isn't found, stop function. - if ( is_null( $qmn_quiz_options ) || 1 == $qmn_quiz_options->deleted ) { - return __( 'This quiz is no longer available.', 'quiz-master-next' ); - } - - // If quiz options isn't found, stop function. - if ( is_null( $qmn_quiz_options ) || empty( $qmn_quiz_options->quiz_name ) ) { - return __( 'It appears that this quiz is not set up correctly', 'quiz-master-next' ); - } + global $qmn_allowed_visit, $qmn_json_data, $mlw_qmn_quiz; // Loads Quiz Template. wp_enqueue_style( 'qmn_quiz_animation_style', QSM_PLUGIN_CSS_URL . '/animate.css', array(), $mlwQuizMasterNext->version ); @@ -1102,7 +1253,7 @@ public function display_pages( $options, $quiz_data ) { <?php $editor_text = $wp_embed->run_shortcode( $message_before ); $editor_text = preg_replace( '/\s*[\w\/:\.]*youtube.com\/watch\?v=([\w]+)([\w\*\-\?\&\;\%\=\.]*)/i', '<iframe width="420" height="315" src="//www.youtube.com/embed/$1" frameborder="0" allowfullscreen></iframe>', $editor_text ); - echo do_shortcode( wp_kses_post( $editor_text ) ); + echo wp_kses_post( do_shortcode( $editor_text ) ); ?> </div> <?php @@ -1131,7 +1282,7 @@ public function display_pages( $options, $quiz_data ) { <?php $editor_text = $wp_embed->run_shortcode( $message_before ); $editor_text = preg_replace( '/\s*[\w\/:\.]*youtube.com\/watch\?v=([\w]+)([\w\*\-\?\&\;\%\=\.]*)/i', '<iframe width="420" height="315" src="//www.youtube.com/embed/$1" frameborder="0" allowfullscreen></iframe>', $editor_text ); - echo do_shortcode( wp_kses_post( $editor_text ) ); + echo wp_kses_post( do_shortcode( $editor_text ) ); ?> </div> <?php @@ -1142,6 +1293,7 @@ public function display_pages( $options, $quiz_data ) { </div> <?php } + do_action( 'qsm_after_welcome_page', $options, $quiz_data, 'single' ); foreach ( $pages[0] as $question_id ) { $question_list .= $question_id . 'Q'; $question = $questions[ $question_id ]; @@ -1168,7 +1320,7 @@ public function display_pages( $options, $quiz_data ) { // Checks if a hint is entered. if ( ! empty( $question['hints'] ) ) { $hint_data = wp_kses_post( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $question['hints'], "hint-{$question_id}" ) ); - echo '<div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="' . esc_html( $hint_data ) . '">' . esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $options->hint_text, "quiz_hint_text-{$options->quiz_id}" ) ) . '</div>'; + echo '<div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="' . esc_attr( $hint_data ) . '">' . esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $options->hint_text, "quiz_hint_text-{$options->quiz_id}" ) ) . '</div>'; } ?> </div> @@ -1190,7 +1342,7 @@ public function display_pages( $options, $quiz_data ) { <div class='qsm-after-message mlw_qmn_message_end'> <?php $message_after = apply_filters( 'mlw_qmn_template_variable_quiz_page', wpautop( $message_after ), $quiz_data ); - echo do_shortcode( wp_kses_post( $message_after ) ); + echo wp_kses_post( do_shortcode( $message_after ) ); ?> </div> <?php @@ -1246,7 +1398,7 @@ public function display_pages( $options, $quiz_data ) { // Checks if a hint is entered. if ( ! empty( $question['hints'] ) ) { $hint_data = wp_kses_post( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $question['hints'], "hint-{$question_id}" ) ); - echo '<div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="' . esc_html( $hint_data ) . '">' . esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $options->hint_text, "quiz_hint_text-{$options->quiz_id}" ) ) . '</div>'; + echo '<div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="' . esc_attr( $hint_data ) . '">' . esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $options->hint_text, "quiz_hint_text-{$options->quiz_id}" ) ) . '</div>'; } ?> </div> @@ -1285,7 +1437,7 @@ public function display_pages( $options, $quiz_data ) { <div class='qsm-after-message mlw_qmn_message_end'> <?php $message_after = apply_filters( 'mlw_qmn_template_variable_quiz_page', wpautop( $message_after ), $quiz_data ); - echo do_shortcode( wp_kses_post( $message_after ) ); + echo wp_kses_post( do_shortcode( $message_after ) ); ?> </div> <?php @@ -1353,7 +1505,7 @@ public function display_begin_section( $qmn_quiz_options, $qmn_array_for_variabl ?> <div class='mlw_qmn_message_before'> <?php - echo do_shortcode( wp_kses_post( $editor_text ) ); + echo wp_kses_post( do_shortcode( $editor_text ) ); ?> </div> <?php @@ -1423,19 +1575,21 @@ public function display_questions( $qmn_quiz_options, $qmn_quiz_questions, $qmn_ $mlwQuizMasterNext->pluginHelper->display_question( $mlw_question->question_type_new, $mlw_question->question_id, $qmn_quiz_options ); if ( 0 == $mlw_question->comments ) { ?> + <label class="qsm_accessibility_label" for="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>"><?php echo esc_attr( "Comment" ); ?></label> <input type="text" class="mlw_qmn_question_comment" id="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>" name="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>" placeholder="<?php echo esc_attr( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $qmn_quiz_options->comment_field_text, "quiz_comment_field_text-{$qmn_quiz_options->quiz_id}" ) ); ?>" onclick="qmnClearField(this)" /><br /> <?php } if ( 2 == $mlw_question->comments ) { ?> + <label class="qsm_accessibility_label" for="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>"><?php echo esc_attr( "Comment" ); ?></label> <textarea cols="70" rows="5" class="mlw_qmn_question_comment" id="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>" name="mlwComment<?php echo esc_attr( $mlw_question->question_id ); ?>" placeholder="<?php echo esc_attr( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $qmn_quiz_options->comment_field_text, "quiz_comment_field_text-{$qmn_quiz_options->quiz_id}" ) ); ?>" onclick="qmnClearField(this)"></textarea><br /> <?php } // Checks if a hint is entered. if ( ! empty( $mlw_question->hints ) ) { $hint_data = wp_kses_post( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $mlw_question->hints, "hint-{$mlw_question->question_id}" ) ); ?> - <div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="<?php echo esc_html( $hint_data );?>"><?php echo esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $qmn_quiz_options->hint_text, "quiz_hint_text-{$qmn_quiz_options->quiz_id}" ) ); ?></div><br /><br /> + <div class="qsm-hint qsm_hint mlw_qmn_hint_link qsm_tooltip" title="<?php echo esc_attr( $hint_data );?>"><?php echo esc_html( $mlwQuizMasterNext->pluginHelper->qsm_language_support( $qmn_quiz_options->hint_text, "quiz_hint_text-{$qmn_quiz_options->quiz_id}" ) ); ?></div><br /><br /> <?php } ?> @@ -1487,7 +1641,7 @@ public function display_comment_section( $qmn_quiz_options, $qmn_array_for_varia $message_comments = $mlwQuizMasterNext->pluginHelper->qsm_language_support( htmlspecialchars_decode( $qmn_quiz_options->message_comment, ENT_QUOTES ), "quiz_message_comment-{$qmn_quiz_options->quiz_id}" ); $message_comments = apply_filters( 'mlw_qmn_template_variable_quiz_page', wpautop( $message_comments ), $qmn_array_for_variables ); ?> - <label for="mlwQuizComments" class="mlw_qmn_comment_section_text"><?php echo do_shortcode( wp_kses_post( $message_comments ) ); ?></label><br /> + <label for="mlwQuizComments" class="mlw_qmn_comment_section_text"><?php echo wp_kses_post( do_shortcode( $message_comments ) ); ?></label><br /> <textarea cols="60" rows="10" id="mlwQuizComments" name="mlwQuizComments" class="qmn_comment_section"></textarea> </div> <?php @@ -1525,7 +1679,7 @@ public function display_end_section( $qmn_quiz_options, $qmn_array_for_variables <?php $message_end = $mlwQuizMasterNext->pluginHelper->qsm_language_support( htmlspecialchars_decode( $qmn_quiz_options->message_end_template, ENT_QUOTES ), "quiz_message_end_template-{$qmn_quiz_options->quiz_id}" ); $message_end = apply_filters( 'mlw_qmn_template_variable_quiz_page', wpautop( $message_end ), $qmn_array_for_variables ); - echo do_shortcode( wp_kses_post( $message_end ) ); + echo wp_kses_post( do_shortcode( $message_end ) ); ?> </span> <br /><br /> @@ -1725,6 +1879,89 @@ public function qsm_get_quiz_to_reload() { exit; } + /** + * Add quiz result + * + * @since 9.0.2 + * @param array $data required data ( i.e. qmn_array_for_variables, results_array, unique_id, http_referer, form_type ) for adding quiz result + * + * @return boolean results added or not + */ + private function add_quiz_results( $data ) { + global $wpdb; + if ( empty( $wpdb ) || empty( $data['qmn_array_for_variables'] ) || empty( $data['results_array'] ) || empty( $data['unique_id'] ) || empty( $data['http_referer'] ) || ! isset( $data['form_type'] ) ) { + return false; + } + + // Inserts the responses in the database. + $table_name = $wpdb->prefix . 'mlw_results'; + + // Temporarily suppress error reporting + $wpdb->suppress_errors(); + + try { + $res = $wpdb->insert( + $table_name, + array( + 'quiz_id' => $data['qmn_array_for_variables']['quiz_id'], + 'quiz_name' => $data['qmn_array_for_variables']['quiz_name'], + 'quiz_system' => $data['qmn_array_for_variables']['quiz_system'], + 'point_score' => $data['qmn_array_for_variables']['total_points'], + 'correct_score' => $data['qmn_array_for_variables']['total_score'], + 'correct' => $data['qmn_array_for_variables']['total_correct'], + 'total' => $data['qmn_array_for_variables']['total_questions'], + 'name' => $data['qmn_array_for_variables']['user_name'], + 'business' => $data['qmn_array_for_variables']['user_business'], + 'email' => $data['qmn_array_for_variables']['user_email'], + 'phone' => $data['qmn_array_for_variables']['user_phone'], + 'user' => $data['qmn_array_for_variables']['user_id'], + 'user_ip' => $data['qmn_array_for_variables']['user_ip'], + 'time_taken' => $data['qmn_array_for_variables']['time_taken'], + 'time_taken_real' => gmdate( 'Y-m-d H:i:s', strtotime( $data['qmn_array_for_variables']['time_taken'] ) ), + 'quiz_results' => maybe_serialize( $data['results_array'] ), + 'deleted' => 0, + 'unique_id' => $data['unique_id'], + 'form_type' => $data['form_type'], + 'page_url' => $data['http_referer'], + 'page_name' => url_to_postid( $data['http_referer'] ) ? get_the_title( url_to_postid( $data['http_referer'] ) ) : '', + ), + array( + '%d', + '%s', + '%d', + '%f', + '%d', + '%d', + '%d', + '%s', + '%s', + '%s', + '%s', + '%d', + '%s', + '%s', + '%s', + '%s', + '%d', + '%s', + '%d', + '%s', + '%s', + ) + ); + if ( false === $res ) { + // Throw exception + throw new Exception( 'Database insert failed.' ); + } + // If insert is successful, return response + return $res; + } catch ( Exception $e ) { + return false; + } + + return false; + } + /** * Perform The Quiz/Survey Submission * @@ -1804,6 +2041,7 @@ public function submit_results( $qmn_quiz_options, $qmn_array_for_variables ) { } $qmn_array_for_variables['hidden_questions'] = $hidden_questions; $qmn_array_for_variables = apply_filters( 'qsm_result_variables', $qmn_array_for_variables ); + $error_details = ""; if ( ! isset( $_POST['mlw_code_captcha'] ) || ( isset( $_POST['mlw_code_captcha'], $_POST['mlw_user_captcha'] ) && sanitize_text_field( wp_unslash( $_POST['mlw_user_captcha'] ) ) == sanitize_text_field( wp_unslash( $_POST['mlw_code_captcha'] ) ) ) ) { $qsm_check_answers_return = $this->check_answers( $qmn_quiz_options, $qmn_array_for_variables ); $qmn_array_for_variables = array_merge( $qmn_array_for_variables, $qsm_check_answers_return ); @@ -1852,67 +2090,36 @@ public function submit_results( $qmn_quiz_options, $qmn_array_for_variables ) { array( 'result_id' => $results_id ) ); if ( false === $results_update ) { - $mlwQuizMasterNext->log_manager->add( 'Error 0001', $wpdb->last_error . ' from ' . $wpdb->last_query, 0, 'error' ); + $error_details = $wpdb->last_error; + $mlwQuizMasterNext->log_manager->add( 'Error 0001', $error_details . ' from ' . $wpdb->last_query, 0, 'error' ); } } else { $http_referer = isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : ''; if ( 254 < strlen($http_referer) ) { $results_array['page_url'] = $http_referer; $http_referer = substr($http_referer, 0, 254); } - $results_insert = $wpdb->insert( - $table_name, - array( - 'quiz_id' => $qmn_array_for_variables['quiz_id'], - 'quiz_name' => $qmn_array_for_variables['quiz_name'], - 'quiz_system' => $qmn_array_for_variables['quiz_system'], - 'point_score' => $qmn_array_for_variables['total_points'], - 'correct_score' => $qmn_array_for_variables['total_score'], - 'correct' => $qmn_array_for_variables['total_correct'], - 'total' => $qmn_array_for_variables['total_questions'], - 'name' => $qmn_array_for_variables['user_name'], - 'business' => $qmn_array_for_variables['user_business'], - 'email' => $qmn_array_for_variables['user_email'], - 'phone' => $qmn_array_for_variables['user_phone'], - 'user' => $qmn_array_for_variables['user_id'], - 'user_ip' => $qmn_array_for_variables['user_ip'], - 'time_taken' => $qmn_array_for_variables['time_taken'], - 'time_taken_real' => gmdate( 'Y-m-d H:i:s', strtotime( $qmn_array_for_variables['time_taken'] ) ), - 'quiz_results' => maybe_serialize( $results_array ), - 'deleted' => 0, - 'unique_id' => $unique_id, - 'form_type' => isset( $qmn_quiz_options->form_type ) ? $qmn_quiz_options->form_type : 0, - 'page_url' => $http_referer, - 'page_name' => url_to_postid( $http_referer ) ? get_the_title( url_to_postid( $http_referer ) ) : '', - ), - array( - '%d', - '%s', - '%d', - '%f', - '%d', - '%d', - '%d', - '%s', - '%s', - '%s', - '%s', - '%d', - '%s', - '%s', - '%s', - '%s', - '%d', - '%s', - '%d', - '%s', - '%s', - ) + $insert_data = array( + 'qmn_array_for_variables' => $qmn_array_for_variables, + 'results_array' => $results_array, + 'unique_id' => $unique_id, + 'form_type' => isset( $qmn_quiz_options->form_type ) ? $qmn_quiz_options->form_type : 0, + 'http_referer' => $http_referer, ); + $results_insert = $this->add_quiz_results( $insert_data ); $results_id = $wpdb->insert_id; if ( false === $results_insert ) { $quiz_submitted_data = qsm_printTableRows($qmn_array_for_variables); - $mlwQuizMasterNext->log_manager->add( __('Error 0001 submission failed - Quiz ID:', 'quiz-master-next') . $qmn_array_for_variables['quiz_id'], '<b>Quiz data:</b> ' . $quiz_submitted_data . ' <br/><b>Quiz answers:</b> ' . maybe_serialize( $results_array ) . '<br><b>Error:</b>' . $wpdb->last_error . ' from ' . $wpdb->last_query, 0, 'error' ); + $error_details = $wpdb->last_error; + $mlwQuizMasterNext->log_manager->add( + __('Error 0001 submission failed - Quiz ID:', 'quiz-master-next') . $qmn_array_for_variables['quiz_id'], + '<b>Quiz data:</b> ' . $quiz_submitted_data . ' <br/><b>Quiz answers:</b> ' . maybe_serialize( $results_array ) . '<br><b>Error:</b>' . $error_details . ' from ' . $wpdb->last_query, + 0, + 'error', + array( + 'result_insert_data' => maybe_serialize( $insert_data ), + ) + ); $mlwQuizMasterNext->audit_manager->new_audit( 'Submit Quiz by ' . $qmn_array_for_variables['user_name'] .' - ' .$qmn_array_for_variables['user_ip'], $qmn_array_for_variables['quiz_id'], wp_json_encode( $qmn_array_for_variables ) ); } } @@ -1928,13 +2135,14 @@ public function submit_results( $qmn_quiz_options, $qmn_array_for_variables ) { // Determines redirect/results page. $results_pages = $this->display_results_text( $qmn_quiz_options, $qmn_array_for_variables ); if ( 1 === intval( $qmn_quiz_options->store_responses ) && ! $qmn_array_for_variables['response_saved'] ) { - $result_display .= '<div class="qsm-result-page-warning">' . __('Your responses are not being saved in the database due to a technical issue. Please contact the website administrator for assistance.', 'quiz-master-next') . '</div>'; + $result_display .= '<div class="qsm-result-page-warning">' . __("Sorry, there's an issue in saving your responses. Please let the website admin know about it.", "quiz-master-next") . '</div>'; } $result_display .= $results_pages['display']; $result_display = apply_filters( 'qmn_after_results_text', $result_display, $qmn_quiz_options, $qmn_array_for_variables ); $result_display .= $this->display_social( $qmn_quiz_options, $qmn_array_for_variables ); $result_display = apply_filters( 'qmn_after_social_media', $result_display, $qmn_quiz_options, $qmn_array_for_variables ); + $qmn_quiz_options = apply_filters( 'qmn_retake_quiz_button_before', $qmn_quiz_options ); if ( 1 == $qmn_quiz_options->enable_retake_quiz_button ) { $result_display .= '<form method="POST">'; $result_display .= '<input type="hidden" value="' . $qmn_array_for_variables['quiz_id'] . '" name="qsm_retake_quiz_id" />'; @@ -2010,6 +2218,7 @@ public function submit_results( $qmn_quiz_options, $qmn_array_for_variables ) { 'result_status' => array( 'save_response' => $qmn_array_for_variables['response_saved'], 'id' => $qmn_array_for_variables['result_unique_id'], + 'error_details' => substr( $error_details, 0, 15 ), ), ); $return_array = apply_filters( 'qsm_submit_results_return_array', $return_array, $qmn_array_for_variables );
php/classes/class-qsm-contact-manager.php+6 −6 modified@@ -438,7 +438,7 @@ public static function generate_contact_field( $field, $index, $quiz_options, $d $class = apply_filters( 'qsm_contact_text_field_class', $class, $field['use'] ); if ( ! isset( $field['hide_label'] ) || 'true' != $field['hide_label'] ) { ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <?php } ?> <input type='text' class='<?php echo esc_attr( $class ); ?>' <?php echo $fieldAttr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> /> <?php @@ -459,7 +459,7 @@ public static function generate_contact_field( $field, $index, $quiz_options, $d $fieldAttr .= " placeholder='" . esc_attr( wp_strip_all_tags( $field_placeholder ) ) . "' "; if ( ! isset( $field['hide_label'] ) || 'true' != $field['hide_label'] ) { ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <?php } ?> <input type='email' class='mlwEmail <?php echo esc_attr( $class ); ?>' <?php echo $fieldAttr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> /> <?php @@ -483,7 +483,7 @@ public static function generate_contact_field( $field, $index, $quiz_options, $d } $class = apply_filters( 'qsm_contact_date_field_class', $class, $field['use'] ); ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <input type='date' class='<?php echo esc_attr( $class ); ?>' <?php echo $fieldAttr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> value='' /> <?php break; @@ -500,7 +500,7 @@ public static function generate_contact_field( $field, $index, $quiz_options, $d $fieldAttr .= " placeholder='" . esc_attr( wp_strip_all_tags( $field_placeholder ) ) . "' "; if ( ! isset( $field['hide_label'] ) || 'true' != $field['hide_label'] ) { ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <?php } ?> <input type='url' class='mlwUrl <?php echo esc_attr( $class ); ?>' <?php echo $fieldAttr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> /> <?php @@ -531,7 +531,7 @@ public static function generate_contact_field( $field, $index, $quiz_options, $d $fieldAttr .= " placeholder='" . esc_attr( wp_strip_all_tags( $field_placeholder ) ) . "' "; if ( ! isset( $field['hide_label'] ) || 'true' != $field['hide_label'] ) { ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <?php } ?> <input type='number' class='mlwRequiredNumber <?php echo esc_attr( $class ); ?>' <?php echo $fieldAttr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> <?php if ( isset( $field['maxlength'] ) && 0 < intval( $field['maxlength'] ) ) : ?>maxlength='<?php echo intval( $field['maxlength'] ); ?>' oninput='maxLengthCheck(this)' <?php endif; ?> /> <?php @@ -584,7 +584,7 @@ class="qmn_quiz_radio" // If REQUIRED is set then assigning the required class if ( isset( $field['options'] ) ) { ?> - <span class='mlw_qmn_question qsm_question'><?php echo esc_attr( $field_label ); ?></span> + <span class='mlw_qmn_question qsm_question'><label for="contact_field_<?php echo esc_attr( $index ) ?>"><?php echo esc_attr( $field_label ); ?></label></span> <select class='<?php echo esc_attr( $class ); ?>' name='contact_field_<?php echo esc_attr( $index ); ?>' id='contact_field_<?php echo esc_attr( $index ); ?>'> <?php if ( ! isset( $field['use_default_option'] ) || 'true' != $field['use_default_option'] ) { ?> <option value=''>
php/classes/class-qsm-emails.php+1 −1 modified@@ -67,7 +67,7 @@ public static function send_emails( $transient_id ) { } if ( ! empty($condition['extra_condition']) && 'category' == $main_condition ) { $category = $condition['extra_condition']; - if ( str_contains($category, 'qsm-cat-') ) { + if ( false !== strpos( $category, 'qsm-cat-') ) { $cat_id = intval( str_replace( 'qsm-cat-', '', $category ) ); $term = get_term( $cat_id ); if ( $term ) {
php/classes/class-qsm-fields.php+1 −0 modified@@ -163,6 +163,7 @@ public static function generate_section( $fields, $section ) { <div id="quiz_submission" class="quiz_style_tab_content" style="display:none"> <table class="form-table" style="width: 100%;"> <?php + $settings = apply_filters( 'qsm_quiz_submission_section_before', $settings, $fields ); // Cycles through each field foreach ( $fields as $field ) { // Generate the field
php/classes/class-qsm-install.php+187 −175 modified@@ -1362,64 +1362,64 @@ public static function install() { if ( $wpdb->get_var( "SHOW TABLES LIKE '$quiz_table_name'" ) != $quiz_table_name ) { $sql = "CREATE TABLE $quiz_table_name ( - quiz_id mediumint(9) NOT NULL AUTO_INCREMENT, - quiz_name TEXT NOT NULL, - message_before TEXT NOT NULL, - message_after LONGTEXT NOT NULL, - message_comment TEXT NOT NULL, - message_end_template TEXT NOT NULL, - user_email_template LONGTEXT NOT NULL, - admin_email_template TEXT NOT NULL, - submit_button_text TEXT NOT NULL, - name_field_text TEXT NOT NULL, - business_field_text TEXT NOT NULL, - email_field_text TEXT NOT NULL, - phone_field_text TEXT NOT NULL, - comment_field_text TEXT NOT NULL, - email_from_text TEXT NOT NULL, - question_answer_template TEXT NOT NULL, - leaderboard_template TEXT NOT NULL, - quiz_system INT NOT NULL, - randomness_order INT NOT NULL, - loggedin_user_contact INT NOT NULL, - show_score INT NOT NULL, - send_user_email INT NOT NULL, - send_admin_email INT NOT NULL, - contact_info_location INT NOT NULL, - user_name INT NOT NULL, - user_comp INT NOT NULL, - user_email INT NOT NULL, - user_phone INT NOT NULL, - admin_email TEXT NOT NULL, - comment_section INT NOT NULL, - question_from_total INT NOT NULL, - total_user_tries INT NOT NULL, - total_user_tries_text TEXT NOT NULL, - certificate_template TEXT NOT NULL, - social_media INT NOT NULL, - social_media_text TEXT NOT NULL, - pagination INT NOT NULL, - pagination_text TEXT NOT NULL, - timer_limit INT NOT NULL, - quiz_stye TEXT NOT NULL, - question_numbering INT NOT NULL, - quiz_settings TEXT NOT NULL, - theme_selected TEXT NOT NULL, - last_activity DATETIME NOT NULL, - require_log_in INT NOT NULL, - require_log_in_text TEXT NOT NULL, - limit_total_entries INT NOT NULL, - limit_total_entries_text TEXT NOT NULL, - scheduled_timeframe TEXT NOT NULL, - scheduled_timeframe_text TEXT NOT NULL, - disable_answer_onselect INT NOT NULL, - ajax_show_correct INT NOT NULL, - quiz_views INT NOT NULL, - quiz_taken INT NOT NULL, - deleted INT NOT NULL, - quiz_author_id INT NOT NULL, - PRIMARY KEY (quiz_id) - ) $charset_collate;"; + quiz_id mediumint(9) NOT NULL AUTO_INCREMENT, + quiz_name TEXT NOT NULL, + message_before TEXT NOT NULL, + message_after LONGTEXT NOT NULL, + message_comment TEXT NOT NULL, + message_end_template TEXT NOT NULL, + user_email_template LONGTEXT NOT NULL, + admin_email_template TEXT NOT NULL, + submit_button_text TEXT NOT NULL, + name_field_text TEXT NOT NULL, + business_field_text TEXT NOT NULL, + email_field_text TEXT NOT NULL, + phone_field_text TEXT NOT NULL, + comment_field_text TEXT NOT NULL, + email_from_text TEXT NOT NULL, + question_answer_template TEXT NOT NULL, + leaderboard_template TEXT NOT NULL, + quiz_system INT NOT NULL, + randomness_order INT NOT NULL, + loggedin_user_contact INT NOT NULL, + show_score INT NOT NULL, + send_user_email INT NOT NULL, + send_admin_email INT NOT NULL, + contact_info_location INT NOT NULL, + user_name INT NOT NULL, + user_comp INT NOT NULL, + user_email INT NOT NULL, + user_phone INT NOT NULL, + admin_email TEXT NOT NULL, + comment_section INT NOT NULL, + question_from_total INT NOT NULL, + total_user_tries INT NOT NULL, + total_user_tries_text TEXT NOT NULL, + certificate_template TEXT NOT NULL, + social_media INT NOT NULL, + social_media_text TEXT NOT NULL, + pagination INT NOT NULL, + pagination_text TEXT NOT NULL, + timer_limit INT NOT NULL, + quiz_stye TEXT NOT NULL, + question_numbering INT NOT NULL, + quiz_settings TEXT NOT NULL, + theme_selected TEXT NOT NULL, + last_activity DATETIME NOT NULL, + require_log_in INT NOT NULL, + require_log_in_text TEXT NOT NULL, + limit_total_entries INT NOT NULL, + limit_total_entries_text TEXT NOT NULL, + scheduled_timeframe TEXT NOT NULL, + scheduled_timeframe_text TEXT NOT NULL, + disable_answer_onselect INT NOT NULL, + ajax_show_correct INT NOT NULL, + quiz_views INT NOT NULL, + quiz_taken INT NOT NULL, + deleted INT NOT NULL, + quiz_author_id INT NOT NULL, + PRIMARY KEY (quiz_id) + ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); @@ -1429,90 +1429,102 @@ public static function install() { if ( ! $multiple_category ) { add_option( 'qsm_multiple_category_enabled', gmdate( time() ) ); } + update_option( 'qsm_update_db_column', 1 ); + update_option( 'qsm_update_quiz_db_column', 1 ); + update_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', 1 ); } if ( $wpdb->get_var( "SHOW TABLES LIKE '$question_table_name'" ) != $question_table_name ) { $sql = "CREATE TABLE $question_table_name ( - question_id mediumint(9) NOT NULL AUTO_INCREMENT, - quiz_id INT NOT NULL, - question_name TEXT NOT NULL, - answer_array TEXT NOT NULL, - answer_one TEXT NOT NULL, - answer_one_points INT NOT NULL, - answer_two TEXT NOT NULL, - answer_two_points INT NOT NULL, - answer_three TEXT NOT NULL, - answer_three_points INT NOT NULL, - answer_four TEXT NOT NULL, - answer_four_points INT NOT NULL, - answer_five TEXT NOT NULL, - answer_five_points INT NOT NULL, - answer_six TEXT NOT NULL, - answer_six_points INT NOT NULL, - correct_answer INT NOT NULL, - question_answer_info TEXT NOT NULL, - comments INT NOT NULL, - hints TEXT NOT NULL, - question_order INT NOT NULL, - question_type INT NOT NULL, - question_type_new TEXT NOT NULL, - question_settings TEXT NOT NULL, - category TEXT NOT NULL, - deleted INT NOT NULL, - deleted_question_bank INT NOT NULL, - PRIMARY KEY (question_id) - ) $charset_collate;"; + question_id mediumint(9) NOT NULL AUTO_INCREMENT, + quiz_id INT NOT NULL, + question_name TEXT NOT NULL, + answer_array TEXT NOT NULL, + answer_one TEXT NOT NULL, + answer_one_points INT NOT NULL, + answer_two TEXT NOT NULL, + answer_two_points INT NOT NULL, + answer_three TEXT NOT NULL, + answer_three_points INT NOT NULL, + answer_four TEXT NOT NULL, + answer_four_points INT NOT NULL, + answer_five TEXT NOT NULL, + answer_five_points INT NOT NULL, + answer_six TEXT NOT NULL, + answer_six_points INT NOT NULL, + correct_answer INT NOT NULL, + question_answer_info TEXT NOT NULL, + comments INT NOT NULL, + hints TEXT NOT NULL, + question_order INT NOT NULL, + question_type INT NOT NULL, + question_type_new TEXT NOT NULL, + question_settings TEXT NOT NULL, + category TEXT NOT NULL, + deleted INT NOT NULL, + deleted_question_bank INT NOT NULL, + PRIMARY KEY (question_id) + ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); + update_option( 'qsm_add_new_column_question_table_table', 1); + update_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', 1 ); } if ( $wpdb->get_var( "SHOW TABLES LIKE '$results_table_name'" ) != $results_table_name ) { $sql = "CREATE TABLE $results_table_name ( - result_id mediumint(9) NOT NULL AUTO_INCREMENT, - quiz_id INT NOT NULL, - quiz_name TEXT NOT NULL, - quiz_system INT NOT NULL, - point_score FLOAT NOT NULL, - correct_score INT NOT NULL, - correct INT NOT NULL, - total INT NOT NULL, - name TEXT NOT NULL, - business TEXT NOT NULL, - email TEXT NOT NULL, - phone TEXT NOT NULL, - user INT NOT NULL, - user_ip TEXT NOT NULL, - time_taken TEXT NOT NULL, - time_taken_real DATETIME NOT NULL, - quiz_results MEDIUMTEXT NOT NULL, - deleted INT NOT NULL, - unique_id varchar(100) NOT NULL, - form_type INT NOT NULL, - page_name varchar(255) NOT NULL, - page_url varchar(255) NOT NULL, - UNIQUE KEY (unique_id), - PRIMARY KEY (result_id) - ) $charset_collate;"; + result_id mediumint(9) NOT NULL AUTO_INCREMENT, + quiz_id INT NOT NULL, + quiz_name TEXT NOT NULL, + quiz_system INT NOT NULL, + point_score FLOAT NOT NULL, + correct_score INT NOT NULL, + correct INT NOT NULL, + total INT NOT NULL, + name TEXT NOT NULL, + business TEXT NOT NULL, + email TEXT NOT NULL, + phone TEXT NOT NULL, + user INT NOT NULL, + user_ip TEXT NOT NULL, + time_taken TEXT NOT NULL, + time_taken_real DATETIME NOT NULL, + quiz_results LONGTEXT NOT NULL, + deleted INT NOT NULL, + unique_id varchar(100) NOT NULL, + form_type INT NOT NULL, + page_name varchar(255) NOT NULL, + page_url varchar(255) NOT NULL, + UNIQUE KEY (unique_id), + PRIMARY KEY (result_id) + ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); + update_option( 'qsm_update_db_column', 1 ); + update_option( 'qsm_update_result_db_column_datatype', 1 ); + update_option( 'qsm_update_result_db_column', 1 ); + update_option( 'qsm_update_result_db_column_page_name', 1 ); + update_option( 'qsm_update_result_db_column_page_url', 1 ); + update_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', 1 ); } if ( $wpdb->get_var( "SHOW TABLES LIKE '$audit_table_name'" ) != $audit_table_name ) { $sql = "CREATE TABLE $audit_table_name ( - trail_id mediumint(9) NOT NULL AUTO_INCREMENT, - action_user TEXT NOT NULL, - action TEXT NOT NULL, - quiz_id TEXT NOT NULL, - quiz_name TEXT NOT NULL, - form_data TEXT NOT NULL, - time TEXT NOT NULL, - PRIMARY KEY (trail_id) - ) $charset_collate;"; + trail_id mediumint(9) NOT NULL AUTO_INCREMENT, + action_user TEXT NOT NULL, + action TEXT NOT NULL, + quiz_id TEXT NOT NULL, + quiz_name TEXT NOT NULL, + form_data TEXT NOT NULL, + time TEXT NOT NULL, + PRIMARY KEY (trail_id) + ) $charset_collate;"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); + update_option( 'qsm_update_db_column_charset_utf8mb4_unicode_ci', 1 ); } if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}mlw_question_terms'" ) != "{$wpdb->prefix}mlw_question_terms" ) { @@ -1610,27 +1622,27 @@ public function update() { // Update 0.5 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'comment_section'" ) != 'comment_section' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD comment_field_text TEXT NOT NULL AFTER phone_field_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $sql = 'ALTER TABLE ' . $table_name . ' ADD comment_section INT NOT NULL AFTER admin_email'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $sql = 'ALTER TABLE ' . $table_name . ' ADD message_comment TEXT NOT NULL AFTER message_after'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET comment_field_text='Comments', comment_section=1, message_comment='Enter You Text Here'"; $results = $wpdb->query( $update_sql ); } // Update 0.9.4 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'randomness_order'" ) != 'randomness_order' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD randomness_order INT NOT NULL AFTER system'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET randomness_order=0'; $results = $wpdb->query( $update_sql ); } // Update 0.9.5 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_answer_template'" ) != 'question_answer_template' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_answer_template TEXT NOT NULL AFTER comment_field_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $mlw_question_answer_default = '%QUESTION%<br /> Answer Provided: %USER_ANSWER%<br /> Correct Answer: %CORRECT_ANSWER%<br /> Comments Entered: %USER_COMMENTS%<br />'; $update_sql = 'UPDATE ' . $table_name . " SET question_answer_template='" . $mlw_question_answer_default . "'"; $results = $wpdb->query( $update_sql ); @@ -1639,99 +1651,99 @@ public function update() { // Update 0.9.6 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'contact_info_location'" ) != 'contact_info_location' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD contact_info_location INT NOT NULL AFTER send_admin_email'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET contact_info_location=0'; $results = $wpdb->query( $update_sql ); } // Update 1.0 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'email_from_text'" ) != 'email_from_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD email_from_text TEXT NOT NULL AFTER comment_field_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET email_from_text='Wordpress'"; $results = $wpdb->query( $update_sql ); } // Update 1.3.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'loggedin_user_contact'" ) != 'loggedin_user_contact' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD loggedin_user_contact INT NOT NULL AFTER randomness_order'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET loggedin_user_contact=0'; $results = $wpdb->query( $update_sql ); } // Update 1.5.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_from_total'" ) != 'question_from_total' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_from_total INT NOT NULL AFTER comment_section'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET question_from_total=0'; $results = $wpdb->query( $update_sql ); } // Update 1.6.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'total_user_tries'" ) != 'total_user_tries' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD total_user_tries INT NOT NULL AFTER question_from_total'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET total_user_tries=0'; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'total_user_tries_text'" ) != 'total_user_tries_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD total_user_tries_text TEXT NOT NULL AFTER total_user_tries'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET total_user_tries_text='Enter Your Text Here'"; $results = $wpdb->query( $update_sql ); } // Update 1.8.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'message_end_template'" ) != 'message_end_template' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD message_end_template TEXT NOT NULL AFTER message_comment'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET message_end_template=''"; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'certificate_template'" ) != 'certificate_template' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD certificate_template TEXT NOT NULL AFTER total_user_tries_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET certificate_template='Enter your text here!'"; $results = $wpdb->query( $update_sql ); } // Update 1.9.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'social_media'" ) != 'social_media' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD social_media INT NOT NULL AFTER certificate_template'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET social_media='0'"; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'social_media_text'" ) != 'social_media_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD social_media_text TEXT NOT NULL AFTER social_media'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET social_media_text='I just score a %CORRECT_SCORE%% on %QUIZ_NAME%!'"; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'pagination'" ) != 'pagination' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD pagination INT NOT NULL AFTER social_media_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET pagination=0'; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'pagination_text'" ) != 'pagination_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD pagination_text TEXT NOT NULL AFTER pagination'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET pagination_text='Next'"; $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'timer_limit'" ) != 'timer_limit' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD timer_limit INT NOT NULL AFTER pagination_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . ' SET timer_limit=0'; $results = $wpdb->query( $update_sql ); } // Update 2.1.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'quiz_stye'" ) != 'quiz_stye' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD quiz_stye TEXT NOT NULL AFTER timer_limit'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $mlw_style_default = ' div.mlw_qmn_quiz input[type=radio], div.mlw_qmn_quiz input[type=submit], @@ -1781,91 +1793,91 @@ public function update() { // Update 2.2.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_numbering'" ) != 'question_numbering' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_numbering INT NOT NULL AFTER quiz_stye'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET question_numbering='0'"; $results = $wpdb->query( $update_sql ); } // Update 2.8.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'quiz_settings'" ) != 'quiz_settings' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD quiz_settings TEXT NOT NULL AFTER question_numbering'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET quiz_settings=''"; $results = $wpdb->query( $update_sql ); } // Update 3.0.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'theme_selected'" ) != 'theme_selected' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD theme_selected TEXT NOT NULL AFTER quiz_settings'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET theme_selected='default'"; $results = $wpdb->query( $update_sql ); } // Update 3.3.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'last_activity'" ) != 'last_activity' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD last_activity DATETIME NOT NULL AFTER theme_selected'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET last_activity='%s'", gmdate( 'Y-m-d H:i:s' ) ); $results = $wpdb->query( $update_sql ); } // Update 3.5.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'require_log_in'" ) != 'require_log_in' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD require_log_in INT NOT NULL AFTER last_activity'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET require_log_in='%d'", '0' ); $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'require_log_in_text'" ) != 'require_log_in_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD require_log_in_text TEXT NOT NULL AFTER require_log_in'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( 'UPDATE ' . $table_name . " SET require_log_in_text='%s'", 'Enter Text Here' ); $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'limit_total_entries'" ) != 'limit_total_entries' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD limit_total_entries INT NOT NULL AFTER require_log_in_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET limit_total_entries='%d'", '0' ); $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'limit_total_entries_text'" ) != 'limit_total_entries_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD limit_total_entries_text TEXT NOT NULL AFTER limit_total_entries'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET limit_total_entries_text='%s'", 'Enter Text Here' ); $results = $wpdb->query( $update_sql ); } // Update 7.3.8 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'quiz_author_id'" ) != 'quiz_author_id' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD quiz_author_id TEXT NOT NULL AFTER deleted'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); } // Update 3.7.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'scheduled_timeframe'" ) != 'scheduled_timeframe' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD scheduled_timeframe TEXT NOT NULL AFTER limit_total_entries_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET scheduled_timeframe=''"; $results = $wpdb->query( stripslashes( esc_sql( $update_sql ) ) ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'scheduled_timeframe_text'" ) != 'scheduled_timeframe_text' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD scheduled_timeframe_text TEXT NOT NULL AFTER scheduled_timeframe'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET scheduled_timeframe_text='%s'", 'Enter Text Here' ); $results = $wpdb->query( $update_sql ); } // Update 4.3.0 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'disable_answer_onselect'" ) != 'disable_answer_onselect' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD disable_answer_onselect INT NOT NULL AFTER scheduled_timeframe_text'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET disable_answer_onselect=%d", '0' ); $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'ajax_show_correct'" ) != 'ajax_show_correct' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD ajax_show_correct INT NOT NULL AFTER disable_answer_onselect'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET ajax_show_correct=%d", '0' ); $results = $wpdb->query( $update_sql ); } @@ -1875,63 +1887,63 @@ public function update() { // Update 0.5 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'comments'" ) != 'comments' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD comments INT NOT NULL AFTER correct_answer'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $sql = 'ALTER TABLE ' . $table_name . ' ADD hints TEXT NOT NULL AFTER comments'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET comments=%d, hints=''", '1' ); $results = $wpdb->query( $update_sql ); } // Update 0.8 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_order'" ) != 'question_order' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_order INT NOT NULL AFTER hints'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET question_order=%d", '0' ); $results = $wpdb->query( $update_sql ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_type'" ) != 'question_type' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_type INT NOT NULL AFTER question_order'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET question_type=%d", '0' ); $results = $wpdb->query( $update_sql ); } // Update 1.1.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_answer_info'" ) != 'question_answer_info' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_answer_info TEXT NOT NULL AFTER correct_answer'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET question_answer_info=''"; $results = $wpdb->query( stripslashes( esc_sql( $update_sql ) ) ); } // Update 2.5.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'answer_array'" ) != 'answer_array' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD answer_array TEXT NOT NULL AFTER question_name'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET answer_array=''"; $results = $wpdb->query( stripslashes( esc_sql( $update_sql ) ) ); } // Update 3.1.1 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_settings'" ) != 'question_settings' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_settings TEXT NOT NULL AFTER question_type'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET question_settings=''"; $results = $wpdb->query( stripslashes( esc_sql( $update_sql ) ) ); } // Update 4.0.0 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'category'" ) != 'category' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD category TEXT NOT NULL AFTER question_settings'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = 'UPDATE ' . $table_name . " SET category=''"; $results = $wpdb->query( stripslashes( esc_sql( $update_sql ) ) ); } // Update 4.0.0 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'question_type_new'" ) != 'question_type_new' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD question_type_new TEXT NOT NULL AFTER question_type'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET question_type_new=%s", 'question_type' ); $results = $wpdb->query( $update_sql ); } @@ -1940,21 +1952,21 @@ public function update() { $user_email_template_data = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $wpdb->prefix . "mlw_quizzes LIKE 'user_email_template'" ); if ( 'text' === $user_email_template_data->Type ) { $sql = 'ALTER TABLE ' . $wpdb->prefix . 'mlw_quizzes MODIFY user_email_template LONGTEXT'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); } // Update 7.3.11 $user_message_after_data = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $wpdb->prefix . "mlw_quizzes LIKE 'message_after'" ); if ( 'text' === $user_message_after_data->Type ) { $sql = 'ALTER TABLE ' . $wpdb->prefix . 'mlw_quizzes MODIFY message_after LONGTEXT'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); } // Update 2.6.1 - $results = $wpdb->query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_qm_audit_trail CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' ); - $results = $wpdb->query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_questions CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); - $results = $wpdb->query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_quizzes CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); - $results = $wpdb->query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_results CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_qm_audit_trail CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;' ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_questions CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_quizzes CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_results CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci' ); global $wpdb; $table_name = $wpdb->prefix . 'mlw_results'; @@ -1963,31 +1975,31 @@ public function update() { // Update 2.6.4 if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $table_name . " LIKE 'user'" ) != 'user' ) { $sql = 'ALTER TABLE ' . $table_name . ' ADD user INT NOT NULL AFTER phone'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET user=%d", '0' ); $results = $wpdb->query( $update_sql ); } // Update 4.7.0 if ( $wpdb->get_var( "SHOW COLUMNS FROM $table_name LIKE 'user_ip'" ) != 'user_ip' ) { $sql = "ALTER TABLE $table_name ADD user_ip TEXT NOT NULL AFTER user"; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $update_sql = $wpdb->prepare( "UPDATE {$table_name} SET user_ip='%s'", 'Unknown' ); $results = $wpdb->query( $update_sql ); } // Update 7.1.11 $user_message_after_data = $wpdb->get_row( 'SHOW COLUMNS FROM ' . $wpdb->prefix . "mlw_results LIKE 'point_score'" ); if ( 'FLOAT' != $user_message_after_data->Type ) { - $results = $wpdb->query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_results MODIFY point_score FLOAT NOT NULL;' ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( 'ALTER TABLE ' . $wpdb->prefix . 'mlw_results MODIFY point_score FLOAT NOT NULL;' ); } if ( $wpdb->get_var( 'SHOW COLUMNS FROM ' . $audit_table . " LIKE 'quiz_id'" ) != 'quiz_id' ) { $sql = 'ALTER TABLE ' . $audit_table . ' ADD quiz_id TEXT NOT NULL AFTER action'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $sql = 'ALTER TABLE ' . $audit_table . ' ADD quiz_name TEXT NOT NULL AFTER quiz_id'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); $sql = 'ALTER TABLE ' . $audit_table . ' ADD form_data TEXT NOT NULL AFTER quiz_name'; - $results = $wpdb->query( $sql ); + $results = $mlwQuizMasterNext->wpdb_alter_table_query( $sql ); } // Update 5.0.0 @@ -2010,7 +2022,7 @@ public function update() { // Update 8.1.14 if ( ! $wpdb->query("SHOW KEYS FROM {$results_table_name} WHERE Key_name = 'unique_id_unique'" ) ) { - $results = $wpdb->query("ALTER TABLE {$results_table_name} ADD UNIQUE (unique_id)"); + $results = $mlwQuizMasterNext->wpdb_alter_table_query("ALTER TABLE {$results_table_name} ADD UNIQUE (unique_id)"); } // Update 8.0.3
php/classes/class-qsm-questions.php+5 −5 modified@@ -292,7 +292,7 @@ private static function create_save_question( $data, $answers, $settings, $is_cr } $answers = apply_filters( 'qsm_answers_before_save', $sanitize_answers, $answers, $data, $settings ); - $question_name = htmlspecialchars( wp_kses_post( $data['name'] ), ENT_QUOTES ); + $question_name = htmlspecialchars( $mlwQuizMasterNext->sanitize_html( $data['name'] ), ENT_QUOTES ); $trim_question_description = apply_filters( 'qsm_trim_question_description', true ); if ( $trim_question_description ) { $question_name = trim( preg_replace( '/\s+/', ' ', $question_name ) ); @@ -302,7 +302,7 @@ private static function create_save_question( $data, $answers, $settings, $is_cr 'quiz_id' => intval( $data['quiz_id'] ), 'question_name' => $question_name, 'answer_array' => maybe_serialize( $answers ), - 'question_answer_info' => wp_kses_post( $data['answer_info'] ), + 'question_answer_info' => $mlwQuizMasterNext->sanitize_html( $data['answer_info'] ), 'comments' => sanitize_text_field( $data['comments'] ), 'hints' => sanitize_text_field( $data['hint'] ), 'question_order' => intval( $data['order'] ), @@ -401,12 +401,12 @@ private static function create_save_question( $data, $answers, $settings, $is_cr * @return array sanitized $answers The answers for the question. */ public static function sanitize_answers( $answers, $settings ) { - + global $mlwQuizMasterNext; foreach ( $answers as $key => $answer ) { if ( isset( $settings['answerEditor'] ) && 'rich' == $settings['answerEditor'] ) { - $answer[0] = wp_kses_post( $answer[0] ); + $answer[0] = $mlwQuizMasterNext->sanitize_html( $answer[0] ); } else { - $answer[0] = sanitize_text_field( $answer[0] ); + $answer[0] = $mlwQuizMasterNext->sanitize_html( $answer[0], false ); } $answers[ $key ] = $answer; }
php/classes/class-qsm-results-pages.php+3 −3 modified@@ -57,7 +57,7 @@ public static function generate_pages( $response_data ) { } if ( ! empty($condition['extra_condition']) && 'category' == $main_condition ) { $category = $condition['extra_condition']; - if ( str_contains($category, 'qsm-cat-') ) { + if ( false !== strpos($category, 'qsm-cat-') ) { $cat_id = intval( str_replace( 'qsm-cat-', '', $category ) ); $term = get_term( $cat_id ); if ( $term ) { @@ -177,12 +177,12 @@ public static function generate_pages( $response_data ) { // Decodes special characters, runs through our template // variables, and then outputs the text. - $page = wp_kses_post( htmlspecialchars_decode( $content, ENT_QUOTES) ); + $page = htmlspecialchars_decode( $content, ENT_QUOTES); //last chance to filter $page $page = apply_filters( 'qsm_template_variable_results_page', $page, $response_data ); - echo apply_filters( 'mlw_qmn_template_variable_results_page', $page, $response_data ); + echo wp_kses_post( apply_filters( 'mlw_qmn_template_variable_results_page', $page, $response_data ) ); do_action( 'qsm_after_results_page', $response_data, $page_index ); ?> </div><?php
php/question-types/qsm-question-title.php+15 −0 modified@@ -26,9 +26,15 @@ function qsm_question_title_func( $question, $question_type = '', $new_question_ if ( '' !== $new_question_title ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( htmlspecialchars_decode( $new_question_title, ENT_QUOTES ), "Question-{$question_id}", "QSM Questions"); $new_question_title = apply_filters( 'qsm_question_title_before', $new_question_title, $question_type, $question_id ); + if ( in_array( intval( get_question_type( $question_id ) ), [ 12, 7, 3, 5 ], true ) ) { + ?> + <div class='mlw_qmn_new_question'><label for="question<?php echo esc_attr( $question_id ); ?>"><?php echo esc_html( $new_question_title ); ?> </label></div> + <?php + } else { ?> <div class='mlw_qmn_new_question'><?php echo esc_html( $new_question_title ); ?> </div> <?php + } $title_extra_classes .= ' qsm_remove_bold'; } if ( $question_id ) { @@ -63,4 +69,13 @@ function qsm_question_title_func( $question, $question_type = '', $new_question_ </div> <?php do_action('qsm_question_title_func_after',$question, $question_type, $new_question_title, $question_id ); +} + +function get_question_type( $question_id = 0 ) { + global $wpdb; + $question_type_new = $wpdb->get_var( $wpdb->prepare( "SELECT `question_type_new` FROM `{$wpdb->prefix}mlw_questions` WHERE `question_id`=%d", $question_id ) ); + if ( empty( $question_type_new ) ) { + return false; + } + return $question_type_new; } \ No newline at end of file
php/question-types/qsm-question-type-file-upload.php+2 −1 modified@@ -29,7 +29,8 @@ function qmn_file_upload_display( $id, $question, $answers ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'question_title' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> <div></div> - <input style="display: none;" type="file" class="mlw_answer_file_upload <?php echo esc_attr( $mlw_require_class ); ?>"/> + <label style="display: none;" for="question<?php echo esc_attr( $id ); ?>"><?php echo esc_attr( "Choose File" ); ?></label> + <input style="display: none;" type="file" id="question<?php echo esc_attr( $id ); ?>" class="mlw_answer_file_upload <?php echo esc_attr( $mlw_require_class ); ?>"/> <?php if ( ! $hide ) : ?> <div class="qsm-file-upload-container"> <span class="dashicons dashicons-cloud-upload qsm-file-upload-logo"></span>
php/question-types/qsm-question-type-fill-in-the-blanks.php+1 −1 modified@@ -25,7 +25,7 @@ function qmn_fill_blank_display( $id, $question, $answers ) { 'name' => true, 'pattern' => true, 'placeholder' => true, - 'readony' => true, + 'readonly' => true, 'required' => true, 'size' => true, 'step' => true,
php/question-types/qsm-question-type-multiple-choice-horizontal.php+9 −2 modified@@ -32,6 +32,8 @@ function qmn_horizontal_multiple_choice_display( $id, $question, $answers ) { $image_height = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'image_size-height' ); qsm_question_title_func( $question, 'horizontal_multiple_choice', $new_question_title, $id ); ?> + <fieldset> + <legend></legend> <div class="qmn_radio_answers qmn_radio_horizontal_answers <?php echo esc_attr( $mlw_class ); ?>"> <?php if ( is_array( $answers ) ) { @@ -44,12 +46,14 @@ function qmn_horizontal_multiple_choice_display( $id, $question, $answers ) { $mrq_checkbox_class = "mrq_checkbox_class"; } $mlw_answer_total++; + $other_option_class = ''; + $other_option_class = apply_filters( 'qsm_multiple_choice_other_option_classes', $other_option_class, $mlw_answer_total, $id, $answers ); if ( '' !== $answer[0] ) { $answer_class = apply_filters( 'qsm_answer_wrapper_class', '', $answer, $id ); $answer_class .= 'image' === $answerEditor ? ' qmn_image_option' : ''; ?> <span class="mlw_horizontal_choice <?php echo esc_attr( $answer_class.' '.$mrq_checkbox_class ); ?>"> - <input type="radio" class="qmn_quiz_radio qmn-multiple-choice-input" name="question<?php echo esc_attr( $id ); ?>" id="question<?php echo esc_attr( $id ) . '_' . esc_attr( $mlw_answer_total ); ?>" value="<?php echo esc_attr( $answer_index ); ?>" /> + <input type="radio" class="qmn_quiz_radio qmn-multiple-choice-input <?php echo esc_attr( $other_option_class ); ?>" name="question<?php echo esc_attr( $id ); ?>" id="question<?php echo esc_attr( $id ) . '_' . esc_attr( $mlw_answer_total ); ?>" value="<?php echo esc_attr( $answer_index ); ?>" /> <label class="qsm-input-label" for="question<?php echo esc_attr( $id ) . '_' . esc_attr( $mlw_answer_total ); ?>"> <?php if ( 'image' === $answerEditor ) { @@ -73,7 +77,7 @@ function qmn_horizontal_multiple_choice_display( $id, $question, $answers ) { } else { $answer_text = trim( htmlspecialchars_decode($add_label_value." ". $answer[0], ENT_QUOTES ) ); $answer_text = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answer_text, 'answer-' . $id . '-' . $answer_index, 'QSM Answers' ); - echo do_shortcode( wp_kses_post( $answer_text ) ); + echo wp_kses_post( do_shortcode( $answer_text ) ); } ?> </label> @@ -86,11 +90,13 @@ function qmn_horizontal_multiple_choice_display( $id, $question, $answers ) { } echo apply_filters( 'qmn_horizontal_multiple_choice_question_display', '', $id, $question, $answers ); ?> + <label style="display: none;" for="<?php echo esc_attr( 'question' . $id . '_none' ); ?>"><?php echo esc_attr( 'question' . $id ); ?></label> <input type="radio" style="display: none;" name="question<?php echo esc_attr( $id ); ?>" id="question<?php echo esc_attr( $id ); ?>_none" checked="checked" value="" /> <?php } ?> </div> + </fieldset> <?php echo apply_filters( 'qmn_horizontal_multiple_choice_display_front', '', $id, $question, $answers ); } @@ -106,6 +112,7 @@ function qmn_horizontal_multiple_choice_display( $id, $question, $answers ) { */ function qmn_horizontal_multiple_choice_review( $id, $question, $answers ) { $current_question = new QSM_Question_Review_Choice( $id, $question, $answers ); + $current_question = apply_filters( 'qmn_multiple_choice_review_before', $current_question, $id, $question, $answers ); $user_text_array = $current_question->get_user_answer( 'single_response' ); $correct_text_array = $current_question->get_correct_answer(); $return_array['user_text'] = ! empty( $user_text_array ) ? implode( ', ', $user_text_array ) : '';
php/question-types/qsm-question-type-multiple-choice.php+10 −2 modified@@ -29,6 +29,8 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { // $question_title = apply_filters('the_content', $question); qsm_question_title_func( $question, 'multiple_choice', $new_question_title, $id ); ?> + <fieldset> + <legend></legend> <div class='qmn_radio_answers <?php echo esc_attr( $mlw_class ); ?>'> <?php if ( is_array( $answers ) ) { @@ -41,6 +43,8 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { $mrq_checkbox_class = "mrq_checkbox_class"; } $mlw_answer_total++; + $other_option_class = ''; + $other_option_class = apply_filters( 'qsm_multiple_choice_other_option_classes', $other_option_class, $mlw_answer_total, $id, $answers ); if ( '' !== $answer[0] ) { $answer_class = apply_filters( 'qsm_answer_wrapper_class', '', $answer, $id ); if ( 'rich' === $answerEditor ) { @@ -57,7 +61,7 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { <?php } ?> - <input type='radio' class='qmn_quiz_radio qmn-multiple-choice-input' name="<?php echo esc_attr( 'question' . $id ); ?>" id="<?php echo esc_attr( 'question' . $id . '_' . $mlw_answer_total ); ?>" value="<?php echo esc_attr( $answer_index ); ?>" /> + <input type='radio' class='qmn_quiz_radio qmn-multiple-choice-input <?php echo esc_attr( $other_option_class ); ?>' name="<?php echo esc_attr( 'question' . $id ); ?>" id="<?php echo esc_attr( 'question' . $id . '_' . $mlw_answer_total ); ?>" value="<?php echo esc_attr( $answer_index ); ?>" /> <label class="qsm-input-label" for="<?php echo esc_attr( 'question' . $id . '_' . $mlw_answer_total ); ?>"> <?php if ( 'image' === $answerEditor ) { @@ -81,7 +85,7 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { } else { $answer_text = trim( htmlspecialchars_decode($add_label_value." ".$answer[0], ENT_QUOTES ) ); $answer_text = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answer_text, 'answer-' . $id . '-' . $answer_index, 'QSM Answers' ); - echo do_shortcode( wp_kses_post($answer_text ) ); + echo wp_kses_post( do_shortcode($answer_text ) ); } ?> </label> @@ -93,12 +97,15 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { } //} } + echo apply_filters( 'qsm_multiple_choice_display_after_loop', ' ', $id, $question, $answers ); ?> + <label style="display: none;" for="<?php echo esc_attr( 'question' . $id . '_none' ); ?>"><?php echo esc_attr( 'question' . $id ); ?></label> <input type="radio" style="display: none;" name="<?php echo esc_attr( 'question' . $id ); ?>" id="<?php echo esc_attr( 'question' . $id . '_none' ); ?>" checked="checked" value="" /> <?php } ?> </div> + </fieldset> <?php echo apply_filters( 'qmn_multiple_choice_display_front', '', $id, $question, $answers ); } @@ -114,6 +121,7 @@ function qmn_multiple_choice_display( $id, $question, $answers ) { */ function qmn_multiple_choice_review( $id, $question, $answers ) { $current_question = new QSM_Question_Review_Choice( $id, $question, $answers ); + $current_question = apply_filters( 'qmn_multiple_choice_review_before', $current_question, $id, $question, $answers ); $user_text_array = $current_question->get_user_answer(); $correct_text_array = $current_question->get_correct_answer(); $return_array['user_answer'] = $user_text_array;
php/question-types/qsm-question-type-multiple-response-horizontal.php+4 −1 modified@@ -30,6 +30,8 @@ function qmn_horizontal_multiple_response_display( $id, $question, $answers ) { $image_height = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'image_size-height' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> + <fieldset> + <legend></legend> <div class="qmn_check_answers qmn_multiple_horizontal_check <?php echo esc_attr( $mlw_class ); ?>"> <?php if ( is_array( $answers ) ) { @@ -71,7 +73,7 @@ function qmn_horizontal_multiple_response_display( $id, $question, $answers ) { } else { $answer_text = trim( htmlspecialchars_decode( $add_label_value." ".$answer[0], ENT_QUOTES ) ); $answer_text = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answer_text, 'answer-' . $answer_text, 'QSM Answers' ); - echo do_shortcode( wp_kses_post( $answer_text ) ); + echo wp_kses_post( do_shortcode( $answer_text ) ); } ?> </label> @@ -85,6 +87,7 @@ function qmn_horizontal_multiple_response_display( $id, $question, $answers ) { } ?> </div> + </fieldset> <?php echo apply_filters( 'qmn_horizontal_multiple_response_display_front', '', $id, $question, $answers ); }
php/question-types/qsm-question-type-multiple-response.php+4 −1 modified@@ -31,6 +31,8 @@ function qmn_multiple_response_display( $id, $question, $answers ) { $image_height = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'image_size-height' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> + <fieldset> + <legend></legend> <div class="qmn_check_answers <?php echo esc_attr( $mlw_class ); ?>"> <?php if ( is_array( $answers ) ) { @@ -72,7 +74,7 @@ function qmn_multiple_response_display( $id, $question, $answers ) { } else { $answer_text = trim( htmlspecialchars_decode( $add_label_value." ". $answer[0], ENT_QUOTES ) ); $answer_text = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answer_text, 'answer-' . $id . '-' . $answer_index, 'QSM Answers' ); - echo do_shortcode( wp_kses_post( $answer_text ) ); + echo wp_kses_post( do_shortcode( $answer_text ) ); } ?> </label> @@ -83,6 +85,7 @@ function qmn_multiple_response_display( $id, $question, $answers ) { } ?> </div> + </fieldset> <?php echo apply_filters( 'qmn_multiple_response_display_front', '', $id, $question, $answers ); }
php/question-types/qsm-question-type-number.php+1 −1 modified@@ -27,7 +27,7 @@ function qmn_number_display( $id, $question, $answers ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'question_title' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> - <input type="number" class="mlw_answer_number <?php echo esc_attr( $mlw_require_class ); ?>" name="question<?php echo esc_attr( $id ); ?>" <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>" oninput="checkMaxLength(this)" <?php endif; ?> <?php echo esc_attr( $min_num_attr ); ?> /> + <input type="number" class="mlw_answer_number <?php echo esc_attr( $mlw_require_class ); ?>" id="question<?php echo esc_attr( $id ); ?>" name="question<?php echo esc_attr( $id ); ?>" <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>" oninput="checkMaxLength(this)" <?php endif; ?> <?php echo esc_attr( $min_num_attr ); ?> /> <?php echo apply_filters( 'qmn_number_display_front', '', $id, $question, $answers ); }
php/question-types/qsm-question-type-opt-in.php+1 −1 modified@@ -30,7 +30,7 @@ function qmn_accept_display( $id, $question, $answers ) { $question = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'question_title' ); } $question = $mlwQuizMasterNext->pluginHelper->qsm_language_support( htmlspecialchars_decode( $question, ENT_QUOTES ), "question-description-{$id}", 'QSM Questions' ); - echo do_shortcode( wp_kses_post( $question ) ); + echo wp_kses_post( do_shortcode( $question ) ); ?> </span> </label>
php/question-types/qsm-question-type-paragraph.php+1 −1 modified@@ -27,7 +27,7 @@ function qmn_large_open_display( $id, $question, $answers ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'question_title' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> - <textarea class="mlw_answer_open_text <?php echo esc_attr( $mlw_require_class ); ?>" cols="70" rows="5" name="question<?php echo esc_attr( $id ); ?>" <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>"<?php endif; ?> <?php echo esc_attr( $min_length_attr ); ?> /></textarea> + <textarea class="mlw_answer_open_text <?php echo esc_attr( $mlw_require_class ); ?>" cols="70" rows="5" id="question<?php echo esc_attr( $id ); ?>" name="question<?php echo esc_attr( $id ); ?>" <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>"<?php endif; ?> <?php echo esc_attr( $min_length_attr ); ?> /></textarea> <?php echo apply_filters( 'qmn_large_open_display_front', '', $id, $question, $answers ); }
php/question-types/qsm-question-type-polar.php+2 −2 modified@@ -66,7 +66,7 @@ function qmn_polar_display( $id, $question, $answers ) { <?php } else { $left_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answers[0][0], 'answer-' . $id . '-0', "QSM Answers" ); - echo do_shortcode( wp_kses_post( $left_title ) ); + echo wp_kses_post( do_shortcode( $left_title ) ); } ?> </div> <div class='slider-main-wrapper'> @@ -95,7 +95,7 @@ function qmn_polar_display( $id, $question, $answers ) { <?php } else { $right_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answers[1][0], 'answer-' . $id . '-1', "QSM Answers" ); - echo do_shortcode( wp_kses_post( $right_title ) ); + echo wp_kses_post( do_shortcode( $right_title ) ); } ?></div> </span>
php/question-types/qsm-question-type-short-answer.php+1 −1 modified@@ -29,7 +29,7 @@ function qmn_small_open_display( $id, $question, $answers ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->get_question_setting( $id, 'question_title' ); qsm_question_title_func( $question, '', $new_question_title, $id ); ?> - <input <?php echo esc_attr( $autofill_att ); ?> type="text" class="mlw_answer_open_text <?php echo esc_attr( $mlw_require_class ); ?>" name="question<?php echo esc_attr( $id ); ?>" <?php echo esc_attr( $min_text_attr ); ?> <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>"<?php endif; ?> /> + <input <?php echo esc_attr( $autofill_att ); ?> type="text" class="mlw_answer_open_text <?php echo esc_attr( $mlw_require_class ); ?>" id="question<?php echo esc_attr( $id ); ?>" name="question<?php echo esc_attr( $id ); ?>" <?php echo esc_attr( $min_text_attr ); ?> <?php if ( $limit_text ) : ?>maxlength="<?php echo esc_attr( $limit_text ); ?>"<?php endif; ?> /> <?php echo apply_filters( 'qmn_small_open_display_front', '', $id, $question, $answers ); }
php/shortcodes.php+1 −1 modified@@ -85,7 +85,7 @@ function qsm_display_recent_quizzes( $attrs ) { } elseif ( $start_date && $start_date > $now && 'no' === $include_future_quizzes ) { continue; } else { - $title = $quiz->quiz_name; + $title = esc_html( $quiz->quiz_name ); $id = $quiz->quiz_id; $url = do_shortcode( "[qsm_link id='$id'] Take Quiz [/qsm_link]" ); $result .= "<div class='ind-quiz'>
php/template-variables.php+7 −7 modified@@ -401,7 +401,7 @@ function mlw_qmn_variable_total_questions( $content, $mlw_quiz_array ) { } function mlw_qmn_variable_correct_score( $content, $mlw_quiz_array ) { - $correct_score = isset( $mlw_quiz_array['total_score'] ) ? $mlw_quiz_array['total_score'] : ''; + $correct_score = isset( $mlw_quiz_array['total_score'] ) ? $mlw_quiz_array['total_score'] : 0; $correct_score = qsm_is_allow_score_roundoff() ? round( $correct_score ) : round( $correct_score, 2 ); $content = str_replace( '%CORRECT_SCORE%', $correct_score, $content ); return $content; @@ -1392,7 +1392,7 @@ function qsm_questions_answers_shortcode_to_text( $mlw_quiz_array, $qmn_question $question_max_point = ( isset( $questions[ $answer['id'] ] ) ? qsm_get_question_maximum_points( $questions[ $answer['id'] ] ) : 0 ); $mlw_question_answer_display = str_replace( '%QUESTION_MAX_POINTS%', $question_max_point, $mlw_question_answer_display ); - $mlw_question_answer_display = do_shortcode( wp_kses_post( $mlw_question_answer_display ) ); + $mlw_question_answer_display = wp_kses_post( do_shortcode( $mlw_question_answer_display ) ); if ( $total_question_cnt == $qsm_question_cnt && false == $remove_border ) { $extra_border_bottom_class = 'qsm-remove-border-bottom'; @@ -1401,7 +1401,7 @@ function qsm_questions_answers_shortcode_to_text( $mlw_quiz_array, $qmn_question $question_obj = ( isset( $questions[ $answer['id'] ] ) ? $questions[ $answer['id'] ] : null ); $display = "<div class='qmn_question_answer $extra_border_bottom_class $question_answer_class'>" . apply_filters( 'qmn_variable_question_answers', $mlw_question_answer_display, $mlw_quiz_array, $question_obj ) . '</div>'; - return $display; + return wp_kses_post( $display ); } function qsm_get_question_maximum_points( $question = array() ) { @@ -1530,7 +1530,7 @@ function qmn_polar_display_on_resultspage( $id, $question, $answers, $answer ) { $input_text .= '<span class="qsm_image_caption">'.esc_html( $caption_text ).'</span>'; } else { $left_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answers[0][0], "answer-" . $answers[0][0], "QSM Answers" ); - $input_text .= do_shortcode( wp_kses_post( $left_title ) ); + $input_text .= wp_kses_post( do_shortcode( $left_title ) ); } $input_text .= "</div>"; @@ -1552,7 +1552,7 @@ function qmn_polar_display_on_resultspage( $id, $question, $answers, $answer ) { $input_text .= '<span class="qsm_image_caption">'.esc_html( $caption_text ).'</span>'; } else { $right_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $answers[1][0], "answer-" . $answers[0][0], "QSM Answers" ); - $input_text .= do_shortcode( wp_kses_post( $right_title ) ); + $input_text .= wp_kses_post( do_shortcode( $right_title ) ); } $input_text .= "</div>"; $question = $input_text; @@ -1623,10 +1623,10 @@ function qsm_varibale_question_title_func( $question, $question_type = '', $new_ if ( '' !== $new_question_title ) { $new_question_title = $mlwQuizMasterNext->pluginHelper->qsm_language_support( htmlspecialchars_decode( $new_question_title, ENT_QUOTES ), "Question-{$question_id}", 'QSM Questions' ); - $question_display .= "<div class='mlw_qmn_new_question'>" . $new_question_title . '</div>'; + $question_display .= "<div class='mlw_qmn_new_question'>" . esc_html( $new_question_title ) . '</div>'; $polar_extra_class .= ' qsm_remove_bold'; } $question_display .= "<div class='mlw_qmn_question' >" . do_shortcode( $question_title ) . '</div>'; - return $question_display; + return wp_kses_post( $question_display ); }
php/template-variables/qsm-tempvar-question-answers.php+1 −0 modified@@ -39,6 +39,7 @@ function qsm_tempvar_qa_text_qt_choice( $total_answers, $answers_from_response, $image_class = ''; $show_user_answer = $mlwQuizMasterNext->pluginHelper->qsm_language_support( $show_user_answer, 'answer-' . $answers_from_response['id'] . '-' . $single_answer_key, 'QSM Answers' ); } + $show_user_answer = apply_filters( 'qsm_show_user_answer_after', $show_user_answer, $single_answer, $user_answer_array, $single_answer_key, $answers_from_response, $grading_system, $question_settings, $form_type, $total_answers ); $close_span = '</span>'; if ( 0 == $form_type && ( 0 === intval( $grading_system ) || 3 === intval( $grading_system ) ) ) { $hide_correct_answer = $mlwQuizMasterNext->pluginHelper->get_section_setting( 'quiz_options', 'hide_correct_answer' );
readme.txt+15 −813 modified@@ -1,10 +1,10 @@ -=== Quiz And Survey Master - Best Quiz, Exam and Survey Plugin for WordPress === +=== Quiz and Survey Master (QSM) - Easy Quiz and Survey Maker === Contributors: quizsurvey,expresstech -Tags: quiz, survey, lead, test, score, exam, questionnaire, question,wordpress quiz plugin +Tags: quiz, survey, test, exam, online assessment Requires at least: 4.9 Tested up to: 6.5 Requires PHP: 5.4 -Stable tag: 9.0.1 +Stable tag: 9.0.2 License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -163,6 +163,17 @@ This is usually a theme conflict. You can [checkout out our common conflict solu 18. Database == Changelog == += 9.0.2 ( June 05, 2024 ) = +* Bug: Fixed security vulnerability +* Bug: Resolved an issue causing incorrect display of shortcodes due to invalid quiz IDs +* Bug: Improved user permission checks and input validation for question deletion +* Bug: Fixed validation issue with contact fields +* Feature: Users can resubmit or delete failed submissions +* Enhancement: Improved logic for handling migration queries +* Enhancement: Improved functionality for clicking the Enter key +* Enhancement: Added a Failed Submissions list to the QSM menu +* Enhancement: Improved admin notifications + = 9.0.1 (April 25, 2024) = * Bug: Fixed date format in %ANSWER_X% variable * Bug: Resolved PHP warning in Quiz Block editor @@ -186,816 +197,7 @@ This is usually a theme conflict. You can [checkout out our common conflict solu * Enhancement: Improved the user interface of the upload files question type * Enhancement: Improve result and email page UI -= 8.2.3 (March 12, 2024) = -* Bug: Fixed issue with inline result while duplicating quizzes -* Bug: Patched a vulnerability related to the result page -* Enhancement: Improve contact fields UI - -= 8.2.2 (January 18, 2024) = -* Feature: Added an option to mark texts as code snippets in the question description -* Bug: Fixed the issue of skipping question validation after the quiz timer ends -* Bug: Fixed issue when using apostrophe in fill-in-the-blanks questions -* Bug: Fixed the quiz navigation problem with reCAPTCHA -* Enhancement: Improved auto-pause logic for embedded audio when shifting pages. - -= 8.2.1 (January 05, 2024) = -* Feature: Added option to delete bulk questions -* Bug: Resolved JavaScript conflicts -* Bug: Fixed translation issue on quiz result page -* Enhancement: Improved logic to auto pause emabded video after changing page - -= 8.2.0 (December 15, 2023) = -* Feature: Added option to change deselect answer text -* Feature: Added option to duplicate quiz theme settings -* Bug: Fixed issue related to limiting random questions by category -* Bug: Fixed issue with images and video tags in the correct answer info -* Enhancement: Improved login form validations -* Enhancement: Improved performance by optimizing cookies - -= 8.1.19 (November 08, 2023) = -* Feature: Added an option to display result URLs on the admin result page -* Bug: Resolved Cross Site Request Forgery vulnerability -* Enhancement: Improved quiz timer performance -* Enhancement: Added a user alert message for cases where results will not be stored in the database - -= 8.1.18 (October 26, 2023) = -* Enhancement: Updated the message when you submit a quiz in draft mode - -= 8.1.17 (October 11, 2023) = -* Feature: Added option to include custom text when the answer choice limit exceeds in multiple response type questions. -* Feature: Added a new feature to accept shortcodes in the text set to display at the end of quizzes. -* Bug: Fixed issues with HTML tags in exported PDFs -* Bug: Fixed issues with HTML tags in question descriptions -* Bug: Fixed issue with the 'Required box' unchecking itself -* Bug: Patched a vulnerability related to draft quiz submissions - -= 8.1.16 (September 20, 2023) = -* Feature: Added option to use random question and answer with manual pagination -* Bug: Fix quiz score calculation issue with file upload question types -* Enhancement: Improved nonce validation logic - -= 8.1.15 (September 11, 2023) = -* Bug: Fixed issue causing numeric responses of 0 to display as "No Answer Provided" in emails -* Bug: Fixed issue with next button while using manual pagination -* Bug: Fixed WPML issue with retake and start buttons -* Bug: Fixed custom CSS issue -* Enhancement: Improve file upload question type functionality -* Enhancement: Improve nonce validation logic -* Enhancement: Improved RTL (Right-to-Left) layout support - -= 8.1.14 (August 24, 2023) = -* Feature: Added option to change text label for "No answer provided” -* Bug: Resolved the issue where the timer would continue to display in the page title even after being disabled -* Bug: Addressed several PHP warnings -* Bug: Patched a vulnerability to prevent race conditions during submission -* Bug: Fixed Cross Site Scripting (XSS) vulnerability in question description -* Enhancement: Included an option to underline text in the editor - -= 8.1.13 (August 02, 2023) = -* Bug: Fixed translation issue with German letters -* Bug: Resolved quiz store issue related to long quiz URLs -* Bug: Fixed issue with inline CSS class in quiz answer selection - -= 8.1.12 (July 20, 2023) = -* Bug: The HTML tag issue with the admin result page has been resolved -* Bug: Fixed issue with question position on manual pagination -* Bug: Resolved the issue related to multiple responses showing in the inline result option -* Enhancement: Significant performance improvements have been made to the show inline result feature - -= 8.1.11 (July 14, 2023) = -* Bug: Resolved problem causing a blank screen upon submission -* Bug: Rectified issues with the layout of the progress bar -* Bug: Fixed security vulnerabilities and enhanced overall system protection - -= 8.1.10 (June 30, 2023) = -* Bug: Fixed issues with timer after 8.1.9 release - -= 8.1.9 (June 28, 2023) = -* Feature: Added option to disable quiz public links -* Feature: Added option to apply global setting on multiple quizzes -* Feature: Added the ability to set a default text for unanswered questions -* Feature: Added option to store failed quiz submitted data -* Feature: Added option to enable/disable QSM logs -* Bug: Fixed visiblity issue with next button on comment screen -* Bug: Fixed correct answer logic issue with multi choice question type - -= 8.1.8 (June 13, 2023) = -* Feature: Added option to end quiz after x number of wrong answers -* Feature: Added option to display the start and end dates of quizzes in the result list -* Bug: Fixed issue with correct answer logic while applying global setting -* Bug: Resolved hyperlink problem with multiple answer in email. -* Enhancement: Improve show inline result UX -* Enhancement: Improve questions hint tooltip UI -* Enhancement: Implemented various improvements to enhance the user experience of the quiz admin panel - -= 8.1.7 (May 22, 2023) = -* Feature: Now users can set separate question limits for individual categories. -* Bug: Fixed issues with ending a quiz if wrong answer is selected -* Enhancement: Enhanced the validation flow for the "end quiz if wrong answer" option. -* Enhancement: Added a warning alert to notify users when they attempt to save invalid variables in the result or email template -* Enhancement: Improved the functionality of nonce validation -* Enhancement: Enhanced the user interface for displaying multiple response results -* Enhancement: Improved the user experience for the "show inline result" option - -= 8.1.6 (April 24, 2023) = -* Bug: Resolved a JavaScript conflict with the Avada theme -* Bug: PHP warnings related to disallowing submission after quiz expiry have been fixed -* Bug: Fixed issue with end quiz if there is wrong answer option -* Bug: Corrected decimal and negative points calculations associated with point-related variables -* Bug: Fixed visiblity issue with start button - -= 8.1.5 (April 13, 2023) = -* Feature: Added option to display inline results for fill-in-the-blank and dropdown question types -* Bug: Resolved an issue with the next button when multiple quizzes are used on the same page -* Bug: Fixed a critical error on the result page -* Bug: Addressed security and vulnerability concerns -* Bug: Resolved an issue with hidden required questions validation -* Bug: Fixed the correct answer information issue when importing questions from the question bank -* Enhancement: Improved the user interface of the categories dropdown in the Options tab - -= 8.1.4 (March 31, 2023) = -* Hotfix: Resolved an issue where the submit button appeared twice - -= 8.1.3 (March 29, 2023) = -* Feature: Added Select and Radio input types as new features for contact fields -* Bug: Resolved an issue where the submit button was not visible when pagination was used -* Bug: Fixed submit button label rename issue with auto pagination -* Bug: Fixed a problem with rounding scores -* Bug: Improved security and resolved vulnerability issues -* Bug: Corrected a validation issue with contact field checkboxes -* Enhancement: Checked and confirmed compatibility with WordPress version 6.2 - -= 8.1.2 (March 15, 2023) = -* Hotfix: Fixed submit button visiblity issue with random question option - -= 8.1.1 (March 09, 2023) = -* Feature: Added an option to highlight the correct answer if the user selected the wrong answer -* Feature: Added an option to show/hide the question's featured image on the result page -* Bug: Fixed an issue with adding a class for the correct/incorrect answers option -* Bug: Fixed an encoding issue in the email header -* Bug: Fixed an issue with immediately ending the quiz if the user selects the wrong answer in pagination -* Enhancement: Improved the user interface for the question bank popup and options tabs -* Enhancement: Improved the user interface for the quiz next and submit buttons - - -= 8.1.0 (Feb 27, 2023) = -* Feature: Added a new feature that allows users to show or hide correct answers on the result page -* Bug: Fixed a bug that caused issues with the required field for the polar question type -* Bug: Fixed security and vulnerability issues that were identified in the plugin -* Bug: Fixed a bug that caused issues with displaying results inline for the short answer type -* Enhancement: Improved user interface for editor - -= 8.0.10 (Feb 02, 2023) = -* Feature: Added option to set theme color transparency -* Bug: Fixed issue with %TIMER_MINUTES% variable -* Bug: Fixed issue with duplicate question position - -= 8.0.9 (Jan 25, 2023) = -* Feature: Added option to move a question on specified page/position -* Feature: Added image answer type support for horizontal multiple response questions -* Feature: Added separate button on first page to start quiz/survey -* Bug: Fixed issue with fill in the blank question type causing conflict with other plugins -* Bug: Fixed question position issue while duplicating questions -* Bug: Fixed issue with %TIMER_MINUTES% variable -* Bug: Fixed security issues -* Enhancement: Improved format of wrong answers in emails - -= 8.0.8 (Dec 15, 2022) = -* Bug: Fixed issue with short answer question type -* Bug: Fixed security issues -* Bug: Fixed compatibility issues with php v7 or older - -= 8.0.7 (Dec 05, 2022) = -* Feature: Added option to show and hide Text/HTML question type on result page -* Bug: Fixed block.js warnings -* Bug: Fixed issue with required questions validations - -= 8.0.6 (Nov 22, 2022) = -* Feature: Added option to search by quiz in question bank -* Feature: Added option to set image size in email template -* Bug: Fixed timer issue with multiple quiz shortcodes -* Bug: Fixed issue with german and french language questions -* Enhancement: Added alert for non active question types -* Enhancement: Improved UI in text tabs - -= 8.0.5 (Oct 20, 2022) = -* Bug: Fixed issue with random question and answers -* Bug: Fixed issue with quiz timer -* Bug: Fixed issue with file size limit -* Bug: Fixed security and Vulnerability issues. -* Enhancement: Improved UI for required fields validation message -* Enhancement: Improved UI in polar question -* Enhancement: Improved UI in Opt-in question - -= 8.0.4 (September 29, 2022) = -* Feature: Added captions for image answer on result page -* Bug: Fixed issue with themes list in style tab -* Bug: Fixed issue with quiz end date -* Bug: Fixed issue with labels for opt-in question type -* Bug: Fixed PHP warning and errors with inactive quiz themes -* Enhancement: Minor UI improvements -* Enhancement: Improved Image alignment in image type answers - -= 8.0.3 (July 26, 2022) = -* Feature: Added option to enable/disable case sensitive answer for fill-in blank question -* Feature: Added option to enable/disable MathJax -* Feature: Added option to enable/disable emails notifications -* Feature: Added option to set images size for image type answers -* Feature: Added %ANSWER_X% variables to show user's answer to a specific question -* Feature: Added translation support for all Javascript string messages -* Feature: Added image answer support for polar question type -* Bug: Fixed display issue with leaderboard customization block -* Bug: Fixed issue with questions count in quiz list page -* Bug: Fixed issue with %QUESTION_ANSWER_X% variables -* Bug: Fixed issue while deleting/duplicating old quizzes -* Bug: Fixed issue with timer while using pagination -* Enhancement: Improved UI for image type answers options - -= 8.0.2 (June 23, 2022) = -* Bug: Fixed scoring issue while using random questions -* Bug: Fixed issue with file question type validation settings -* Bug: Fixed issue with video player in rich text answer type - -= 8.0.1 (June 17, 2022) = -* Hotfix: Fixed issues while using random questions with question limit - -= 8.0 (June 13, 2022) = -* Feature: Added WPML compatibility -* Feature: Added option to select correct answer logic -* Feature: Added option to show and hide Opt-in question type on result page -* Feature: Added validation options in contact form fields -* Enhancement: Improved UI for question editor in admin panel -* Enhancement: Redesigned contact tab interface in admin panel -* Enhancement: Autosave last question when user creates new question -* Enhancement: Added column to show the number of questions in quiz list -* Enhancement: Added qsm_results_css_inliner hook to edit email template -* Bug: Fixed issue with quiz links -* Bug: Fixed deletion issue with trash quizzes -* Bug: Fixed issues with random questions order -* Bug: Fixed %AMOUNT_INCORRECT% & %AMOUNT_ATTEMPTED% variables -* Bug: Fixed issue while updating quiz title -* Bug: Fixed issue with duplicate question while importing from question bank -* Bug: Fixed JS issue with polar question type -* Bug: Fixed several PHP warning and errors -* Bug: Fixed issue with HTML tags in answer text editor - -= 7.3.14 (April 5, 2022) = -* Bug: Fixed issue with paragraph question type -* Bug: Fixed issue with qmn_register_my_templates hook -* Bug: Fixed issue with %CATEGORY_POINTS_X% template variable -* Bug: Fixed issue with question numbers in email -* Bug: Fixed issue with elementor popup -* Bug: Issue fixed with touch devices -* Feature: Added option to set default number of answers -* Feature: Added option to search questions from question bank -* Enhancement: Made UI improvements in polar question - -= 7.3.13 (March 14, 2022) = -* Bug: Fixed issue with comments field UI -* Bug: Fixed issue with support Link -* Bug: Fixed issue with %CATEGORY_SCORE_X% template variable -* Bug: Fixed issue while using multiple quiz shortcodes -* Bug: Fixed issue with qmn_register_my_templates hook -* Bug: Fixed issue with answer text limit -* Bug: Fixed issue while using limit questions with random questions -* Feature: Added option to customize the label of Retake Quiz Button - -= 7.3.12 (February 18, 2022) = -* Hotfix: Fixed compatibility issues with php 8 - -= 7.3.11 (February 17, 2022) = -* Bug: Fixed validation issues with limit multiple choice option -* Bug: Fixed issue while creating new quiz -* Bug: Fixed issue where empty answers are marked as correct -* Bug: Fixed issue with quiz dashboard -* Bug: Fixed issue with random questions & answers -* Bug: Fixed issue with template variable %QUESTIONS_ANSWERS_EMAIL% -* Bug: Fixed validation issues with dropdown field -* Bug: Fixed issue while importing questions from question bank -* Bug: Fixed issue while saving multiple results pages -* Bug: Fixed various security vulnerabilities -* Feature: Added new template variable %FINISHED_TIME% -* Enhancement: Made UI improvements in question numbers - -= 7.3.10 (January 28, 2022) = -* Checked compatibility with WordPress 5.9 -* Bug: Fixed UI issues in QSM dashboard banner -* Bug: Fixed CURRENT_DATE template variable with certificate addon -* Bug: Fixed CATEGORY_SCORE_X template variable -* Bug: Fixed incorrectly marked answers in survey & simple form -* Bug: Fixed translation issues -* Bug: Fixed issues with global default settings -* Bug: Fixed issues with multiple response question type - -= 7.3.9 (January 20, 2022) = -* Hotfix: Issues with markup in email -* Hotfix: Issues with quiz review for blank submissions -* Hotfix: Issues with question/average points/score template variable -* Hotfix: Issues with result items on admin dashboard - -== Changelog == -= 7.3.8 (January 18, 2022) = -* Bug: Fixed issues while taking quiz with logic questions. -* Bug: Fixed issues with category selection on email page. -* Bug: Fixed the issues with category points and score template variables. -* Bug: Fixed issues when contact form is set to appears at end of the quiz. -* Bug: Fixed issues with multiple quiz shortcode on a same page. -* Bug: Fixed issues with number of questions per category and random questions logic. -* Bug: Fixed security issues. -* Bug: Fixed issues with date and current date format in template variable. -* Bug: Fixed issues with QSM Theme. -* Enhancement: Added option to edit quiz in admin bar. -* Enhancement: Added option to disable first page on quiz. -* Enhancement: Made UI improvements in QSM. -* Enhancement: Made improvements in answer matching logic. - -= 7.3.7 (December 27, 2021) = -* Bug: Fixed issues in fill in the blanks question type -* Bug: Fixed issues with category selection on result page -* Bug: Fixed issues with deletion and duplication capabilities for non admin users -* Bug: Fixed issue where url parameters are being translated -* Bug: Fixed the issues with category points and score template variables -* Feature: Added a feature to hide/show columns in admin results page -* Enhancement: Introduced Page Name and Page URL columns to admin results table -* Enhancement: Made UI improvements in polar question type slider -* Enhancement: Made UI improvements in template variable popup -* Enhancement: Made improvements in Audit Logs - -= 7.3.6 (December 10, 2021) = -* Hotfix: Issues with survey form type Fixed -* Hotfix: Issues with simple form fixed -* Hotfix: Issues with random questions feature Fixed -* Hotfix: Issues with comment form and hints fixed -* Hotfix: Issues with deselect option fixed - -= 7.3.5 (November 17, 2021) = -* Bug: Fixed issue while permanently deleting bulk quizzes -* Bug: Fixed issue while editing questions imported from question bank -* Bug: Fixed issue with question categories -* Bug: Fixed various security vulnerabilities -* Bug: Fixed Authenticated SQL injection -* Bug: Fixed issues with polar question type -* Bug: Fixed issue where multiple popups were appearing -* Bug: Fixed issues where refreshing the page resets answered questions -* Bug: Fixed issues with QSM block -* Bug: Fixed issue with autofill for contact input -* Bug: Fixed issues with polar question type slider on admin results page -* Feature: Added support for webp file format -* Feature: Added new template variable %MINIMUM_POINTS% -* Enhancement: Replaced shortened urls with original urls -* Enhancement: Refactored code to enqueue JS and CSS files as per coding standards -* Enhancement: Refactored code to utilise libraries bundled with WordPress core -* Enhancement: Updated out of date libraries -* Enhancement: Removed CDN and third party server scripts -* Enhancement: Sanitized, Escaped, and Validated all variable, file uploads and data -* Enhancement: Moved inline scripts to wp_enqueue_script and wp_add_inline_script - -= 7.3.4 (October 1, 2021) = -* Bug: Fixed the issue with validation of date field for contact section - -= 7.3.3 (October 1, 2021) = -* Bug: Fixed the issue where %AVERAGE_CATEGORY_POINTS_X% was calculating total instead of average. -* Bug: Fixed the issue where no category found for questions imported from question bank. -* Bug: Fixed the issue where the limit number of questions per category was not working. -* Bug: Fixed the issue with "Limit question per category" setting when "Random" option is enabled -* Bug: Fixed the issue where timer was not showing on single page quiz. -* Bug: Fixed the issue when recaptcha button not showing when question per page quiz options is enabled. -* Bug: Fixed the issues while duplicating a quiz. -* Bug: Fixed the issue where date question type shows date in reverse order on the results page and in emails. -* Feature: Added date field in quiz contact tab. -* Enhancement: Added Correct/Incorrect answers in different color in email. - -= 7.3.2 (September 06, 2021) = -* Bug: Added Translation for Time is up and Cancel button. -* Bug: Fixed the issue of category name not visible. -* Bug: Fixed the issue of limit number of questions per category is not working. -* Bug: Fixed the issue of results page and email showing only 1 question and its answer multiple times. -* Bug: Fixed the issue of %POLL_RESULT_X% not displaying images while using rich answers. -* Bug: Fixed the issue of %AVERAGE_CATEGORY_POINTS_X% variable not working. -* Bug: Fixed the issue of validation errors appearing on the questions before entering the responses. -* Bug: Fixed the issue of timer not showing on the quiz. -* Bug: Fixed security issue to prevent Cross-Site Scripting attacks. - - -= 7.3.1 (August 13, 2021) = -* Bug: Fixed the error on updating database. -* Bug: Fixed the issue of everything displayed in the same line in the results page. -* Bug: Fixed the issue of fill in the blank question type not showing user answer and correct answer in the results page and email. -* Feature: Added global default settings for quiz options. -* Enhancement: Added option to deny quiz submission after end date/time -* Enhancement: Made order of random questions same on the results page and the quiz frontend. - - -= 7.3.0 (July 29, 2021) = -* Feature: Added option to add multiple categories to single question. -* Feature: Added option to display quiz results based on category points. -* Enhancement: Extended category based template variables to support multiple categories. -* Bug: Fixed issue with quiz duplication. - -= 7.2.3 (July 15, 2021) = -* Bug: Fixed issue fatal error on php version below 7.3. - -= 7.2.2 (July 14, 2021) = -* Feature: Implemented multiple fill in the blanks support. -* Feature: Implemented new template variable %TIMER_SECONDS% to show left over seconds. -* Feature: Implemented new option to limit number of questions per category. -* Bug: Fixed issue with template variable %AMOUNT_INCORRECT%. -* Bug: Fixed issue of undefined index notice of facebook app id. -* Bug: Fixed issue with saving conditions in email and results tab. -* Bug: Fixed issue of wordpress database error notice on fresh installation. -* Bug: Fixed issue with validation on retake quiz - -= 7.2.1 (June 25, 2021) = -* Bug: Fixed layout issues with rtl languages. -* Bug: Fixed issue of user comments not appearing on admin result page. -* Bug: Fixed issue with recaptcha not appearing on random quiz. - -= 7.2.0 (June 21, 2021) = -* Feature: Introduced QSM Themes. -* Feature: Introduced image type answers. -* Bug: Fixed issue where there is an empty last page while using auto pagination. - -= 7.1.19 (June 3, 2021) = -* Bug: Fixed security issue related to IP address sanitization. - -= 7.1.18 (May 31, 2021) = -* Bug: Fixed recently discovered security issues. - -= 7.1.17 (May 28, 2021) = -* Bug: Fixed the issue where page title shows Nan:Nan:Nan on reload. -* Bug: Fixed the issue when editing duplicate questions updates original questions. - -= 7.1.16 (April 29, 2021) = -* Bug: Fixed the issue with Facebook share. -* Bug: Fixed issue with timer starting on intro page. -* Bug: Fixed pagination issue with multiple quizzes on same page. -* Bug: Fixed issue with tiny-mce causing conflict with other plugins. -* Bug: Fixed the issue of logic rules not being copied when duplicating quiz. -* Feature: Added rich textbox for correct answer information. -* Feature: Added additional condition for Email template for different answers. - -= 7.1.15 (April 13, 2021) = -* Bug: Fixed SQL errors due to which questions were disappearing from some old quizzes. -* Bug: Fixed [qsm_result] shortcode format in results page. -* Bug: Fixed the issue with incorrect points while using Latex commands along with the anchor tags in the rich answers. - -= 7.1.14 (March 25, 2021) = -* Bug: Fixed security and Vulnerability issues. -* Bug: Fixed the inability to recognize correct answer for Question type Paragraph. -* Bug: Fixed the issue of question not displaying when randomizing questions by category. -* Bug: Fixed the issue of [latex] shortcode not working on retake quiz. -* Enhancement: Added the feature to Unlink questions from quiz. -* Enhancement: UI improvements for Quiz Editor. - -= 7.1.13 (March 9, 2021) = -* Bug: Fixed several security issues. -* Bug: Fixed the issue of audio and video player not showing in question content -* Bug: Fixed the issue of [latex] shortcode not showing Red cross mark for incorrect option. -* Bug: Fixed the issue required field getting surpassed by spaces in contact form. - -= 7.1.12 (February 22, 2021) = -* Bug: Fixed prevention of SQL injection while using result shortcode and question bank. -* Bug: Fixed the issue of broken [latex] shortcode in result and user dashboard page. -* Enhancement: Added option to end the quiz if answer is wrong. -* Enhancement: Added option to turn off the HTML auto complete. -* Enhancement: Modified background color to fix contrast ratios from SEO perspective. - -= 7.1.11 (January 27, 2021) = -* Bug: Fixed jquery issue while editing the result page. -* Bug: Added string translation for %POLL_RESULTS_X% variable. -* Bug: Fixed incorrect score while using point value with decimal. -* Enhancement: Added link support in contact field label. -* Enhancement: Added HTML support in email tab. -* Enhancement: Added option to add link in Hint field. -* Enhancement: Added support for HTML tags in Correct answer info field. -* Enhancement: Added option to view roadmap. -* Enhancement: Added option to delete questions from database. -* Enhancement: Changed the quiz status by default to Draft. - - -= 7.1.10 (December 29, 2020) = -* Bug: Fixed the inconsistency between no of participants and available results. -* Bug: Fixed incorrect pagination in results page. -* Bug: Fixed the issue with interchanging of settings while using two quiz on same page. -* Bug: Fixed shortcode not working while using rich answer. -* Bug: Fixed ID and Class names not showing on result page while using rich answer. -* Bug: Fixed selected options not being shown while using Polar question type. -* Enhancement: Changed the captcha validation message. -* Enhancement: Added the option to round off Score of correct/incorrect answer to a whole number. - -= 7.1.9 (December 14, 2020) = -* Bug: Fixed the issue where answers with apostrophe's are not being recognized as correct. -* Bug: Fixed the issue where inline are shown twice when Random Questions are enabled. -* Bug: Fixed the issue with point score and maximum point variable -* Bug: Fixed the issue where only last answer display as correct when all the answers were marked correct. -* Enhancement: Added Limit Text option for paragraph question type. -* Enhancement: Added an option for inserting a link in the Correct info. - -= 7.1.8 (November 18, 2020) = -* Bug: Fixed required field not working while using Date question type. -* Bug: Fixed the issue of right answers containing apostrophes marked as incorrect in Multiple Response/ Multiple Choice questions -* Bug: Fixed incorrect message while using rich answer type while using Show results inline option. -* Bug: Fixed CSS overlapping issue for quiz_section class while using auto pagination. -* Bug: Fixed continuous loading of result page while using landing page addon. -* Bug: Fixed number question type not being recorded while using Force submit after timer expires. -* Enhancement: Allowed plus, dash, bracket and slash in phone contact field. -* Enhancement: Added option to limit the characters in Number question type. - -= 7.1.7 (November 10, 2020) = -* Bug: Fixed math formula not showing on result page. -* Bug: Fixed incorrect results while using %POLL_RESULTS_X% template variable. -* Bug: Fixed advanced timer not showing while questions per page option. -* Bug: Fixed translation issue with string 'No Answer Provided'. - -= 7.1.6 (October 29, 2020) = -* Bug: Fixed division by zero error while limiting number of questions. -* Bug: Fixed inclusion of file upload question type in calculation of average point and average category point. - -= 7.1.5 (October 26, 2020) = -* Bug: Fixed logic addon rules not being copied while duplicating quiz. -* Bug: Fixed vietnamese accents and special characters not being recognized in quiz result page. -* Bug: Fixed apostrophe and double quotes not working with Dropdown question type. -* Bug: Fixed apostrophe being marked as incorrect for %USER_ANSWERS_DEFAULT% template variable. -* Bug: Fixed question's answers being case sensitive while using %USER_ANSWERS_DEFAULT% template variable. -* Bug: Fixed HTML codes appearing in email while using rich answer type. -* Bug: Fixed Polar question type scoring being rounded off to integers incorrectly. -* Bug: Fixed timer not appearing while using retaking a quiz on result page. - -= 7.1.4 (October 06, 2020) = -* Bug: Fixed point score issues when answer type is Rich Answer with HTML tags. -* Enhancement: Added JS hook for quiz to enhance JS event. -* Enhancement: Added .pot file to translate string into any language. -* Enhancement: Added %POINT_SCORE% variable support in %QUESTIONS_ANSWERS% template variable. -* Enhancement: Added option to display Correct Answer Info with inline result. - -= 7.1.3 (September 22, 2020) = -* Bug: Fixed issues when email templates were not showing if classic editor was disabled. -* Bug: Fixed the issue of Certificate Addon link not showing in admin result detail page issue. -* Bug: Fixed point score calculation issue for rich answers. -* Bug: Fixed the issue of question title not showing on front while using captcha question type. -* Bug: Fixed the issue of Comment Field showing placeholder text when the comment field is blank. -* Bug: Removed unnecessary gap between question and answers in quiz result page. -* Bug: Fixed the issue of text showing in the next line on mobile while using Fill in the blank question type. -* Bug: Fixed the issue of apostrophes showing backslash in email content. -* Bug: Fixed the issue of cloning of the question which was creating a blank answer -* Bug: Fixed conflict between %QUESTION_ANSWER_X% variable and Extra Template Variables. -* Bug: Fixed %QUESTION_ANSWER_X% variable content issue in email. -* Enhancement: Implemented %CORRECT_SCORE% template variable score to round figure. -* Enhancement: Added the option to disable scroll on click of next and previous button. -* Enhancement: Added the option of Deleting a question from question bank while deleting the quiz. -* Enhancement: Added a message when multiple choice limits are reached while using Multiple Response and Horizontal Multiple Response question type. - -= 7.1.2 (September 04, 2020) = -* Bug: Fixed admin results page to make it compatible with new variable %QUESTIONS_ANSWERS_DEFAULT%. -* Bug: Fixed issues with %QUESTIONS_ANSWERS_DEFAULT% variable in quiz result while using point based quiz. -* Bug: Fixed validation issue on front end while using Deselect Answer option. -* Bug: Fixed issues with inline results when there is extra spacing between words. -* Enhancement: Added feature to show the uploaded file into media library for File Upload question type. - -= 7.1.1 (September 02, 2020) = -* Bug: Fixed problem with questions on front end while using random questions option. -* Bug: Fixed submit button overlapping issue with progress bar for auto pagination. -* Bug: Fixed the UI of meta boxes on Dashboard Page, Tools Page and Help Page. - -= 7.1.0 (August 31, 2020) = -* Enhancement: Added a new variable %USER_ANSWERS_DEFAULT% to improve default result page. All new quizzes will have this variable by default. -* Enhancement: Created new %AMOUNT_INCORRECT% and %AMOUNT_ATTEMPTED% template variable to enhance the quiz result page. -* Enhancement: Added time( hours and minute ) support in quiz start and end date. -* Enhancement: Added option in setting menu to delete data related to QSM on deletion of plugin. -* Enhancement: Added option in setting menu to enable/disable the Background Quiz Email Process. -* Enhancement: Added qsm prefixes to email classes. -* Enhancement: Added feature to view uploaded file in admin result page for File Upload question type. -* Enhancement: Added option to show only title in quiz result page. -* Enhancement: Added a button to view uploaded file in quiz result page and replaced the empty spaces in the uploaded file slug with dashes. -* Enhancement: Added a check box to select/deselect question in Question Bank Popup. -* Bug: Fixed issues where questions were not showing up in admin when there is no pages in quiz. -* Bug: Fixed jquery error when editor is changed to text in Quiz text tab. -* Bug: Fixed PHP 7.4 Sentry Issues while creating new quiz. -* Bug: Fixed issues with Allowed file types while question editing. -* Bug: Fixed submit button position for auto pagination. -* Bug: Fixed issues with quiz loading when pagination is enabled. - -= 7.0.2 (August 18, 2020) = -* Enhancement: Checked compatibility with WordPress 5.5. -* Enhancement: Added option to customize the inline correct/incorrect messages. -* Enhancement: Added video, audio, youtube and gallery support while displaying message before quiz. -* Enhancement: Added support of template variables when redirecting to result page. -* Enhancement: Added new template variable %MAXIMUM_POINTS% to display the maximum possible points per quiz. -* Enhancement: Added option to select quiz in Gutenberg block editor. -* Enhancement: Email and name fields will be captured automatically for logged in user. -* Enhancement: Upgraded user interface of addons settinga page. -* Bug: Fixed score calculation issues. -* Bug: Fixed issues while editing quiz's text tab. -* Bug: Fixed issue where question title not showing for Polar question type. -* Bug: Fixed calculation issues while using Polar question type. -* Bug: Fixed validation issues with phone field in contact tab. -* Bug: Fixed issue where option to limit choices was not working for horizontal multiple response question type. -* Bug: Fixed security vulnerability (discovered by NinTechNet). -* Bug: Fixed issue where number of items per page was not working on Quizzes/Surveys page. -* Bug: Fixed issue with required checkbox while editing questions. -* Bug: Fixed extra contact field were not showing in admin result new template. -* Bug: Fixed issues with the title while retaking a quiz. -* Bug: Fixed issue where category not assigning while editing the question. - -= 7.0.1 (August 05, 2020) = -* Enhancement: Added option to set items per page while adding questions from question bank. -* Enhancement: Hide question description by default or when empty. -* Enhancement: Fixed the question number position while displaying questions. -* Enhancement: Added new option to skip validations when timer expires. -* Enhancement: Redesigned addons setting page. -* Enhancement: Renamed the question type for better understanding [Read Documentation](https://quizandsurveymaster.com/docs/v7/questions-tab/#Question-Type). -* Bug: Fixed issue with storing results when questions are more than 100. -* Bug: Fixed issue with force submit option after timer expiry. -* Bug: Fixed incorrect data issue in email when using %QUESTIONS_ANSWERS%. -* Bug: Fixed broken layout when editing or adding question. -* Bug: Fixed security vulnerability (discovered by Wordfence). - -= 7.0.0 (July 22, 2020) = -* Enhancement: Complete UI overhaul QSM admin view including new Dashboard -* Enhancement: A new wizard to create quizzes effortlessly -* Enhancement: Separate field for question title when you edit questions -* Enhancement: Updated UI of several pages in admin panel -* Enhancement: Added new template for results page in admin panel -* Enhancement: Added background email feature to improve performance while displaying results. -* Bug: Fixed issue where recaptcha appears on every page -* Bug: Fixed a database error where some users were not able to create a quiz (Error Code: 0001) -* Bug: Fixed cross-site scripting vulnerability (discovered by Vishnupriya Ilango of Fortinet's FortiGuard Labs.) -* Bug: Fixed issues while duplicating a quiz - -= 6.4.12 (June 22, 2020) = -* Bug: Fixed validation issue in email with spaces. -* Bug: Fixed issues with settings related to number of times a user can take quiz. -* Bug: Fixed missing time calculation while retaking quiz. -* Bug: Fixed incorrect calculation of %QUESTION_ANSWER_CORRECT% and %QUESTION_ANSWER_INCORRECT% variables. -* Bug: Fixed time up popup with advanced timer on retaking quiz. -* Bug: Removed irrelevant queries running behind the scene on each admin page. -* Bug: Removed duplicate column name database error. -* Bug: Removed orphaned plugin settings on its deletion. -* Bug: Fixed issues with fill in the blank question type when using polylang. -* Enhancement: Added user notification for collecting and storing IP addresses setting. -* Bug: Fixed inconsistent polar question type title. - -= 6.4.11 (May 22, 2020) = -* Bug: Removed static data from about us page. -* Bug: Fixed progress bar JS error and its calculation issues. -* Bug: Fixed issue with spaces before tables in questions. -* Bug: Fixed scroll to top issue for pagination. -* Bug: Fixed incorrect calculation with %AMOUNT_CORRECT% and %POINT_SCORE% variables. -* Bug: Removed unnecessary query repetitions. -* Enhancement: Added filter to add additional data to email content. -* Enhancement: Trim white space at the end of text answers. -* Enhancement: Created new function to check whether plugin is activated or not (https://wordpress.org/support/topic/error-on-submitting-quiz/#post-12821263) -* Enhancement: Added progress bar support for options tab pagination. -* Enhancement: Added new variable %QUESTION_ANSWER_X% to show specific question’s answer. - -= 6.4.10 (May 05, 2020) = -* Bug: Fixed issue while using quotes in CSS (https://github.com/QuizandSurveyMaster/quiz_master_next/issues/874). -* Bug: Fixed issue where text label overrides checkbox. -* Bug: Fixed duplicate messages when login is required. -* Bug: Fixed unwanted appearance of timer popup (https://wordpress.org/support/topic/time-is-up-message-is-displayed-for-odd-reason/#post-12749059). -* Bug: Fixed issue with latex syntax on result page. -* Enhancement: Added pagination while importing questions from question bank to increase performance - -= 6.4.9 (April 21, 2020) = -* Bug: Fixed popup design issues. - -= 6.4.8 (April 20, 2020) = -* Bug: Changed the quiz post type slug to solve the conflict with LMS plugin -* Feature: Added the button to remove the result data permanent -* Feature: Added supporting code for new advanced timer -* Feature: Option to select categories for random questions -* Enhancement: JavaScript error messages will show up only for WordPress admins. - -= 6.4.7 (April 07, 2020) = -* Bug: Solved jquery UI error -* Bug: Customized text using the "Text tab" and remove from "Options Tab" for user is not logged in -* Bug: Fixed share Quizz's results on Social Media ( https://wordpress.org/support/topic/sharing-to-social-media/ ) -* Bug: For polar question type added the validation while creating option -* Bug: Solved phone number field validation -* Bug: Solved User Dashboard addon issue for first row -* Feature: Special capabilities #810 ( https://github.com/QuizandSurveyMaster/quiz_master_next/issues/810 ) -* Feature: Added Show JS Error library to show the JS Error in quiz page -* Feature: Changed type of quiz_results to MEDIUMTEXT (16M size) ( https://github.com/QuizandSurveyMaster/quiz_master_next/issues/522 ) - -= 6.4.5 (March 16, 2020) = -* Bug: Hint not readable -* Bug: Full html of the option is being output in the ID of wrapper div and in the value of the option ( https://github.com/QuizandSurveyMaster/quiz_master_next/issues/849 ) -* Bug: QSM not picking up user select answer when empty spaces at the end -* Feature: Added checkbox for selecting questions from question bank ( https://wordpress.org/support/topic/adding-questions-from-question-bank/ ) -* Feature: Take to quiz edit after creating a new quiz -* Feature: added 'deselect answer' button for multiple choice and horizontal multiple choice question type - -= 6.4.4 (Feb 24, 2020) = -* Bug: Security Issues reported by WORDFENCE -* Bug: Change text in Get a Free Addon page -* Feature: Change sendy to sendinblue in free addon page -* Feature: Added sorting functionality on name and last activity - -= 6.4.3 (Feb 6, 2020) = -* Bug: Solved user limit issue with ip address -* Bug: Solved Search input issue on Quizzes/Surveys -* Added: added question type help link and changed the old documentation in whole plugin -* Feature: Added polar question type - - -= 6.4.2 (Jan 27, 2020) = -* Bug: Solved Email without (https://github.com/QuizandSurveyMaster/quiz_master_next/issues/831) - -= 6.4.1 (Jan 24, 2020) = -* Bug: Solve vulnerability issues reported by wordfence -* Bug: PHP notices in Settings page -* Bug: Audio files does not show and play in the Question -* Bug: Unable to rename quiz -* Bug: Thumbnail and Medium size image does not show up in Question -* Bug: PHP warnings in get free adon page -* Bug: Video Shortcode does not work in Question -* Feature: WordPress 5.3 compatability - -= 6.4 (Jan 1, 2020) = -* Bug: Result summary page is not displaying Math problems -* Feature: Client wants users to upload images/attachments to the survey -* Bug: Edit question popup not working -* Bug: PHP Warnings -* Bug: Quiz post setting not working properly -* Bug: Broken links to documentation pages in quiz setting -* Bug: Export & Import addon bug -* Bug: Customising form with CSS is not easy -* Bug: Bug Regarding Pagination Feature -* Feature: User wants a logic to work in the same way for Checkbox & Multiple choice questions -* Feature: Provide an export button on top of quiz index - -= 6.3.6 (Nov 28, 2019) = -* Included all the suggestions made by WordPress.org team -* Made external files loading from local website -* Security updates - type safe for all $_GET and $_POST vars -* Update out of date library (Chart.min.js) - -= 6.3.5 (Nov 22, 2019) = -* New Design Elements -* Show page count for multipage quizzes -* Get Quiz and Survey Data Using Wordpress API (https://github.com/QuizandSurveyMaster/quiz_master_next/issues/769) -* Filters and hooks listed on documentation -* Animations/transition options for questions (https://github.com/QuizandSurveyMaster/quiz_master_next/issues/719) -* Bug: WordPress embed shortcode does not work in question -* Remove advertisement from top bar in quizzes -* Results table design change -* XSS Vulnerability (https://github.com/QuizandSurveyMaster/quiz_master_next/issues/795) - -= 6.3.4 (Oct 24, 2019) = -* Massive overhaule for being responsive in admin panel. -* Checkbox limit ([Issue #743] https://github.com/QuizandSurveyMaster/quiz_master_next/issues/743) -* Logic addon bug ([Issue #760] https://github.com/QuizandSurveyMaster/quiz_master_next/issues/760) -* Add filter to results array ([Issue #785] https://github.com/QuizandSurveyMaster/quiz_master_next/issues/785) - -= 6.3.3 (Oct 04, 2019) = -* Option to disable "retake" quiz option. -* Mouse pointer over the FB / TW buttons -* Translate for "Retake Quiz" ([Issue #773] https://github.com/QuizandSurveyMaster/quiz_master_next/issues/773) -* Radio buttons hard to select ([WP Issue] (https://wordpress.org/support/topic/radio-buttons-are-hard-to-select-on-mobile-devices/)) -* Results page enhancements - -= 6.3.2 (July 06, 2019) = -* UI Changes -* Addons Pricing Page Update -* Free Addon Page Added -* Show results of quiz in realtime - #646 -* Timer Enhacements - Auto submit at expiry and show message on expiry -* Personality Quiz Enhancements - Show category on frontend and Show results per category -* Retake Quiz - #661 -* Question Bank Enhacements - #39 -* Facebook Button Icons - -= 6.3.1 (May 19, 2019) = -* Closed Bug: Duplicate post issue ([Issue #758](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/758)) -* Closed Enhancement: Option to turn off autofill ([WP Issue](https://wordpress.org/support/topic/can-you-add-an-option-to-turn-off-autofill-on-galaxy-phones-and-other-devices/)) -* Added Feature: Preview quiz within the quiz edit page. -* Added Feature: Auto save quiz and questions -* Closed Enhancement: Disable autofill for contact fields ([Issue #718](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/718)) -* Closed Enhancement: Added %POLL_RESULTS_X% tag for results page to show poll results ([Issue #458](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/458)) -* Closed Bug: Facebook Share not working properly ([WP Issue](https://wordpress.org/support/topic/facebook-share-40/)) - - -= 6.3.0 (April 20, 2019) = -* Massive UI update -* Closed Enhancement: Support for Image and Rich answers -([Issue #146](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/146)) - -= 6.2.2 (March 14, 2019) = -* Security update as suggested by WordPress team. - -= 6.2.1 (February 20, 2019) = -* Fixes cut off submit button on mobile phone issue -* Switches "Frank Corso" with "QSM Team" in relevant places - -= 6.2.0 (January 31, 2019) = -* Closed Enhancement: Create new alert system on quiz options page ([Issue #754](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/754)) -* Closed Bug: No access allowed when clicking "Support" from plugins page ([Issue #753](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/753)) -* Closed Bug: To many redirects ([Issue #745](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/745)) -* Closed User Request: Allow default email to be deleted or turned off ([Issue #735](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/735)) -* Closed Enhancement: Rewrite emails to allow for different conditions ([Issue #379](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/379)) -* Closed Enhancement: Rewrite results pages to allow for different conditions ([Issue #378](https://github.com/QuizandSurveyMaster/quiz_master_next/issues/378)) - -([Read Full Changelog](https://github.com/QuizandSurveyMaster/quiz_master_next/blob/master/CHANGELOG.md)) +([Read Full Changelog](https://quizandsurveymaster.com/qsm-changelog/)) == Upgrade Notice ==
Vulnerability mechanics
Root cause
"Missing input validation and escaping of the `question_id` parameter in the `qsm_bulk_delete_question_from_database` AJAX action leads to SQL injection."
Attack vector
An attacker with at least Contributor-level privileges on a WordPress site can exploit this by sending a crafted AJAX request to the `qsm_bulk_delete_question_from_database` action. The `question_id` parameter is not sanitized or escaped before being used in a SQL query, enabling SQL injection. The attacker can manipulate the parameter to extract, modify, or delete arbitrary data from the WordPress database. No additional authentication beyond the Contributor role is required, and the attack is performed over HTTP via the WordPress admin AJAX endpoint.
Affected code
The vulnerability exists in the `qsm_bulk_delete_question_from_database` AJAX action handler. The `question_id` parameter is passed directly into a SQL query without proper validation or escaping, allowing an attacker to inject malicious SQL fragments. The patch file is not fully shown in the diff, but the changelog and commit message confirm the fix addresses input validation for question deletion.
What the fix does
The patch, released as version 9.0.2, addresses the vulnerability by adding proper user permission checks and input validation for the question deletion functionality [patch_id=1889122]. The changelog explicitly states "Improved user permission checks and input validation for question deletion" and "Fixed security vulnerability." By validating and escaping the `question_id` parameter before it reaches the SQL query, the patch prevents attackers from injecting arbitrary SQL commands through the AJAX action.
Preconditions
- authThe attacker must have at least the Contributor role on the WordPress site.
- configThe QSM plugin must be installed and active with a version before 9.0.2.
- networkThe attacker must be able to send AJAX requests to the WordPress admin-ajax.php endpoint.
Generated on May 23, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
1- wpscan.com/vulnerability/e3eee6bc-1f69-4be1-b323-0c9b5fe7535e/mitreexploitvdb-entrytechnical-description
News mentions
0No linked articles in our index yet.