Skip to content

Conversation

@justlevine
Copy link
Collaborator

What does this implement/fix? Explain your changes.

This PR fixes the regressions reported in #3300 in the following ways:

  • Drops wp-scripts down to v27.x, where [react-jsx-runtime] is still bundled. (Fixes < WP6.6)
  • Fixes the extensions root file (and updates the graphiql root file) to check for React 18's createRoot(), before falling back to React 17's render() (Fixes WP < 6.2 )

Does this close any currently open issues?

Fixes #3300

Any relevant logs, error output, GraphiQL screenshots, etc?

Any other comments?

  • Long term a react-jsx-runtime polyfill can be shipped but it requires cleanign up out asset-handling first.
  • Maybe it makes sense for us to Bump to WP 6.2 (in our WPGraphQL 3.0 release)? React 18 seems like a good baseline than whatever 6.0 represents ), and support for a 2-year-old version of WP still feels pretty generous.

Where has this been tested?

Operating System: Ubuntu 24.04 (wsl2 + devilbox + php 8.2.26)

WordPress Version: Tested againt. 5.9, 6.1, 6.2, 6.6, 6.7.1

@justlevine justlevine requested a review from jasonbahl February 9, 2025 12:43
@justlevine justlevine added status: in review Awaiting review before merging or closing needs: reviewer response This needs the attention of a codeowner or maintainer regression Bug that causes a regression to a previously working feature labels Feb 9, 2025
@qlty-cloud-legacy
Copy link

Code Climate has analyzed commit add3bd0 and detected 2 issues on this pull request.

Here's the issue category breakdown:

Category Count
Duplication 2

View more on Code Climate.

