Skip to content

fix: React backwards-compatibility with WP < 6.6#3301

Merged
jasonbahl merged 1 commit into
wp-graphql:developfrom
justlevine:fix/react-bc
Feb 10, 2025
Merged

fix: React backwards-compatibility with WP < 6.6#3301
jasonbahl merged 1 commit into
wp-graphql:developfrom
justlevine:fix/react-bc

Conversation

@justlevine
Copy link
Copy Markdown
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
Comment thread packages/wpgraphiql/app.js
@qlty-cloud-legacy
Copy link
Copy Markdown

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.

Comment thread build/extensions.js
@@ -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

'[wordpress.org](1)' can be anywhere in the URL, and arbitrary hosts may come before or after it.
Comment thread build/extensions.js
@@ -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

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

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
Copy Markdown
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
Copy Markdown
Collaborator

Thanks for tracking this down and fixing! 🙏🏻

@jasonbahl jasonbahl merged commit 402b828 into wp-graphql:develop Feb 10, 2025
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

4 participants