@@ -1 +1 @@
(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.element,n=window.React,a=window.wp.i18n,i=window.wp.components,s=window.wp.apiFetch;var l=e.n(s);const r=window.ReactJSXRuntime,o=({plugin:e})=>{const{installing:s,activating:o,status:p,error:c,installPlugin:u,activatePlugin:d}=((e,t)=>{const[i,s]=(0,n.useState)(!1),[r,o]=(0,n.useState)(!1),[p,c]=(0,n.useState)(""),[u,d]=(0,n.useState)(""),w=(e,t="")=>{c(e),d(t)},h=async(n=t)=>{if(o(!0),w((0,a.__)("Activating...","wp-graphql")),!n){let t=new URL(e).pathname.split("/").filter(Boolean).pop();n=`${t}/${t}.php`}try{const t=await l()({path:`/wp/v2/plugins/${n}`,method:"PUT",data:{status:"active"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}});if("active"===t.status)return w((0,a.__)("Active","wp-graphql")),window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e?{...t,installed:!0,active:!0}:t)),!0;throw t.message.includes("Plugin file does not exist")?new Error((0,a.__)("Plugin file does not exist","wp-graphql")):new Error((0,a.__)("Activation failed","wp-graphql"))}catch(e){throw w((0,a.__)("Activation failed","wp-graphql"),e.message||(0,a.__)("Activation failed","wp-graphql")),e}finally{s(!1),o(!1)}};return{installing:i,activating:r,status:p,error:u,installPlugin:async()=>{s(!0),w((0,a.__)("Installing...","wp-graphql"));let n=new URL(e).pathname.split("/").filter(Boolean).pop();try{if("inactive"!==(await l()({path:"/wp/v2/plugins",method:"POST",data:{slug:n,status:"inactive"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}})).status)throw new Error((0,a.__)("Installation failed","wp-graphql"));await h(t)}catch(e){if(!e.message.includes("destination folder already exists"))throw w((0,a.__)("Installation failed","wp-graphql"),e.message||(0,a.__)("Installation failed","wp-graphql")),s(!1),e;await h(t)}},activatePlugin:h}})(e.plugin_url,e.plugin_path),[w,h]=(0,t.useState)(e.installed),[g,_]=(0,t.useState)(e.active),[m,x]=(0,t.useState)(!0);(0,t.useEffect)((()=>{h(e.installed),_(e.active)}),[e]);const b=new URL(e.plugin_url).host,{buttonText:f,buttonDisabled:v}=((e,t,n,i,s,l,r)=>{let o,p=!1,c=null;const u=e=>()=>window.open(e,"_blank");if(s)o=(0,a.__)("Installing...","wp-graphql"),p=!0;else if(l)o=(0,a.__)("Activating...","wp-graphql"),p=!0;else if(i)o=(0,a.__)("Active","wp-graphql"),p=!0;else if(n)o=(0,a.__)("Activate","wp-graphql"),c=r;else{const e=new URL(t).hostname.toLowerCase();switch(!0){case/github\.com$/.test(e):o=(0,a.__)("View on GitHub","wp-graphql"),c=u(t);break;case/bitbucket\.org$/.test(e):o=(0,a.__)("View on Bitbucket","wp-graphql"),c=u(t);break;case/gitlab\.com$/.test(e):o=(0,a.__)("View on GitLab","wp-graphql"),c=u(t);break;case/wordpress\.org$/.test(e):o=(0,a.__)("Install & Activate","wp-graphql"),c=r;break;default:o=(0,a.__)("View Plugin","wp-graphql"),c=u(t)}}return{buttonText:o,buttonDisabled:p,buttonOnClick:c}})(0,e.plugin_url,w,g,s,o),q=({author:e})=>e&&e.name&&e.homepage?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("em",{children:"By "}),(0,r.jsx)("cite",{children:(0,r.jsx)("a",{href:e.homepage,target:"_blank",rel:"noopener noreferrer",children:e.name})},e.homepage)]}):null;return(0,r.jsxs)("div",{className:"plugin-card",children:[(0,r.jsxs)("div",{className:"plugin-card-top",children:[(0,r.jsxs)("div",{className:"name column-name",children:[(0,r.jsx)("h2",{children:e.name}),(0,r.jsx)(q,{author:e.author}),e.experiment&&(0,r.jsx)("em",{className:"plugin-experimental",children:"(experimental)"})]}),(0,r.jsx)("div",{className:"action-links",children:(0,r.jsxs)("ul",{className:"plugin-action-buttons",children:[b.includes("wordpress.org")&&(0,r.jsx)("li",{children:(0,r.jsxs)("button",{type:"button",className:"button "+(g?"button-disabled":"button-primary"),disabled:v,onClick:async()=>{const t=w,n=g;try{w?(await d(e.plugin_path),_(!0)):(await u(),h(!0),_(!0))}catch(e){h(t),_(n)}finally{window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e.plugin_url?{...t,installed:w,active:g}:t))}},children:[f,(s||o)&&(0,r.jsx)(i.Spinner,{})]})}),b.includes("github.com")&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.plugin_url,target:"_blank",rel:"noopener noreferrer",className:"button button-secondary",children:(0,a.__)("View on GitHub","wp-graphql")})}),e.support_url&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.support_url,target:"_blank",rel:"noopener noreferrer",className:"thickbox open-plugin-details-modal",children:(0,a.__)("Get Support","wp-graphql")})}),e.settings_url&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.settings_url,children:(0,a.__)("Settings","wp-graphql")})})]})}),(0,r.jsx)("div",{className:"desc column-description",children:(0,r.jsx)("p",{children:e.description})})]}),c&&m&&(0,r.jsx)(i.Notice,{status:"error",isDismissible:!0,onRemove:()=>x(!1),children:c})]})},p=()=>{const[e,t]=(0,n.useState)([]);return(0,n.useEffect)((()=>{window.wpgraphqlExtensions&&window.wpgraphqlExtensions.extensions&&t(window.wpgraphqlExtensions.extensions)}),[]),(0,r.jsx)("div",{className:"wp-clearfix",children:(0,r.jsx)("div",{className:"plugin-cards",children:e.map((e=>(0,r.jsx)(o,{plugin:e},e.plugin_url)))})})};document.addEventListener("DOMContentLoaded",(()=>{const e=document.getElementById("wpgraphql-extensions");e&&(0,t.createRoot)(e).render((0,t.createElement)(p))}))})(); No newline at end of file
(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,n=window.wp.element,a=window.wp.i18n,l=window.wp.components,i=window.wp.apiFetch;var r=e.n(i);const s=({plugin:e})=>{const{installing:i,activating:s,status:o,error:p,installPlugin:c,activatePlugin:u}=((e,n)=>{const[l,i]=(0,t.useState)(!1),[s,o]=(0,t.useState)(!1),[p,c]=(0,t.useState)(""),[u,w]=(0,t.useState)(""),g=(e,t="")=>{c(e),w(t)},m=async(t=n)=>{if(o(!0),g((0,a.__)("Activating...","wp-graphql")),!t){let n=new URL(e).pathname.split("/").filter(Boolean).pop();t=`${n}/${n}.php`}try{const n=await r()({path:`/wp/v2/plugins/${t}`,method:"PUT",data:{status:"active"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}});if("active"===n.status)return g((0,a.__)("Active","wp-graphql")),window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e?{...t,installed:!0,active:!0}:t)),!0;throw n.message.includes("Plugin file does not exist")?new Error((0,a.__)("Plugin file does not exist","wp-graphql")):new Error((0,a.__)("Activation failed","wp-graphql"))}catch(e){throw g((0,a.__)("Activation failed","wp-graphql"),e.message||(0,a.__)("Activation failed","wp-graphql")),e}finally{i(!1),o(!1)}};return{installing:l,activating:s,status:p,error:u,installPlugin:async()=>{i(!0),g((0,a.__)("Installing...","wp-graphql"));let t=new URL(e).pathname.split("/").filter(Boolean).pop();try{if("inactive"!==(await r()({path:"/wp/v2/plugins",method:"POST",data:{slug:t,status:"inactive"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}})).status)throw new Error((0,a.__)("Installation failed","wp-graphql"));await m(n)}catch(e){if(!e.message.includes("destination folder already exists"))throw g((0,a.__)("Installation failed","wp-graphql"),e.message||(0,a.__)("Installation failed","wp-graphql")),i(!1),e;await m(n)}},activatePlugin:m}})(e.plugin_url,e.plugin_path),[w,g]=(0,n.useState)(e.installed),[m,d]=(0,n.useState)(e.active),[h,_]=(0,n.useState)(!0);(0,n.useEffect)((()=>{g(e.installed),d(e.active)}),[e]);const E=new URL(e.plugin_url).host,{buttonText:b,buttonDisabled:f}=((e,t,n,l,i,r,s)=>{let o,p=!1,c=null;const u=e=>()=>window.open(e,"_blank");if(i)o=(0,a.__)("Installing...","wp-graphql"),p=!0;else if(r)o=(0,a.__)("Activating...","wp-graphql"),p=!0;else if(l)o=(0,a.__)("Active","wp-graphql"),p=!0;else if(n)o=(0,a.__)("Activate","wp-graphql"),c=s;else{const e=new URL(t).hostname.toLowerCase();switch(!0){case/github\.com$/.test(e):o=(0,a.__)("View on GitHub","wp-graphql"),c=u(t);break;case/bitbucket\.org$/.test(e):o=(0,a.__)("View on Bitbucket","wp-graphql"),c=u(t);break;case/gitlab\.com$/.test(e):o=(0,a.__)("View on GitLab","wp-graphql"),c=u(t);break;case/wordpress\.org$/.test(e):o=(0,a.__)("Install & Activate","wp-graphql"),c=s;break;default:o=(0,a.__)("View Plugin","wp-graphql"),c=u(t)}}return{buttonText:o,buttonDisabled:p,buttonOnClick:c}})(0,e.plugin_url,w,m,i,s);return(0,t.createElement)("div",{className:"plugin-card"},(0,t.createElement)("div",{className:"plugin-card-top"},(0,t.createElement)("div",{className:"name column-name"},(0,t.createElement)("h2",null,e.name),(0,t.createElement)((({author:e})=>e&&e.name&&e.homepage?(0,t.createElement)(t.Fragment,null,(0,t.createElement)("em",null,"By "),(0,t.createElement)("cite",{key:e.homepage},(0,t.createElement)("a",{href:e.homepage,target:"_blank",rel:"noopener noreferrer"},e.name))):null),{author:e.author}),e.experiment&&(0,t.createElement)("em",{className:"plugin-experimental"},"(experimental)")),(0,t.createElement)("div",{className:"action-links"},(0,t.createElement)("ul",{className:"plugin-action-buttons"},E.includes("wordpress.org")&&(0,t.createElement)("li",null,(0,t.createElement)("button",{type:"button",className:"button "+(m?"button-disabled":"button-primary"),disabled:f,onClick:async()=>{const t=w,n=m;try{w?(await u(e.plugin_path),d(!0)):(await c(),g(!0),d(!0))}catch(e){g(t),d(n)}finally{window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e.plugin_url?{...t,installed:w,active:m}:t))}}},b,(i||s)&&(0,t.createElement)(l.Spinner,null))),E.includes("github.com")&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.plugin_url,target:"_blank",rel:"noopener noreferrer",className:"button button-secondary"},(0,a.__)("View on GitHub","wp-graphql"))),e.support_url&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.support_url,target:"_blank",rel:"noopener noreferrer",className:"thickbox open-plugin-details-modal"},(0,a.__)("Get Support","wp-graphql"))),e.settings_url&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.settings_url},(0,a.__)("Settings","wp-graphql"))))),(0,t.createElement)("div",{className:"desc column-description"},(0,t.createElement)("p",null,e.description))),p&&h&&(0,t.createElement)(l.Notice,{status:"error",isDismissible:!0,onRemove:()=>_(!1)},p))},o=()=>{const[e,n]=(0,t.useState)([]);return(0,t.useEffect)((()=>{window.wpgraphqlExtensions&&window.wpgraphqlExtensions.extensions&&n(window.wpgraphqlExtensions.extensions)}),[]),(0,t.createElement)("div",{className:"wp-clearfix"},(0,t.createElement)("div",{className:"plugin-cards"},e.map((e=>(0,t.createElement)(s,{key:e.plugin_url,plugin:e})))))};document.addEventListener("DOMContentLoaded",(()=>{const e=document.getElementById("wpgraphql-extensions");e&&(n.createRoot?(0,n.createRoot)(e).render((0,t.createElement)(o,null)):(0,n.render)((0,t.createElement)(o,null),e))}))})(); No newline at end of file

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
wordpress.org
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
@@ -1 +1 @@
(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.element,n=window.React,a=window.wp.i18n,i=window.wp.components,s=window.wp.apiFetch;var l=e.n(s);const r=window.ReactJSXRuntime,o=({plugin:e})=>{const{installing:s,activating:o,status:p,error:c,installPlugin:u,activatePlugin:d}=((e,t)=>{const[i,s]=(0,n.useState)(!1),[r,o]=(0,n.useState)(!1),[p,c]=(0,n.useState)(""),[u,d]=(0,n.useState)(""),w=(e,t="")=>{c(e),d(t)},h=async(n=t)=>{if(o(!0),w((0,a.__)("Activating...","wp-graphql")),!n){let t=new URL(e).pathname.split("/").filter(Boolean).pop();n=`${t}/${t}.php`}try{const t=await l()({path:`/wp/v2/plugins/${n}`,method:"PUT",data:{status:"active"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}});if("active"===t.status)return w((0,a.__)("Active","wp-graphql")),window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e?{...t,installed:!0,active:!0}:t)),!0;throw t.message.includes("Plugin file does not exist")?new Error((0,a.__)("Plugin file does not exist","wp-graphql")):new Error((0,a.__)("Activation failed","wp-graphql"))}catch(e){throw w((0,a.__)("Activation failed","wp-graphql"),e.message||(0,a.__)("Activation failed","wp-graphql")),e}finally{s(!1),o(!1)}};return{installing:i,activating:r,status:p,error:u,installPlugin:async()=>{s(!0),w((0,a.__)("Installing...","wp-graphql"));let n=new URL(e).pathname.split("/").filter(Boolean).pop();try{if("inactive"!==(await l()({path:"/wp/v2/plugins",method:"POST",data:{slug:n,status:"inactive"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}})).status)throw new Error((0,a.__)("Installation failed","wp-graphql"));await h(t)}catch(e){if(!e.message.includes("destination folder already exists"))throw w((0,a.__)("Installation failed","wp-graphql"),e.message||(0,a.__)("Installation failed","wp-graphql")),s(!1),e;await h(t)}},activatePlugin:h}})(e.plugin_url,e.plugin_path),[w,h]=(0,t.useState)(e.installed),[g,_]=(0,t.useState)(e.active),[m,x]=(0,t.useState)(!0);(0,t.useEffect)((()=>{h(e.installed),_(e.active)}),[e]);const b=new URL(e.plugin_url).host,{buttonText:f,buttonDisabled:v}=((e,t,n,i,s,l,r)=>{let o,p=!1,c=null;const u=e=>()=>window.open(e,"_blank");if(s)o=(0,a.__)("Installing...","wp-graphql"),p=!0;else if(l)o=(0,a.__)("Activating...","wp-graphql"),p=!0;else if(i)o=(0,a.__)("Active","wp-graphql"),p=!0;else if(n)o=(0,a.__)("Activate","wp-graphql"),c=r;else{const e=new URL(t).hostname.toLowerCase();switch(!0){case/github\.com$/.test(e):o=(0,a.__)("View on GitHub","wp-graphql"),c=u(t);break;case/bitbucket\.org$/.test(e):o=(0,a.__)("View on Bitbucket","wp-graphql"),c=u(t);break;case/gitlab\.com$/.test(e):o=(0,a.__)("View on GitLab","wp-graphql"),c=u(t);break;case/wordpress\.org$/.test(e):o=(0,a.__)("Install & Activate","wp-graphql"),c=r;break;default:o=(0,a.__)("View Plugin","wp-graphql"),c=u(t)}}return{buttonText:o,buttonDisabled:p,buttonOnClick:c}})(0,e.plugin_url,w,g,s,o),q=({author:e})=>e&&e.name&&e.homepage?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("em",{children:"By "}),(0,r.jsx)("cite",{children:(0,r.jsx)("a",{href:e.homepage,target:"_blank",rel:"noopener noreferrer",children:e.name})},e.homepage)]}):null;return(0,r.jsxs)("div",{className:"plugin-card",children:[(0,r.jsxs)("div",{className:"plugin-card-top",children:[(0,r.jsxs)("div",{className:"name column-name",children:[(0,r.jsx)("h2",{children:e.name}),(0,r.jsx)(q,{author:e.author}),e.experiment&&(0,r.jsx)("em",{className:"plugin-experimental",children:"(experimental)"})]}),(0,r.jsx)("div",{className:"action-links",children:(0,r.jsxs)("ul",{className:"plugin-action-buttons",children:[b.includes("wordpress.org")&&(0,r.jsx)("li",{children:(0,r.jsxs)("button",{type:"button",className:"button "+(g?"button-disabled":"button-primary"),disabled:v,onClick:async()=>{const t=w,n=g;try{w?(await d(e.plugin_path),_(!0)):(await u(),h(!0),_(!0))}catch(e){h(t),_(n)}finally{window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e.plugin_url?{...t,installed:w,active:g}:t))}},children:[f,(s||o)&&(0,r.jsx)(i.Spinner,{})]})}),b.includes("github.com")&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.plugin_url,target:"_blank",rel:"noopener noreferrer",className:"button button-secondary",children:(0,a.__)("View on GitHub","wp-graphql")})}),e.support_url&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.support_url,target:"_blank",rel:"noopener noreferrer",className:"thickbox open-plugin-details-modal",children:(0,a.__)("Get Support","wp-graphql")})}),e.settings_url&&(0,r.jsx)("li",{children:(0,r.jsx)("a",{href:e.settings_url,children:(0,a.__)("Settings","wp-graphql")})})]})}),(0,r.jsx)("div",{className:"desc column-description",children:(0,r.jsx)("p",{children:e.description})})]}),c&&m&&(0,r.jsx)(i.Notice,{status:"error",isDismissible:!0,onRemove:()=>x(!1),children:c})]})},p=()=>{const[e,t]=(0,n.useState)([]);return(0,n.useEffect)((()=>{window.wpgraphqlExtensions&&window.wpgraphqlExtensions.extensions&&t(window.wpgraphqlExtensions.extensions)}),[]),(0,r.jsx)("div",{className:"wp-clearfix",children:(0,r.jsx)("div",{className:"plugin-cards",children:e.map((e=>(0,r.jsx)(o,{plugin:e},e.plugin_url)))})})};document.addEventListener("DOMContentLoaded",(()=>{const e=document.getElementById("wpgraphql-extensions");e&&(0,t.createRoot)(e).render((0,t.createElement)(p))}))})(); No newline at end of file
(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,n=window.wp.element,a=window.wp.i18n,l=window.wp.components,i=window.wp.apiFetch;var r=e.n(i);const s=({plugin:e})=>{const{installing:i,activating:s,status:o,error:p,installPlugin:c,activatePlugin:u}=((e,n)=>{const[l,i]=(0,t.useState)(!1),[s,o]=(0,t.useState)(!1),[p,c]=(0,t.useState)(""),[u,w]=(0,t.useState)(""),g=(e,t="")=>{c(e),w(t)},m=async(t=n)=>{if(o(!0),g((0,a.__)("Activating...","wp-graphql")),!t){let n=new URL(e).pathname.split("/").filter(Boolean).pop();t=`${n}/${n}.php`}try{const n=await r()({path:`/wp/v2/plugins/${t}`,method:"PUT",data:{status:"active"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}});if("active"===n.status)return g((0,a.__)("Active","wp-graphql")),window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e?{...t,installed:!0,active:!0}:t)),!0;throw n.message.includes("Plugin file does not exist")?new Error((0,a.__)("Plugin file does not exist","wp-graphql")):new Error((0,a.__)("Activation failed","wp-graphql"))}catch(e){throw g((0,a.__)("Activation failed","wp-graphql"),e.message||(0,a.__)("Activation failed","wp-graphql")),e}finally{i(!1),o(!1)}};return{installing:l,activating:s,status:p,error:u,installPlugin:async()=>{i(!0),g((0,a.__)("Installing...","wp-graphql"));let t=new URL(e).pathname.split("/").filter(Boolean).pop();try{if("inactive"!==(await r()({path:"/wp/v2/plugins",method:"POST",data:{slug:t,status:"inactive"},headers:{"X-WP-Nonce":wpgraphqlExtensions.nonce}})).status)throw new Error((0,a.__)("Installation failed","wp-graphql"));await m(n)}catch(e){if(!e.message.includes("destination folder already exists"))throw g((0,a.__)("Installation failed","wp-graphql"),e.message||(0,a.__)("Installation failed","wp-graphql")),i(!1),e;await m(n)}},activatePlugin:m}})(e.plugin_url,e.plugin_path),[w,g]=(0,n.useState)(e.installed),[m,d]=(0,n.useState)(e.active),[h,_]=(0,n.useState)(!0);(0,n.useEffect)((()=>{g(e.installed),d(e.active)}),[e]);const E=new URL(e.plugin_url).host,{buttonText:b,buttonDisabled:f}=((e,t,n,l,i,r,s)=>{let o,p=!1,c=null;const u=e=>()=>window.open(e,"_blank");if(i)o=(0,a.__)("Installing...","wp-graphql"),p=!0;else if(r)o=(0,a.__)("Activating...","wp-graphql"),p=!0;else if(l)o=(0,a.__)("Active","wp-graphql"),p=!0;else if(n)o=(0,a.__)("Activate","wp-graphql"),c=s;else{const e=new URL(t).hostname.toLowerCase();switch(!0){case/github\.com$/.test(e):o=(0,a.__)("View on GitHub","wp-graphql"),c=u(t);break;case/bitbucket\.org$/.test(e):o=(0,a.__)("View on Bitbucket","wp-graphql"),c=u(t);break;case/gitlab\.com$/.test(e):o=(0,a.__)("View on GitLab","wp-graphql"),c=u(t);break;case/wordpress\.org$/.test(e):o=(0,a.__)("Install & Activate","wp-graphql"),c=s;break;default:o=(0,a.__)("View Plugin","wp-graphql"),c=u(t)}}return{buttonText:o,buttonDisabled:p,buttonOnClick:c}})(0,e.plugin_url,w,m,i,s);return(0,t.createElement)("div",{className:"plugin-card"},(0,t.createElement)("div",{className:"plugin-card-top"},(0,t.createElement)("div",{className:"name column-name"},(0,t.createElement)("h2",null,e.name),(0,t.createElement)((({author:e})=>e&&e.name&&e.homepage?(0,t.createElement)(t.Fragment,null,(0,t.createElement)("em",null,"By "),(0,t.createElement)("cite",{key:e.homepage},(0,t.createElement)("a",{href:e.homepage,target:"_blank",rel:"noopener noreferrer"},e.name))):null),{author:e.author}),e.experiment&&(0,t.createElement)("em",{className:"plugin-experimental"},"(experimental)")),(0,t.createElement)("div",{className:"action-links"},(0,t.createElement)("ul",{className:"plugin-action-buttons"},E.includes("wordpress.org")&&(0,t.createElement)("li",null,(0,t.createElement)("button",{type:"button",className:"button "+(m?"button-disabled":"button-primary"),disabled:f,onClick:async()=>{const t=w,n=m;try{w?(await u(e.plugin_path),d(!0)):(await c(),g(!0),d(!0))}catch(e){g(t),d(n)}finally{window.wpgraphqlExtensions.extensions=window.wpgraphqlExtensions.extensions.map((t=>t.plugin_url===e.plugin_url?{...t,installed:w,active:m}:t))}}},b,(i||s)&&(0,t.createElement)(l.Spinner,null))),E.includes("github.com")&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.plugin_url,target:"_blank",rel:"noopener noreferrer",className:"button button-secondary"},(0,a.__)("View on GitHub","wp-graphql"))),e.support_url&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.support_url,target:"_blank",rel:"noopener noreferrer",className:"thickbox open-plugin-details-modal"},(0,a.__)("Get Support","wp-graphql"))),e.settings_url&&(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.settings_url},(0,a.__)("Settings","wp-graphql"))))),(0,t.createElement)("div",{className:"desc column-description"},(0,t.createElement)("p",null,e.description))),p&&h&&(0,t.createElement)(l.Notice,{status:"error",isDismissible:!0,onRemove:()=>_(!1)},p))},o=()=>{const[e,n]=(0,t.useState)([]);return(0,t.useEffect)((()=>{window.wpgraphqlExtensions&&window.wpgraphqlExtensions.extensions&&n(window.wpgraphqlExtensions.extensions)}),[]),(0,t.createElement)("div",{className:"wp-clearfix"},(0,t.createElement)("div",{className:"plugin-cards"},e.map((e=>(0,t.createElement)(s,{key:e.plugin_url,plugin:e})))))};document.addEventListener("DOMContentLoaded",(()=>{const e=document.getElementById("wpgraphql-extensions");e&&(n.createRoot?(0,n.createRoot)(e).render((0,t.createElement)(o,null)):(0,n.render)((0,t.createElement)(o,null),e))}))})(); No newline at end of file

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High

'
github.com
' can be anywhere in the URL, and arbitrary hosts may come before or after it.
@coveralls
Copy link

Coverage Status

coverage: 83.194%. remained the same
when pulling add3bd0 on justlevine:fix/react-bc
into eb824fd on wp-graphql:develop.

@jasonbahl
Copy link
Collaborator

@justlevine I've opened up an issue to follow up with bumping the min WP version for a v3.0 release: #3304

@jasonbahl
Copy link
Collaborator

Thanks for tracking this down and fixing! 🙏🏻

@jasonbahl jasonbahl merged commit 402b828 into wp-graphql:develop Feb 10, 2025
35 of 37 checks passed
This was referenced Feb 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs: reviewer response This needs the attention of a codeowner or maintainer regression Bug that causes a regression to a previously working feature status: in review Awaiting review before merging or closing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Regression: GraphiQL IDE + Extensions screen don't work in WP <6.6

3 participants