Updates to 8.0.0
This commit is contained in:
parent
708a1fa4a4
commit
7b355505bf
|
|
@ -1 +1 @@
|
|||
<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '33d4c418a7e0cdfdfdd5');
|
||||
<?php return array('dependencies' => array('react', 'wc-blocks-checkout', 'wc-blocks-data-store', 'wc-price-format', 'wc-settings', 'wp-data', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '76dd98c6a2badbfb9781');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(()=>{"use strict";var e={20:(e,r,s)=>{var t=s(609),n=Symbol.for("react.element"),i=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,c=t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function a(e,r,s){var t,i={},a=null,p=null;for(t in void 0!==s&&(a=""+s),void 0!==r.key&&(a=""+r.key),void 0!==r.ref&&(p=r.ref),r)o.call(r,t)&&!l.hasOwnProperty(t)&&(i[t]=r[t]);if(e&&e.defaultProps)for(t in r=e.defaultProps)void 0===i[t]&&(i[t]=r[t]);return{$$typeof:n,type:e,key:a,ref:p,props:i,_owner:c.current}}r.Fragment=i,r.jsx=a,r.jsxs=a},609:e=>{e.exports=window.React},848:(e,r,s)=>{e.exports=s(20)}},r={};const s=window.wp.plugins,t=window.wc.blocksCheckout,n=window.wp.i18n,i=window.wc.priceFormat,o=window.wc.wcSettings;function c(e){return{day:(0,n._nx)("day","days",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),week:(0,n._nx)("week","weeks",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),month:(0,n._nx)("month","months",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),year:(0,n._nx)("year","years",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions")}}function l({billing_interval:e,billing_period:r},s,t){const i=c(e)[r];return s=s.trim(),1===e?`${t} ${s} ${i}`:(0,n.sprintf)(
|
||||
(()=>{"use strict";var e={20:(e,s,i)=>{var n=i(609),t=Symbol.for("react.element"),r=Symbol.for("react.fragment"),o=Object.prototype.hasOwnProperty,c=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,a={key:!0,ref:!0,__self:!0,__source:!0};function l(e,s,i){var n,r={},l=null,p=null;for(n in void 0!==i&&(l=""+i),void 0!==s.key&&(l=""+s.key),void 0!==s.ref&&(p=s.ref),s)o.call(s,n)&&!a.hasOwnProperty(n)&&(r[n]=s[n]);if(e&&e.defaultProps)for(n in s=e.defaultProps)void 0===r[n]&&(r[n]=s[n]);return{$$typeof:t,type:e,key:l,ref:p,props:r,_owner:c.current}}s.Fragment=r,s.jsx=l,s.jsxs=l},609:e=>{e.exports=window.React},848:(e,s,i)=>{e.exports=i(20)}},s={};const i=window.wp.plugins,n=window.wc.blocksCheckout,t=window.wp.i18n,r=window.wc.priceFormat,o=window.wc.wcSettings,c=window.wp.data,a=window.wc.wcBlocksData;function l(e){return{day:(0,t._nx)("day","days",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),week:(0,t._nx)("week","weeks",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),month:(0,t._nx)("month","months",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),year:(0,t._nx)("year","years",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions")}}function p({billing_interval:e,billing_period:s},i,n){const r=l(e)[s];return i=i.trim(),1===e?`${n} ${i} ${r}`:(0,t.sprintf)(
|
||||
/*
|
||||
* translators: %1$s is the price of the product. %2$s is the separator used e.g "every" or "/",
|
||||
* %3$d is the length, %4$s is week, month, year
|
||||
|
|
@ -7,29 +7,30 @@
|
|||
* translators: %1$s is the price of the product. %2$s is the separator used e.g "every" or "/",
|
||||
* %3$d is the length, %4$s is week, month, year
|
||||
*/
|
||||
(0,n.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),t,s,e,i)}function a({subscriptionLength:e,billingInterval:r}){return e===r}var p=function s(t){var n=r[t];if(void 0!==n)return n.exports;var i=r[t]={exports:{}};return e[t](i,i.exports,s),i.exports}(848);const u=(0,o.getSetting)("displayCartPricesIncludingTax",!1),m=({currency:e,values:r})=>{const{total_discount:s,total_discount_tax:i}=r,o=parseInt(s,10);if(!o)return null;const c=parseInt(i,10),l=u?o+c:o;return(0,p.jsx)(t.TotalsItem,{className:"wc-block-components-totals-discount",currency:e,label:(0,n.__)("Discount","woocommerce-subscriptions"),value:-1*l})},_=({values:e,currency:r,selectedRate:s,needsShipping:i,calculatedShipping:c})=>{if(!i||!c)return null;const l=u?parseInt(e.total_shipping,10)+parseInt(e.total_shipping_tax,10):parseInt(e.total_shipping,10),a=0===l&&(0,o.isWcVersion)("9.0",">=")?(0,p.jsx)("strong",{children:(0,n.__)("Free","woocommerce-subscriptions")}):l;return(0,p.jsx)(t.TotalsItem,{value:a,label:(0,n.__)("Shipping","woocommerce-subscriptions"),currency:r,description:!!s&&(0,n.sprintf)(
|
||||
(0,t.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),n,i,e,r)}function u({subscriptionLength:e,billingInterval:s}){return e===s}const d=(0,o.getSetting)("countryData",{}),g=(0,o.getSetting)("countries",{}),m={...Object.fromEntries(Object.keys(d).filter((e=>!0===d[e].allowBilling)).map((e=>[e,g[e]||""]))),...Object.fromEntries(Object.keys(d).filter((e=>!0===d[e].allowShipping)).map((e=>[e,g[e]||""])))},_=Object.fromEntries(Object.keys(m).map((e=>[e,d[e].locale||{}]))),b={address:["first_name","last_name","company","address_1","address_2","city","postcode","country","state","phone"],contact:["email"],order:[]},h=Object.entries(_).reduce(((e,[s,i])=>(e[s]=Object.entries(i).reduce(((e,[s,i])=>(e[s]=(e=>{const s={};return void 0!==e.label&&(s.label=e.label),void 0!==e.required&&(s.required=e.required),void 0!==e.hidden&&(s.hidden=e.hidden),void 0===e.label||e.optionalLabel||(s.optionalLabel=(0,t.sprintf)(/* translators: %s Field label. */ /* translators: %s Field label. */
|
||||
(0,t.__)("%s (optional)","woocommerce-subscriptions"),e.label)),void 0!==e.optionalLabel&&(s.optionalLabel=e.optionalLabel),e.index&&("number"==typeof e.index&&(s.index=e.index),"string"==typeof e.index&&(s.index=parseInt(e.index,10))),e.hidden&&(s.required=!1),s})(i),e)),{}),e)),{}),w=["state","country","postcode","city"],y=e=>e.some((e=>!!e.shipping_rates.length)),f=(0,o.getSetting)("collectableMethodIds",[]),v=(0,o.getSetting)("localPickupEnabled",!1);var x=function i(n){var t=s[n];if(void 0!==t)return t.exports;var r=s[n]={exports:{}};return e[n](r,r.exports,i),r.exports}(848);const k=(0,o.getSetting)("displayCartPricesIncludingTax",!1),S=({currency:e,values:s,isLoading:i})=>{const{total_discount:r,total_discount_tax:o}=s,c=parseInt(r,10);if(!c)return null;const a=parseInt(o,10),l=k?c+a:c;return(0,x.jsx)(n.TotalsItem,{className:"wc-block-components-totals-discount",currency:e,label:(0,t.__)("Discount","woocommerce-subscriptions"),value:-1*l,showSkeleton:i})},j=({values:e,currency:s,shippingRatePackages:i,isLoading:n,needsShipping:r,calculatedShipping:l,shippingAddress:p})=>{const u=(0,c.useSelect)((e=>e(a.checkoutStore).prefersCollection()));if(!r||!l)return null;const d=(_=((e,s)=>e.map((e=>({...e,shipping_rates:e.shipping_rates.filter((e=>{const i=(n=e.method_id,!!v&&(Array.isArray(n)?!!n.find((e=>f.includes(e))):f.includes(n)));var n;return s?i:!i}))}))))(i,null!=u&&u),!!y(_)&&_.every((e=>e.shipping_rates.every((e=>!e.selected||(e=>f.includes(e.method_id))(e)))))),g=!!(m=p).country&&((e,s,i="")=>{const n=i&&void 0!==h[i]?h[i]:{};return e.map((e=>({key:e,...s&&e in s?s[e]:{},...n&&e in n?n[e]:{}}))).sort(((e,s)=>e.index-s.index))})((0,o.getSetting)("addressFieldsLocations",b).address,o.defaultFields,m.country).filter((({key:e})=>w.includes(e))).every((({key:e,hidden:s,required:i})=>!0===s||!1===i||e in m&&""!==m[e]));var m,_;return(0,x.jsx)(I,{label:d?(0,t.__)("Pickup","woocommerce-subscriptions"):(0,t.__)("Delivery","woocommerce-subscriptions"),placeholder:(0,x.jsx)("span",{className:"wc-block-components-shipping-placeholder__value",children:g?(0,t.__)("No available delivery option","woocommerce-subscriptions"):(0,t.__)("Enter address to calculate","woocommerce-subscriptions")}),isLoading:n,shippingRatePackages:i,currency:s,values:e})},I=({values:e,currency:s,shippingRatePackages:i,label:r,placeholder:c,isLoading:a})=>{const l=i?.flatMap((e=>e.shipping_rates)).find((({selected:e})=>e))?.name,p=!!y(u=i)&&u.some((e=>e.shipping_rates.some((e=>e.selected))));var u;const d=!p||i?.length>1?r:(0,t.__)("Shipping","woocommerce-subscriptions"),g=k?parseInt(e.total_shipping,10)+parseInt(e.total_shipping_tax,10):parseInt(e.total_shipping,10),m=0===g&&(0,o.isWcVersion)("9.0",">=")?(0,x.jsx)("strong",{children:(0,t.__)("Free","woocommerce-subscriptions")}):g;return(0,x.jsx)(n.TotalsItem,{value:p?m:c,label:d,currency:s,showSkeleton:a,description:!!l&&(0,t.sprintf)(
|
||||
// translators: %s selected shipping rate (ex: flat rate)
|
||||
// translators: %s selected shipping rate (ex: flat rate)
|
||||
(0,n.__)("via %s","woocommerce-subscriptions"),s)})},g=({nextPaymentDate:e,subscriptionLength:r,billingPeriod:s,billingInterval:t})=>{const i=function({subscriptionLength:e,billingPeriod:r}){const s=c(e);return(0,n.sprintf)("For %1$d %2$s",e,s[r],"woocommerce-subscriptions")}({subscriptionLength:r,billingPeriod:s}),o=a({subscriptionLength:r,billingInterval:t})?(0,n.sprintf)(/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */
|
||||
(0,n.__)("Due: %1$s","woocommerce-subscriptions"),e):(0,n.sprintf)(/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */
|
||||
(0,n.__)("Starting: %1$s","woocommerce-subscriptions"),e);return(0,p.jsxs)("span",{children:[!!e&&o," ",!!r&&r>=t&&(0,p.jsx)("span",{className:"wcs-recurring-totals__subscription-length",children:i})]})},d=({currency:e,billingInterval:r,billingPeriod:s,nextPaymentDate:i,subscriptionLength:o,totals:c})=>{const l=a({billingInterval:r,subscriptionLength:o})?(0,n.__)("Total","woocommerce-subscriptions"):function({billingInterval:e,billingPeriod:r}){switch(e){case 1:if("day"===r)return(0,n.__)("Daily recurring total","woocommerce-subscriptions");if("week"===r)return(0,n.__)("Weekly recurring total","woocommerce-subscriptions");if("month"===r)return(0,n.__)("Monthly recurring total","woocommerce-subscriptions");if("year"===r)return(0,n.__)("Yearly recurring total","woocommerce-subscriptions");break;case 2:return(0,n.sprintf)(/* translators: %1$s is week, month, year */ /* translators: %1$s is week, month, year */
|
||||
(0,n.__)("Recurring total every 2nd %1$s","woocommerce-subscriptions"),r);case 3:return(0,n.sprintf)(/* Translators: %1$s is week, month, year */ /* Translators: %1$s is week, month, year */
|
||||
(0,n.__)("Recurring total every 3rd %1$s","woocommerce-subscriptions"),r);default:return(0,n.sprintf)(/* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */ /* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */
|
||||
(0,n.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),e,r)}}({billingInterval:r,billingPeriod:s});return(0,p.jsx)(t.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:e,label:l,value:c,description:(0,p.jsx)(g,{nextPaymentDate:i,subscriptionLength:o,billingInterval:r,billingPeriod:s})})},b=({subscription:e,needsShipping:r,calculatedShipping:s})=>{const{totals:o,billing_interval:c,billing_period:l,next_payment_date:a,subscription_length:g,shipping_rates:b}=e;if(!a)return null;const w=b?.[0]?.shipping_rates?.find((({selected:e})=>e))?.name,h=(0,i.getCurrencyFromPriceResponse)(o);return(0,p.jsxs)("div",{className:"wcs-recurring-totals-panel",children:[(0,p.jsx)(d,{billingInterval:c,billingPeriod:l,nextPaymentDate:a,subscriptionLength:g,totals:parseInt(o.total_price,10),currency:h}),(0,p.jsxs)(t.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:(0,n.__)("Details","woocommerce-subscriptions"),children:[(0,p.jsxs)(t.TotalsWrapper,{children:[(0,p.jsx)(t.Subtotal,{currency:h,values:o}),(0,p.jsx)(m,{currency:h,values:o})]}),(0,p.jsx)(t.TotalsWrapper,{className:"wc-block-components-totals-shipping",children:(0,p.jsx)(_,{currency:h,needsShipping:r,calculatedShipping:s,values:o,selectedRate:w})}),!u&&(0,p.jsx)(t.TotalsWrapper,{children:(0,p.jsx)(t.TotalsTaxes,{currency:h,values:o})}),(0,p.jsx)(t.TotalsWrapper,{children:(0,p.jsx)(t.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:h,label:(0,n.__)("Total","woocommerce-subscriptions"),value:parseInt(o.total_price,10)})})]})]})},w=({extensions:e,cart:r})=>{const{subscriptions:s}=e,{cartNeedsShipping:t,cartHasCalculatedShipping:n}=r;return s&&0!==s.length?s.map((({key:e,...r})=>(0,p.jsx)(b,{subscription:r,needsShipping:t,calculatedShipping:n},e))):null},h=window.wp.element,x=({extensions:e,collapsible:r,collapse:s,showItems:t,noResultsMessage:n,renderOption:i,components:o,context:c})=>{const{subscriptions:l=[]}=e,{ShippingRatesControlPackage:a}=o,u=(0,h.useMemo)((()=>Object.values(l).map((e=>e.shipping_rates)).filter(Boolean).flat()),[l]),m=(0,h.useMemo)((()=>u.length>1||s),[u.length,s]),_=(0,h.useMemo)((()=>u.length>1||t),[u.length,t]);return u.map((({package_id:e,...s})=>(0,p.jsx)(a,{packageId:e,packageData:s,collapsible:r,collapse:m,showItems:_,noResultsMessage:n,renderOption:i,highlightChecked:"woocommerce/checkout"===c},e)))};(0,s.registerPlugin)("woocommerce-subscriptions",{render:()=>(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(t.ExperimentalOrderShippingPackages,{children:(0,p.jsx)(x,{})}),(0,p.jsx)(t.ExperimentalOrderMeta,{children:(0,p.jsx)(w,{})})]}),scope:"woocommerce-checkout"}),(0,t.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:(e,{subscriptions:r})=>r?.length>0?(0,n.__)("Total due today","woocommerce-subscriptions"):e,subtotalPriceFormat:(e,{subscriptions:r})=>{if(r?.billing_period&&r?.billing_interval){const{billing_interval:s,subscription_length:t}=r;return a({subscriptionLength:t,billingInterval:s})?l(r,1===t?
|
||||
(0,t.__)("via %s","woocommerce-subscriptions"),l)})},L=({nextPaymentDate:e,subscriptionLength:s,billingPeriod:i,billingInterval:n})=>{const r=function({subscriptionLength:e,billingPeriod:s}){const i=l(e);return(0,t.sprintf)("For %1$d %2$s",e,i[s],"woocommerce-subscriptions")}({subscriptionLength:s,billingPeriod:i}),o=u({subscriptionLength:s,billingInterval:n})?(0,t.sprintf)(/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */
|
||||
(0,t.__)("Due: %1$s","woocommerce-subscriptions"),e):(0,t.sprintf)(/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */
|
||||
(0,t.__)("Starting: %1$s","woocommerce-subscriptions"),e);return(0,x.jsxs)("span",{children:[!!e&&o," ",!!s&&s>=n&&(0,x.jsx)("span",{className:"wcs-recurring-totals__subscription-length",children:r})]})},P=({currency:e,billingInterval:s,billingPeriod:i,nextPaymentDate:r,subscriptionLength:o,totals:c,isLoading:a})=>{const l=u({billingInterval:s,subscriptionLength:o})?(0,t.__)("Total","woocommerce-subscriptions"):function({billingInterval:e,billingPeriod:s}){switch(e){case 1:if("day"===s)return(0,t.__)("Daily recurring total","woocommerce-subscriptions");if("week"===s)return(0,t.__)("Weekly recurring total","woocommerce-subscriptions");if("month"===s)return(0,t.__)("Monthly recurring total","woocommerce-subscriptions");if("year"===s)return(0,t.__)("Yearly recurring total","woocommerce-subscriptions");break;case 2:return(0,t.sprintf)(/* translators: %1$s is week, month, year */ /* translators: %1$s is week, month, year */
|
||||
(0,t.__)("Recurring total every 2nd %1$s","woocommerce-subscriptions"),s);case 3:return(0,t.sprintf)(/* Translators: %1$s is week, month, year */ /* Translators: %1$s is week, month, year */
|
||||
(0,t.__)("Recurring total every 3rd %1$s","woocommerce-subscriptions"),s);default:return(0,t.sprintf)(/* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */ /* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */
|
||||
(0,t.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),e,s)}}({billingInterval:s,billingPeriod:i});return(0,x.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:e,label:l,value:c,showSkeleton:a,description:(0,x.jsx)(L,{nextPaymentDate:r,subscriptionLength:o,billingInterval:s,billingPeriod:i})})},O=({subscription:e,needsShipping:s,calculatedShipping:i,shippingAddress:o})=>{const{isLoading:l}=(()=>{const{cartIsLoading:e,isLoadingRates:s,hasPendingItemsOperations:i,isApplyingCoupon:n,isRemovingCoupon:t}=(0,c.useSelect)((e=>{const s=e(a.cartStore);return{cartIsLoading:!s.hasFinishedResolution("getCartData",[]),isLoadingRates:s.isAddressFieldsForShippingRatesUpdating(),hasPendingItemsOperations:s.hasPendingItemsOperations(),isApplyingCoupon:s.isApplyingCoupon(),isRemovingCoupon:s.isRemovingCoupon()}}),[]),r=(0,c.useSelect)((e=>e(a.checkoutStore).isCalculating()),[]);return{isLoading:e||s||n||t||r||i}})(),{totals:p,billing_interval:u,billing_period:d,next_payment_date:g,subscription_length:m,shipping_rates:_}=e;if(!g)return null;const b=(0,r.getCurrencyFromPriceResponse)(p);return(0,x.jsxs)("div",{className:"wcs-recurring-totals-panel",children:[(0,x.jsx)(P,{billingInterval:u,billingPeriod:d,nextPaymentDate:g,subscriptionLength:m,totals:parseInt(p.total_price,10),currency:b,isLoading:l}),(0,x.jsxs)(n.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:(0,t.__)("Details","woocommerce-subscriptions"),children:[(0,x.jsxs)(n.TotalsWrapper,{children:[(0,x.jsx)(n.Subtotal,{currency:b,values:p,showSkeleton:l}),(0,x.jsx)(S,{currency:b,values:p,isLoading:l})]}),(0,x.jsx)(n.TotalsWrapper,{className:"wc-block-components-totals-shipping",children:(0,x.jsx)(j,{currency:b,needsShipping:s,calculatedShipping:i,values:p,shippingAddress:o,shippingRatePackages:_,isLoading:l})}),!k&&(0,x.jsx)(n.TotalsWrapper,{children:(0,x.jsx)(n.TotalsTaxes,{currency:b,values:p})}),(0,x.jsx)(n.TotalsWrapper,{children:(0,x.jsx)(n.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:b,label:(0,t.__)("Total","woocommerce-subscriptions"),value:parseInt(p.total_price,10),showSkeleton:l})})]})]})},R=({extensions:e,cart:s})=>{const{subscriptions:i}=e,{cartNeedsShipping:n,cartHasCalculatedShipping:t,shippingAddress:r}=s;return i&&0!==i.length?i.map((({key:e,...s})=>(0,x.jsx)(O,{subscription:s,needsShipping:n,calculatedShipping:t,shippingAddress:r},e))):null},C=window.wp.element,$=({extensions:e,collapsible:s,collapse:i,showItems:n,noResultsMessage:t,renderOption:r,components:o,context:c})=>{const{subscriptions:a=[]}=e,{ShippingRatesControlPackage:l}=o,p=(0,C.useMemo)((()=>Object.values(a).map((e=>e.shipping_rates)).filter(Boolean).flat()),[a]),u=(0,C.useMemo)((()=>p.length>1||i),[p.length,i]),d=(0,C.useMemo)((()=>p.length>1||n),[p.length,n]);return p.filter((e=>!e.match_initial_rates&&e.needs_shipping)).map((({package_id:e,...i})=>(0,x.jsx)(l,{packageId:e,packageData:i,collapsible:s,collapse:u,showItems:d,noResultsMessage:t,renderOption:r,highlightChecked:"woocommerce/checkout"===c},e)))};(0,i.registerPlugin)("woocommerce-subscriptions",{render:()=>(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(n.ExperimentalOrderShippingPackages,{children:(0,x.jsx)($,{})}),(0,x.jsx)(n.ExperimentalOrderMeta,{children:(0,x.jsx)(R,{})})]}),scope:"woocommerce-checkout"}),(0,n.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:(e,{subscriptions:s})=>s?.length>0?(0,t.__)("Total due today","woocommerce-subscriptions"):e,subtotalPriceFormat:(e,{subscriptions:s})=>{if(s?.billing_period&&s?.billing_interval){const{billing_interval:i,subscription_length:n}=s;return u({subscriptionLength:n,billingInterval:i})?p(s,1===n?
|
||||
// translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month.
|
||||
// translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month.
|
||||
(0,n.__)("for 1","woocommerce-subscriptions"):
|
||||
(0,t.__)("for 1","woocommerce-subscriptions"):
|
||||
// translators: the word used to describe billing frequency, e.g. "for" 6 days or "for" 2 weeks.
|
||||
// translators: the word used to describe billing frequency, e.g. "for" 6 days or "for" 2 weeks.
|
||||
(0,n.__)("for","woocommerce-subscriptions"),e):l(r,
|
||||
(0,t.__)("for","woocommerce-subscriptions"),e):p(s,
|
||||
// translators: the word used to describe billing frequency, e.g. "every" 6 days or "every" 2 weeks.
|
||||
// translators: the word used to describe billing frequency, e.g. "every" 6 days or "every" 2 weeks.
|
||||
(0,n.__)("every","woocommerce-subscriptions"),e)}return e},saleBadgePriceFormat:(e,{subscriptions:r})=>r?.billing_period&&r?.billing_interval?l(r,"/",e):e,itemName:(e,{subscriptions:r})=>r?.is_resubscribe?(0,n.sprintf)(
|
||||
(0,t.__)("every","woocommerce-subscriptions"),e)}return e},saleBadgePriceFormat:(e,{subscriptions:s})=>s?.billing_period&&s?.billing_interval?p(s,"/",e):e,itemName:(e,{subscriptions:s})=>s?.is_resubscribe?(0,t.sprintf)(
|
||||
// translators: %s Product name.
|
||||
// translators: %s Product name.
|
||||
(0,n.__)("%s (resubscription)","woocommerce-subscriptions"),e):r?.switch_type?(0,n.sprintf)(
|
||||
(0,t.__)("%s (resubscription)","woocommerce-subscriptions"),e):s?.switch_type?(0,t.sprintf)(
|
||||
// translators: %1$s Product name, %2$s Switch type (upgraded, downgraded, or crossgraded).
|
||||
// translators: %1$s Product name, %2$s Switch type (upgraded, downgraded, or crossgraded).
|
||||
(0,n.__)("%1$s (%2$s)","woocommerce-subscriptions"),e,function(e){switch(e){case"upgraded":return(0,n.__)("Upgrade","woocommerce-subscriptions");case"downgraded":return(0,n.__)("Downgrade","woocommerce-subscriptions");case"crossgraded":return(0,n.__)("Crossgrade","woocommerce-subscriptions");default:return""}}(r.switch_type)):e,cartItemPrice:(e,{subscriptions:r},{context:s})=>r?.sign_up_fees?"cart"===s?(0,n.sprintf)(/* translators: %s is the subscription price to pay immediately (ie: $10). */ /* translators: %s is the subscription price to pay immediately (ie: $10). */
|
||||
(0,n.__)("Due today %s","woocommerce-subscriptions"),e):(0,n.sprintf)(/* translators: %s is the subscription price to pay immediately (ie: $10). */ /* translators: %s is the subscription price to pay immediately (ie: $10). */
|
||||
(0,n.__)("%s due today","woocommerce-subscriptions"),e):e,placeOrderButtonLabel:e=>{const r=(0,o.getSetting)("subscriptions_data");return r?.place_order_override?r?.place_order_override:e}})})();
|
||||
(0,t.__)("%1$s (%2$s)","woocommerce-subscriptions"),e,function(e){switch(e){case"upgraded":return(0,t.__)("Upgrade","woocommerce-subscriptions");case"downgraded":return(0,t.__)("Downgrade","woocommerce-subscriptions");case"crossgraded":return(0,t.__)("Crossgrade","woocommerce-subscriptions");default:return""}}(s.switch_type)):e,cartItemPrice:(e,{subscriptions:s},{context:i})=>s?.sign_up_fees?"cart"===i?(0,t.sprintf)(/* translators: %s is the subscription price to pay immediately (ie: $10). */ /* translators: %s is the subscription price to pay immediately (ie: $10). */
|
||||
(0,t.__)("Due today %s","woocommerce-subscriptions"),e):(0,t.sprintf)(/* translators: %s is the subscription price to pay immediately (ie: $10). */ /* translators: %s is the subscription price to pay immediately (ie: $10). */
|
||||
(0,t.__)("%s due today","woocommerce-subscriptions"),e):e,placeOrderButtonLabel:e=>{const s=(0,o.getSetting)("subscriptions_data");return s?.place_order_override?s?.place_order_override:e}})})();
|
||||
|
|
@ -1,7 +1,26 @@
|
|||
*** WooCommerce Subscriptions Changelog ***
|
||||
|
||||
2025-09-16 - version 7.9.0
|
||||
2025-10-15 - version 8.0.0
|
||||
* Add: Blocks Checkout now displays a single shipping method selection for both initial and recurring carts, similar to Classic Checkout. This can be disabled using the `wcs_cart_totals_shipping_html_price_only` filter.
|
||||
* Update: Exclude orders with a "processing" status from the "subscription_orders" telemetry data.
|
||||
* Fix: Reactivating limited subscriptions from product page is now supported.
|
||||
* Fix: Gifting email previews.
|
||||
* Fix: Shipping label on blocks checkout no more shows up as "Free" when there's no shipping method available.
|
||||
* Dev: Opt-in tracking data. Data sent to WooCommerce:
|
||||
* WooCommerce Subscriptions setting values
|
||||
* Order totals of subscription-related orders by order type and payment gateway, aggregated by month
|
||||
* Number of subscription-related orders by order type and payment gateway, aggregated by month
|
||||
* Number of products in parent subscription orders, aggregated by month
|
||||
* Number of non-zero value parent subscription orders, aggregated by month
|
||||
* Number of subscription products by billing interval
|
||||
* Number of giftable subscription products
|
||||
* Number of subscriptions by payment method, billing period, and renewal type
|
||||
* Number of gifted subscriptions
|
||||
* Number of subscribers
|
||||
* Purchase event for subscription products
|
||||
* To disable this tracking, opt-out of WooCommerce tracking, see https://woocommerce.com/usage-tracking/
|
||||
|
||||
2025-09-16 - version 7.9.0
|
||||
* Add: REST API endpoint to retrieve subscriptions associated with a specific order ID.
|
||||
* Fix: Keep subscription with successful renewals active when parent order fails.
|
||||
* Fix: Error when renewing subscriptions with downloadable gifts.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce_Subscriptions\Internal\Telemetry\Events as WC_Tracks_Events;
|
||||
|
||||
/**
|
||||
* @method static WC_Subscriptions_Plugin instance()
|
||||
*/
|
||||
|
|
@ -33,6 +35,9 @@ class WC_Subscriptions_Plugin extends WC_Subscriptions_Core_Plugin {
|
|||
WCS_Subscriber_Role_Manager::init();
|
||||
WCS_Upgrade_Notice_Manager::init();
|
||||
|
||||
$tracks_events = new WC_Tracks_Events();
|
||||
$tracks_events->setup();
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
new WC_Subscriptions_CLI();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,9 +138,7 @@ class WCS_Webhooks {
|
|||
throw new \Exception( 'The Legacy REST API plugin is not installed on this site. More information: https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/ ' );
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
WC()->api->WC_API_Subscriptions->register_routes( array() );
|
||||
// @phpstan-ignore-next-line
|
||||
$payload = WC()->api->WC_API_Subscriptions->get_subscription( $resource_id );
|
||||
break;
|
||||
case 'wp_api_v1':
|
||||
|
|
|
|||
|
|
@ -1868,7 +1868,6 @@ class WCS_Admin_Post_Types {
|
|||
* @return string[] $pieces Updated associative array of clauses for the query.
|
||||
*/
|
||||
private function orders_table_clauses_low_performance( $pieces ) {
|
||||
// @phpstan-ignore-next-line
|
||||
$order_datastore = wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore::class );
|
||||
$order_table = $order_datastore::get_orders_table_name();
|
||||
$meta_table = $order_datastore::get_meta_table_name();
|
||||
|
|
@ -1899,7 +1898,6 @@ class WCS_Admin_Post_Types {
|
|||
private function orders_table_clauses_high_performance( $pieces ) {
|
||||
global $wpdb;
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$order_datastore = wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore::class );
|
||||
$order_table = $order_datastore::get_orders_table_name();
|
||||
$meta_table = $order_datastore::get_meta_table_name();
|
||||
|
|
|
|||
|
|
@ -1088,21 +1088,11 @@ class WC_Subscriptions_Cart {
|
|||
self::set_cached_recurring_cart( $recurring_cart );
|
||||
|
||||
foreach ( $recurring_cart->get_shipping_packages() as $recurring_cart_package_key => $recurring_cart_package ) {
|
||||
$package_index = isset( $recurring_cart_package['package_index'] ) ? $recurring_cart_package['package_index'] : 0;
|
||||
$package = WC()->shipping->calculate_shipping_for_package( $recurring_cart_package );
|
||||
|
||||
$package_rates_match = false;
|
||||
if ( isset( $standard_packages[ $package_index ] ) ) {
|
||||
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
||||
$package_rates_match = apply_filters( 'wcs_recurring_shipping_package_rates_match_standard_rates', $package['rates'] == $standard_packages[ $package_index ]['rates'], $package['rates'], $standard_packages[ $package_index ]['rates'], $recurring_cart_key );
|
||||
if ( self::package_rates_match_initial_rates( $standard_packages, $recurring_cart_package, $recurring_cart_key, $recurring_cart ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $package_rates_match ) {
|
||||
// The recurring package rates match the initial package rates, there won't be a selected shipping method for this recurring cart package move on to the next package.
|
||||
if ( apply_filters( 'wcs_cart_totals_shipping_html_price_only', true, $package, $recurring_cart ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$package = WC()->shipping->calculate_shipping_for_package( $recurring_cart_package );
|
||||
|
||||
// If the chosen shipping method is not available for this recurring cart package, display an error and unset the selected method.
|
||||
if ( ! isset( $package['rates'][ $shipping_methods[ $recurring_cart_package_key ] ] ) ) {
|
||||
|
|
@ -1127,6 +1117,47 @@ class WC_Subscriptions_Cart {
|
|||
self::set_cached_recurring_cart( $cached_recurring_cart );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the recurring package rates match the initial package rates.
|
||||
*
|
||||
* @param array $standard_packages The standard packages.
|
||||
* @param array $recurring_cart_package The recurring cart package.
|
||||
* @param string $recurring_cart_key The recurring cart key.
|
||||
* @param object $recurring_cart The recurring cart.
|
||||
* @return bool Whether the recurring package rates match the initial package rates.
|
||||
*/
|
||||
public static function package_rates_match_initial_rates( $standard_packages, $recurring_cart_package, $recurring_cart_key, $recurring_cart ) {
|
||||
$package_index = isset( $recurring_cart_package['package_index'] ) ? $recurring_cart_package['package_index'] : 0;
|
||||
$package = WC()->shipping->calculate_shipping_for_package( $recurring_cart_package );
|
||||
|
||||
$package_rates_match = false;
|
||||
if ( isset( $standard_packages[ $package_index ] ) ) {
|
||||
// Ignore item names during the comparison.
|
||||
$package_rates = array_map(
|
||||
[ __CLASS__, 'remove_item_names_from_rate' ],
|
||||
$package['rates']
|
||||
);
|
||||
$initial_rates = array_map(
|
||||
[ __CLASS__, 'remove_item_names_from_rate' ],
|
||||
$standard_packages[ $package_index ]['rates']
|
||||
);
|
||||
|
||||
// phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- Order of array values is not important.
|
||||
$package_rates_match = apply_filters( 'wcs_recurring_shipping_package_rates_match_standard_rates', $package_rates == $initial_rates, $package['rates'], $standard_packages[ $package_index ]['rates'], $recurring_cart_key );
|
||||
}
|
||||
|
||||
if ( $package_rates_match ) {
|
||||
/**
|
||||
* The recurring package rates match the initial package rates, there won't be a selected shipping method for this recurring cart package move on to the next package.
|
||||
*
|
||||
* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingSinceComment
|
||||
*/
|
||||
return apply_filters( 'wcs_cart_totals_shipping_html_price_only', true, $package, $recurring_cart );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the cart to see if it contains a specific product.
|
||||
*
|
||||
|
|
@ -2539,4 +2570,17 @@ class WC_Subscriptions_Cart {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the item names from the shipping rate
|
||||
* to check if the rates match.
|
||||
*
|
||||
* @param WC_Shipping_Rate $rate The rate.
|
||||
* @return WC_Shipping_Rate The rate.
|
||||
*/
|
||||
private static function remove_item_names_from_rate( $rate ) {
|
||||
$rate->add_meta_data( 'Items', null );
|
||||
|
||||
return $rate;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ class WC_Subscriptions_Extend_Store_Endpoint {
|
|||
// @phpstan-ignore class.notFound
|
||||
self::$currency_formatter = function_exists( 'woocommerce_store_api_get_formatter' ) ? woocommerce_store_api_get_formatter( 'currency' ) : Package::container()->get( ExtendRestApi::class )->get_formatter( 'currency' );
|
||||
self::extend_store();
|
||||
|
||||
add_action( 'woocommerce_store_api_cart_select_shipping_rate', [ __CLASS__, 'initial_shipment_select_shipping_rate' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -331,6 +333,7 @@ class WC_Subscriptions_Extend_Store_Endpoint {
|
|||
}
|
||||
|
||||
$future_subscriptions = array();
|
||||
$standard_packages = WC()->shipping->get_packages();
|
||||
|
||||
if ( ! empty( wc()->cart->recurring_carts ) ) {
|
||||
foreach ( wc()->cart->recurring_carts as $cart_key => $cart ) {
|
||||
|
|
@ -359,7 +362,18 @@ class WC_Subscriptions_Extend_Store_Endpoint {
|
|||
'tax_lines' => self::get_tax_lines( $cart ),
|
||||
)
|
||||
),
|
||||
'shipping_rates' => array_values( array_map( array( self::$schema->get( 'cart-shipping-rate' ), 'get_item_response' ), $shipping_packages ) ),
|
||||
'shipping_rates' => array_values(
|
||||
array_map(
|
||||
function ( $package ) use ( $cart, $cart_key, $standard_packages ) {
|
||||
$shipping_package = self::$schema->get( 'cart-shipping-rate' )->get_item_response( $package );
|
||||
$shipping_package['match_initial_rates'] = WC_Subscriptions_Cart::package_rates_match_initial_rates( $standard_packages, $package, $cart_key, $cart );
|
||||
$shipping_package['needs_shipping'] = WC_Subscriptions_Cart::cart_contains_subscriptions_needing_shipping( $cart );
|
||||
|
||||
return $shipping_package;
|
||||
},
|
||||
$shipping_packages
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -367,6 +381,42 @@ class WC_Subscriptions_Extend_Store_Endpoint {
|
|||
return $future_subscriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the initial shipment shipping rate.
|
||||
*
|
||||
* @param string $package_id Package ID.
|
||||
* @param string $rate_id Rate ID.
|
||||
*/
|
||||
public static function initial_shipment_select_shipping_rate( $package_id, $rate_id ) {
|
||||
WC()->cart->calculate_totals();
|
||||
|
||||
$standard_packages = WC()->shipping->get_packages();
|
||||
|
||||
if ( ! is_numeric( $package_id ) || key( $standard_packages ) !== (int) $package_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( WC()->cart->recurring_carts as $recurring_cart_key => $recurring_cart ) {
|
||||
if ( false === $recurring_cart->needs_shipping() || 0 === $recurring_cart->next_payment_date ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
WC_Subscriptions_Cart::set_calculation_type( 'recurring_total' );
|
||||
WC_Subscriptions_Cart::set_recurring_cart_key( $recurring_cart_key );
|
||||
WC_Subscriptions_Cart::set_cached_recurring_cart( $recurring_cart );
|
||||
|
||||
foreach ( $recurring_cart->get_shipping_packages() as $recurring_cart_package_key => $recurring_cart_package ) {
|
||||
if ( WC_Subscriptions_Cart::package_rates_match_initial_rates( $standard_packages, $recurring_cart_package, $recurring_cart_key, $recurring_cart ) ) {
|
||||
$session_data = wc()->session->get( 'chosen_shipping_methods' ) ? wc()->session->get( 'chosen_shipping_methods' ) : [];
|
||||
|
||||
$session_data[ $recurring_cart_package_key ] = $rate_id;
|
||||
|
||||
wc()->session->set( 'chosen_shipping_methods', $session_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format sign-up fees.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2478,7 +2478,6 @@ f *
|
|||
|
||||
if ( isset( $order->$meta_key ) ) { // WC 2.1+ magic __isset() & __get() methods
|
||||
$meta_value = $order->$meta_key;
|
||||
// @phpstan-ignore-next-line
|
||||
} elseif ( is_array( $order->order_custom_fields ) && isset( $order->order_custom_fields[ '_' . $meta_key ][0] ) && $order->order_custom_fields[ '_' . $meta_key ][0] ) { // < WC 2.1+
|
||||
$meta_value = maybe_unserialize( $order->order_custom_fields[ '_' . $meta_key ][0] );
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,12 +5,17 @@
|
|||
* @class WC_Subscriptions_Tracker
|
||||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.4
|
||||
* @package WooCommerce Subscriptions/Classes
|
||||
* @category Class
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
use Automattic\WooCommerce_Subscriptions\Internal\Telemetry\Collector;
|
||||
|
||||
class WC_Subscriptions_Tracker {
|
||||
/**
|
||||
* Handles the collection of additional pieces of data.
|
||||
*/
|
||||
private static Collector $telemetry_collector;
|
||||
|
||||
/**
|
||||
* Initialize the Tracker.
|
||||
|
|
@ -18,6 +23,8 @@ class WC_Subscriptions_Tracker {
|
|||
public static function init() {
|
||||
// Only add data if Tracker enabled
|
||||
if ( 'yes' === get_option( 'woocommerce_allow_tracking', 'no' ) ) {
|
||||
self::$telemetry_collector = new Collector();
|
||||
self::$telemetry_collector->setup();
|
||||
add_filter( 'woocommerce_tracker_data', [ __CLASS__, 'add_subscriptions_tracking_data' ], 10, 1 );
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +39,11 @@ class WC_Subscriptions_Tracker {
|
|||
$data['extensions']['wc_subscriptions']['settings'] = self::get_subscriptions_options();
|
||||
$data['extensions']['wc_subscriptions']['subscriptions'] = self::get_subscriptions();
|
||||
$data['extensions']['wc_subscriptions']['subscription_orders'] = self::get_subscription_orders();
|
||||
|
||||
// Insert any additional telemetry that we have been collecting.
|
||||
$additional_telemetry = self::$telemetry_collector->get_telemetry_data();
|
||||
$data['extensions']['wc_subscriptions'] = array_merge_recursive( $data['extensions']['wc_subscriptions'], $additional_telemetry );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
|
@ -41,47 +53,86 @@ class WC_Subscriptions_Tracker {
|
|||
* @return array Subscriptions options data.
|
||||
*/
|
||||
private static function get_subscriptions_options() {
|
||||
$customer_notifications_offset = get_option( WC_Subscriptions_Admin::$option_prefix . WC_Subscriptions_Email_Notifications::$offset_setting_string, [] );
|
||||
|
||||
return [
|
||||
// Staging and live site
|
||||
'wc_subscriptions_staging' => WCS_Staging::is_duplicate_site() ? 'staging' : 'live',
|
||||
'wc_subscriptions_live_url' => esc_url( WCS_Staging::get_site_url_from_source( 'subscriptions_install' ) ),
|
||||
|
||||
// Button text, roles
|
||||
// Button text
|
||||
// Add to Cart Button Text
|
||||
'add_to_cart_button_text' => get_option( WC_Subscriptions_Admin::$option_prefix . '_add_to_cart_button_text' ),
|
||||
// Place Order Button Text
|
||||
'order_button_text' => get_option( WC_Subscriptions_Admin::$option_prefix . '_order_button_text' ),
|
||||
|
||||
// Roles
|
||||
// Subscriber Default Role
|
||||
'subscriber_role' => get_option( WC_Subscriptions_Admin::$option_prefix . '_subscriber_role' ),
|
||||
// Inactive Subscriber Role
|
||||
'cancelled_role' => get_option( WC_Subscriptions_Admin::$option_prefix . '_cancelled_role' ),
|
||||
|
||||
// Renewals
|
||||
// Accept Manual Renewals
|
||||
'accept_manual_renewals' => get_option( WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals' ),
|
||||
// Turn off Automatic Payments
|
||||
'turn_off_automatic_payments' => 'no' === get_option( WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals' ) ? 'none' : get_option( WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'none' ),
|
||||
// Auto Renewal Toggle
|
||||
'enable_auto_renewal_toggle' => get_option( WC_Subscriptions_Admin::$option_prefix . '_enable_auto_renewal_toggle' ),
|
||||
|
||||
// Early renewal
|
||||
// Accept Early Renewal Payments
|
||||
'enable_early_renewal' => get_option( WC_Subscriptions_Admin::$option_prefix . '_enable_early_renewal' ),
|
||||
// Accept Early Renewal Payments via a Modal
|
||||
'enable_early_renewal_via_modal' => 'no' === get_option( WC_Subscriptions_Admin::$option_prefix . '_enable_early_renewal' ) ? 'none' : get_option( WC_Subscriptions_Admin::$option_prefix . '_enable_early_renewal_via_modal', 'none' ),
|
||||
|
||||
// Switching
|
||||
// Between Subscription Variations and Between Grouped Subscriptions are condensed into this setting.
|
||||
'allow_switching' => get_option( WC_Subscriptions_Admin::$option_prefix . '_allow_switching' ),
|
||||
// Prorate Recurring Payment
|
||||
'apportion_recurring_price' => get_option( WC_Subscriptions_Admin::$option_prefix . '_apportion_recurring_price', 'none' ),
|
||||
// Prorate Sign up Fee
|
||||
'apportion_sign_up_fee' => get_option( WC_Subscriptions_Admin::$option_prefix . '_apportion_sign_up_fee', 'none' ),
|
||||
// Prorate Subscription Length
|
||||
'apportion_length' => get_option( WC_Subscriptions_Admin::$option_prefix . '_apportion_length', 'none' ),
|
||||
// Switch Button Text
|
||||
'switch_button_text' => get_option( WC_Subscriptions_Admin::$option_prefix . '_switch_button_text', 'none' ),
|
||||
|
||||
// Gifting
|
||||
// Enable gifting
|
||||
'gifting_enable_gifting' => get_option( WC_Subscriptions_Admin::$option_prefix . '_gifting_enable_gifting' ),
|
||||
'gifting_default_option' => get_option( WC_Subscriptions_Admin::$option_prefix . '_gifting_default_option' ),
|
||||
// Gifting Checkbox Text
|
||||
'gifting_gifting_checkbox_text' => get_option( WC_Subscriptions_Admin::$option_prefix . '_gifting_gifting_checkbox_text' ),
|
||||
// Downloadable Products
|
||||
'gifting_downloadable_products' => get_option( WC_Subscriptions_Admin::$option_prefix . '_gifting_downloadable_products' ),
|
||||
|
||||
// Synchronization
|
||||
// Synchronise renewals
|
||||
'sync_payments' => get_option( WC_Subscriptions_Admin::$option_prefix . '_sync_payments' ),
|
||||
// Prorate First Renewal
|
||||
'prorate_synced_payments' => $prorate_synced_payments = ( 'no' === get_option( WC_Subscriptions_Admin::$option_prefix . '_sync_payments' ) ? 'none' : get_option( WC_Subscriptions_Admin::$option_prefix . '_prorate_synced_payments', 'none' ) ),
|
||||
// Sign-up grace period
|
||||
'days_no_fee' => 'recurring' === $prorate_synced_payments ? get_option( WC_Subscriptions_Admin::$option_prefix . '_days_no_fee', 'none' ) : 'none',
|
||||
|
||||
// Miscellaneous
|
||||
// Customer Suspensions
|
||||
'max_customer_suspensions' => get_option( WC_Subscriptions_Admin::$option_prefix . '_max_customer_suspensions' ),
|
||||
// Mixed Checkout
|
||||
'multiple_purchase' => get_option( WC_Subscriptions_Admin::$option_prefix . '_multiple_purchase' ),
|
||||
// $0 Initial Checkout
|
||||
'allow_zero_initial_order_without_payment_method' => get_option( WC_Subscriptions_Admin::$option_prefix . '_zero_initial_payment_requires_payment' ),
|
||||
// Drip Downloadable Content
|
||||
'drip_downloadable_content_on_renewal' => get_option( WC_Subscriptions_Admin::$option_prefix . '_drip_downloadable_content_on_renewal' ),
|
||||
// Retry Failed Payments
|
||||
'enable_retry' => get_option( WC_Subscriptions_Admin::$option_prefix . '_enable_retry' ),
|
||||
|
||||
// Notifications
|
||||
'enable_notification_reminders' => get_option( WC_Subscriptions_Admin::$option_prefix . WC_Subscriptions_Email_Notifications::$switch_setting_string, 'no' ),
|
||||
// Enable Reminders
|
||||
'enable_notification_reminders' => get_option( WC_Subscriptions_Admin::$option_prefix . WC_Subscriptions_Email_Notifications::$switch_setting_string ),
|
||||
// Reminder Timing
|
||||
'customer_notifications_offset_number' => $customer_notifications_offset['number'] ?? 'none',
|
||||
'customer_notifications_offset_unit' => $customer_notifications_offset['unit'] ?? 'none',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -119,80 +170,21 @@ class WC_Subscriptions_Tracker {
|
|||
* @return array Subscription order counts and totals by type (initial, switch, renewal, resubscribe). Values are returned as strings.
|
||||
*/
|
||||
private static function get_subscription_orders() {
|
||||
$order_totals = [];
|
||||
$relation_types = [
|
||||
'switch',
|
||||
'renewal',
|
||||
'resubscribe',
|
||||
];
|
||||
$order_totals = array();
|
||||
|
||||
// Get the subtotal and count for each subscription type.
|
||||
foreach ( $relation_types as $relation_type ) {
|
||||
// Get orders with the given relation type.
|
||||
$relation_orders = wcs_get_orders_with_meta_query(
|
||||
[
|
||||
'type' => 'shop_order',
|
||||
'status' => [ 'wc-completed', 'wc-processing', 'wc-refunded' ],
|
||||
'limit' => -1,
|
||||
'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
[
|
||||
'key' => '_subscription_' . $relation_type,
|
||||
'compare' => 'EXISTS',
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
// Get the subtotal and count for all subscription types in one query
|
||||
$counts_and_totals = self::get_order_count_and_total_by_meta_key();
|
||||
|
||||
// Sum the totals and count the orders.
|
||||
$count = count( $relation_orders );
|
||||
$total = array_reduce(
|
||||
$relation_orders,
|
||||
function( $total, $order ) {
|
||||
return $total + $order->get_total();
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
$order_totals[ $relation_type . '_gross' ] = $total;
|
||||
$order_totals[ $relation_type . '_count' ] = $count;
|
||||
foreach ( $counts_and_totals as $type => $data ) {
|
||||
$order_totals[ $type . '_gross' ] = $data['total'];
|
||||
$order_totals[ $type . '_count' ] = $data['count'];
|
||||
}
|
||||
|
||||
// Finally, get the initial revenue and count.
|
||||
// Get the orders for all initial subscription orders (no switch, renewal or resubscribe meta key).
|
||||
$initial_subscription_orders = wcs_get_orders_with_meta_query(
|
||||
[
|
||||
'type' => 'shop_order',
|
||||
'status' => [ 'wc-completed', 'wc-processing', 'wc-refunded' ],
|
||||
'limit' => -1,
|
||||
'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
[
|
||||
'key' => '_subscription_switch',
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => '_subscription_renewal',
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
[
|
||||
'key' => '_subscription_resubscribe',
|
||||
'compare' => 'NOT EXISTS',
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
// Get initial orders (orders without switch, renewal, or resubscribe meta keys).
|
||||
$count_and_total = self::get_initial_order_count_and_total();
|
||||
|
||||
// Sum the totals and count the orders.
|
||||
$initial_order_count = count( $initial_subscription_orders );
|
||||
$initial_order_total = array_reduce(
|
||||
$initial_subscription_orders,
|
||||
function( $total, $order ) {
|
||||
return $total + $order->get_total();
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
$order_totals['initial_gross'] = $initial_order_total;
|
||||
$order_totals['initial_count'] = $initial_order_count;
|
||||
$order_totals['initial_gross'] = $count_and_total['total'];
|
||||
$order_totals['initial_count'] = $count_and_total['count'];
|
||||
|
||||
// Ensure all values are strings.
|
||||
$order_totals = array_map( 'strval', $order_totals );
|
||||
|
|
@ -200,6 +192,149 @@ class WC_Subscriptions_Tracker {
|
|||
return $order_totals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets order count and total for subscription-related orders.
|
||||
*
|
||||
* @return array Array with counts and totals for switch, renewal, and resubscribe orders.
|
||||
*/
|
||||
private static function get_order_count_and_total_by_meta_key() {
|
||||
global $wpdb;
|
||||
|
||||
$order_statuses = array( 'wc-completed', 'wc-refunded' );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
|
||||
if ( wcs_is_custom_order_tables_usage_enabled() ) {
|
||||
// HPOS: Use wc_orders and wc_orders_meta tables.
|
||||
$orders_table = $wpdb->prefix . 'wc_orders';
|
||||
$meta_table = $wpdb->prefix . 'wc_orders_meta';
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT
|
||||
order_relation.meta_key as 'type',
|
||||
SUM( orders.total_amount ) AS 'total',
|
||||
COUNT( orders.id ) as 'count'
|
||||
FROM {$orders_table} AS orders
|
||||
RIGHT JOIN {$meta_table} AS order_relation ON order_relation.order_id = orders.id
|
||||
WHERE order_relation.meta_key IN ( '_subscription_switch', '_subscription_renewal', '_subscription_resubscribe' )
|
||||
AND orders.status in (%s, %s)
|
||||
AND orders.type = 'shop_order'
|
||||
GROUP BY order_relation.meta_key",
|
||||
$order_statuses
|
||||
);
|
||||
} else {
|
||||
// CPT: Use posts and postmeta tables.
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT
|
||||
order_relation.meta_key as 'type',
|
||||
SUM( order_total.meta_value ) AS 'total',
|
||||
COUNT( orders.ID ) as 'count'
|
||||
FROM {$wpdb->prefix}posts AS orders
|
||||
RIGHT JOIN {$wpdb->prefix}postmeta AS order_relation ON order_relation.post_id = orders.ID
|
||||
RIGHT JOIN {$wpdb->prefix}postmeta AS order_total ON order_total.post_id = orders.ID
|
||||
WHERE order_relation.meta_key IN ( '_subscription_switch', '_subscription_renewal', '_subscription_resubscribe' )
|
||||
AND orders.post_status in (%s, %s)
|
||||
AND order_total.meta_key = '_order_total'
|
||||
GROUP BY order_relation.meta_key",
|
||||
$order_statuses
|
||||
);
|
||||
}
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
|
||||
|
||||
$results = $wpdb->get_results( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
$totals = array(
|
||||
'switch' => array(
|
||||
'count' => 0,
|
||||
'total' => 0.0,
|
||||
),
|
||||
'renewal' => array(
|
||||
'count' => 0,
|
||||
'total' => 0.0,
|
||||
),
|
||||
'resubscribe' => array(
|
||||
'count' => 0,
|
||||
'total' => 0.0,
|
||||
),
|
||||
);
|
||||
|
||||
if ( $results ) {
|
||||
foreach ( $results as $result ) {
|
||||
$type = str_replace( '_subscription_', '', $result['type'] );
|
||||
if ( isset( $totals[ $type ] ) ) {
|
||||
$totals[ $type ] = array(
|
||||
'count' => (int) $result['count'],
|
||||
'total' => (float) $result['total'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log if any type has no data
|
||||
foreach ( $totals as $type => $data ) {
|
||||
if ( 0 === $data['count'] && 0.0 === $data['total'] ) {
|
||||
wc_get_logger()->warning( "WC_Subscriptions_Tracker::get_order_count_and_total_by_meta_key() returned 0 count and total for {$type} orders" );
|
||||
}
|
||||
}
|
||||
|
||||
return $totals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets count and total for initial orders (orders without subscription relation meta keys).
|
||||
*
|
||||
* @return array Array with 'count' and 'total' keys.
|
||||
*/
|
||||
private static function get_initial_order_count_and_total() {
|
||||
global $wpdb;
|
||||
|
||||
$order_statuses = array( 'wc-completed', 'wc-refunded' );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
|
||||
if ( wcs_is_custom_order_tables_usage_enabled() ) {
|
||||
// HPOS: Use wc_orders table
|
||||
$orders_table = $wpdb->prefix . 'wc_orders';
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT
|
||||
SUM( orders.total_amount ) AS 'total', COUNT( DISTINCT orders.id ) as 'count'
|
||||
FROM {$orders_table} AS orders
|
||||
RIGHT JOIN {$orders_table} AS subscriptions ON subscriptions.parent_order_id = orders.id
|
||||
WHERE orders.status in ( %s, %s )
|
||||
AND subscriptions.type = 'shop_subscription'
|
||||
AND orders.type = 'shop_order'",
|
||||
$order_statuses
|
||||
);
|
||||
} else {
|
||||
// CPT: Use posts and postmeta tables.
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT
|
||||
SUM( order_total.meta_value ) AS 'total', COUNT( * ) as 'count'
|
||||
FROM {$wpdb->posts} AS orders
|
||||
RIGHT JOIN {$wpdb->posts} AS subscriptions ON subscriptions.post_parent = orders.ID
|
||||
RIGHT JOIN {$wpdb->postmeta} AS order_total ON order_total.post_id = orders.ID
|
||||
WHERE orders.post_status in ( %s, %s )
|
||||
AND subscriptions.post_type = 'shop_subscription'
|
||||
AND orders.post_type = 'shop_order'
|
||||
AND order_total.meta_key = '_order_total'",
|
||||
$order_statuses
|
||||
);
|
||||
}
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
|
||||
|
||||
$result = $wpdb->get_row( $query, ARRAY_A ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
$totals = array(
|
||||
'count' => (int) ( $result ? $result['count'] : 0 ),
|
||||
'total' => (float) ( $result ? $result['total'] : 0 ),
|
||||
);
|
||||
|
||||
if ( 0 === $totals['count'] && 0.0 === $totals['total'] ) {
|
||||
wc_get_logger()->warning( 'WC_Subscriptions_Tracker::get_initial_order_count_and_total() returned 0 count and total' );
|
||||
}
|
||||
|
||||
return $totals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets first and last subscription created dates.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ class WCS_Failed_Scheduled_Action_Manager {
|
|||
// Log any exceptions caught by the exception listener in action logs.
|
||||
if ( ! empty( $context['exceptions'] ) ) {
|
||||
foreach ( $context['exceptions'] as $exception_message ) {
|
||||
// @phpstan-ignore-next-line
|
||||
ActionScheduler_Logger::instance()->log( $action_id, $exception_message );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,11 +92,9 @@ class WCS_Object_Data_Cache_Manager extends WCS_Post_Meta_Cache_Manager {
|
|||
}
|
||||
|
||||
$force_all_fields = 'all_fields' === $generate_type;
|
||||
// @phpstan-ignore-next-line
|
||||
$changes = $subscription->get_changes();
|
||||
$base_data = $subscription->get_base_data();
|
||||
// @phpstan-ignore-next-line
|
||||
$meta_data = $subscription->get_meta_data();
|
||||
$changes = $subscription->get_changes();
|
||||
$base_data = $subscription->get_base_data();
|
||||
$meta_data = $subscription->get_meta_data();
|
||||
|
||||
// Deleted meta won't be included in the changes, so we need to fetch the previous value via the raw meta data.
|
||||
$data_store = $subscription->get_data_store();
|
||||
|
|
@ -144,7 +142,6 @@ class WCS_Object_Data_Cache_Manager extends WCS_Post_Meta_Cache_Manager {
|
|||
} elseif ( $meta->get_changes() ) {
|
||||
// If the value is being updated.
|
||||
$this->object_changes[ $subscription->get_id() ][ $data_key ] = [
|
||||
// @phpstan-ignore-next-line
|
||||
'new' => $meta->value,
|
||||
'previous' => isset( $previous_meta['value'] ) ? $previous_meta['value'] : null,
|
||||
'type' => 'update',
|
||||
|
|
@ -152,7 +149,6 @@ class WCS_Object_Data_Cache_Manager extends WCS_Post_Meta_Cache_Manager {
|
|||
} elseif ( $force_all_fields ) {
|
||||
// If we're forcing all fields to be recorded.
|
||||
$this->object_changes[ $subscription->get_id() ][ $data_key ] = [
|
||||
// @phpstan-ignore-next-line
|
||||
'new' => $meta->value,
|
||||
'type' => 'add',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ class WC_Subscriptions_Email_Preview {
|
|||
case 'WCS_Email_Customer_Notification_Auto_Renewal':
|
||||
$email->set_object( $this->get_dummy_subscription() );
|
||||
break;
|
||||
case 'WCSG_Email_Recipient_New_Initial_Order':
|
||||
$email->set_object( $this->get_dummy_subscription() );
|
||||
$email->subscriptions = [ $this->get_dummy_subscription() ];
|
||||
break;
|
||||
case 'WCS_Email_Customer_Payment_Retry':
|
||||
case 'WCS_Email_Payment_Retry':
|
||||
$email->retry = $this->get_dummy_retry( $email->object );
|
||||
|
|
@ -191,8 +195,7 @@ class WC_Subscriptions_Email_Preview {
|
|||
* @return bool Whether the email being previewed is a subscription email.
|
||||
*/
|
||||
private function is_subscription_email() {
|
||||
return isset( WC_Subscriptions_Email::$email_classes[ $this->email_type ] )
|
||||
|| isset( WC_Subscriptions_Email_Notifications::$email_classes[ $this->email_type ] )
|
||||
return isset( apply_filters( 'wcs_email_classes', array_merge( WC_Subscriptions_Email::$email_classes, WC_Subscriptions_Email_Notifications::$email_classes ) )[ $this->email_type ] )
|
||||
|| in_array( $this->email_type, [ 'WCS_Email_Customer_Payment_Retry', 'WCS_Email_Payment_Retry' ], true );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.1
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Cancelled_Subscription extends WC_Email {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.0.0
|
||||
* @package WooCommerce/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Completed_Renewal_Order extends WC_Email_Customer_Completed_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.0.0
|
||||
* @package WooCommerce/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Completed_Switch_Order extends WC_Email_Customer_Completed_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @class WCS_Email_Customer_Notification_Auto_Renewal
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Customer_Notification_Auto_Renewal extends WCS_Email_Customer_Notification {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @class WCS_Email_Customer_Notification_Free_Trial_Expiry
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Customer_Notification_Auto_Trial_Expiration extends WCS_Email_Customer_Notification {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @class WCS_Email_Customer_Notification_Manual_Renewal
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Customer_Notification_Manual_Renewal extends WCS_Email_Customer_Notification {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @class WCS_Email_Customer_Notification_Free_Trial_Expiry
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Customer_Notification_Manual_Trial_Expiration extends WCS_Email_Customer_Notification {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @class WCS_Email_Customer_Notification_Subscription_Expiring
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Customer_Notification_Subscription_Expiration extends WCS_Email_Customer_Notification {
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ defined( 'ABSPATH' ) || exit; // Exit if accessed directly.
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v3.0.0
|
||||
* @package WooCommerce_Subscriptions/Includes/Emails
|
||||
* @author WooCommerce.
|
||||
* @extends WC_Email_Customer_On_Hold_Order
|
||||
*/
|
||||
class WCS_Email_Customer_On_Hold_Renewal_Order extends WC_Email_Customer_On_Hold_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v1.4
|
||||
* @package WooCommerce_Subscriptions/Includes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email_Customer_Invoice
|
||||
*/
|
||||
class WCS_Email_Customer_Renewal_Invoice extends WC_Email_Customer_Invoice {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.1
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Expired_Subscription extends WC_Email {
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
*
|
||||
* @class WCS_Email_New_Renewal_Order
|
||||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v1.4
|
||||
* @extends WC_Email_New_Order
|
||||
*/
|
||||
class WCS_Email_New_Renewal_Order extends WC_Email_New_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
*
|
||||
* @class WCS_Email_New_Switch_Order
|
||||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v1.5
|
||||
* @extends WC_Email_New_Order
|
||||
*/
|
||||
class WCS_Email_New_Switch_Order extends WC_Email_New_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.1
|
||||
* @package WooCommerce_Subscriptions/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_On_Hold_Subscription extends WC_Email {
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.0.0
|
||||
* @package WooCommerce/Classes/Emails
|
||||
* @author Prospress
|
||||
* @extends WC_Email
|
||||
*/
|
||||
class WCS_Email_Processing_Renewal_Order extends WC_Email_Customer_Processing_Order {
|
||||
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ abstract class WCS_SV_API_Base {
|
|||
*
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v4.1.0
|
||||
* @param string $uri current request URI
|
||||
* @param \WCS_SV_API_Base $this class instance
|
||||
* @param \WCS_SV_API_Base $instance class instance
|
||||
*/
|
||||
return apply_filters( 'wc_' . $this->get_api_id() . '_api_request_uri', $uri, $this );
|
||||
}
|
||||
|
|
@ -335,7 +335,7 @@ abstract class WCS_SV_API_Base {
|
|||
*
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.0
|
||||
* @param array $args request arguments
|
||||
* @param \WCS_SV_API_Base $this class instance
|
||||
* @param \WCS_SV_API_Base $instance class instance
|
||||
*/
|
||||
return apply_filters( 'wc_' . $this->get_api_id() . '_http_request_args', $args, $this );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ class WCS_PayPal_Reference_Transaction_API_Request {
|
|||
* Use this to modify the PayPal request parameters prior to validation
|
||||
*
|
||||
* @param array $parameters
|
||||
* @param \WC_PayPal_Express_API_Request $this instance
|
||||
* @param \WC_PayPal_Reference_Transaction_API_Request $instance instance
|
||||
*/
|
||||
$this->parameters = apply_filters( 'wcs_paypal_request_params', $this->parameters, $this );
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ class WCS_Repair_Suspended_PayPal_Subscriptions extends WCS_Background_Upgrader
|
|||
* @param int $subscription_id The ID of a shop_subscription/WC_Subscription object.
|
||||
*/
|
||||
protected function update_item( $subscription_id ) {
|
||||
$subscription = null;
|
||||
|
||||
try {
|
||||
$subscription = wcs_get_subscription( $subscription_id );
|
||||
|
||||
|
|
|
|||
|
|
@ -884,7 +884,6 @@ class WCS_Upgrade_2_0 {
|
|||
* @param WC_Subscription $new_subscription A subscription object
|
||||
* @param WC_Order $switch_order The original order used to purchase the subscription
|
||||
* @param int $subscription_item_id The order item ID of the item added to the subscription by self::add_product()
|
||||
* @return null
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||||
*/
|
||||
private static function migrate_switch_meta( $new_subscription, $switch_order, $subscription_item_id ) {
|
||||
|
|
|
|||
|
|
@ -79,11 +79,12 @@ function wcs_cart_totals_shipping_html() {
|
|||
$chosen_recurring_method = empty( $package['rates'] ) ? '' : current( $package['rates'] )->id;
|
||||
}
|
||||
|
||||
$is_package_found = isset( $package['rates'][ $chosen_initial_method ] ) && isset( $initial_packages[ $package_index ] );
|
||||
$shipping_selection_displayed = false;
|
||||
$only_one_shipping_option = count( $package['rates'] ) === 1;
|
||||
$recurring_rates_match_initial_rates = isset( $package['rates'][ $chosen_initial_method ] ) && isset( $initial_packages[ $package_index ] ) && $package['rates'] == $initial_packages[ $package_index ]['rates']; // phpcs:ignore WordPress.PHP.StrictComparisons
|
||||
$recurring_rates_match_initial_rates = WC_Subscriptions_Cart::package_rates_match_initial_rates( $initial_packages, $package, $recurring_cart_package_key, $recurring_cart );
|
||||
|
||||
if ( $only_one_shipping_option || ( $recurring_rates_match_initial_rates && apply_filters( 'wcs_cart_totals_shipping_html_price_only', true, $package, $recurring_cart ) ) ) {
|
||||
if ( $only_one_shipping_option || ( $is_package_found && $recurring_rates_match_initial_rates ) ) {
|
||||
$shipping_method = ( 1 === count( $package['rates'] ) ) ? current( $package['rates'] ) : $package['rates'][ $chosen_initial_method ];
|
||||
// packages match, display shipping amounts only
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -500,3 +500,32 @@ function wcs_get_subscription_grouping_key( $product, $renewal_time = 0 ) {
|
|||
|
||||
return apply_filters( 'wcs_subscription_product_grouping_key', $key, $product, $renewal_time );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reactivate link for a subscription product if the user already has a
|
||||
* pending cancellation subscription.
|
||||
*
|
||||
* @param int $user_id The user ID
|
||||
* @param WC_Product $product The product
|
||||
* @return string The reactivate link
|
||||
*/
|
||||
function wcs_get_user_reactivate_link_for_product( int $user_id, WC_Product $product ): string {
|
||||
$reactivate_link = '';
|
||||
|
||||
$user_subscriptions = wcs_get_subscriptions(
|
||||
[
|
||||
'customer_id' => $user_id,
|
||||
'product_id' => $product->get_id(),
|
||||
'status' => 'pending-cancel',
|
||||
]
|
||||
);
|
||||
|
||||
foreach ( $user_subscriptions as $subscription ) {
|
||||
if ( $subscription->can_be_updated_to( 'active' ) && ! $subscription->needs_payment() ) {
|
||||
$reactivate_link = wcs_get_users_change_status_link( $subscription->get_id(), 'active', $subscription->get_status() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $reactivate_link;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -336,7 +336,6 @@ function wcs_estimate_periods_between( $start_timestamp, $end_timestamp, $unit_o
|
|||
break;
|
||||
}
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
$periods_until = ( 'ceil' == $rounding_method ) ? ceil( $seconds_until_timestamp / $denominator ) : floor( $seconds_until_timestamp / $denominator );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ function wcs_user_has_capability( $allcaps, $caps, $args ) {
|
|||
$user_id = $args[1];
|
||||
$subscription = wcs_get_subscription( $args[2] );
|
||||
|
||||
if ( $user_id === $subscription->get_user_id() ) {
|
||||
if ( $subscription && $user_id === $subscription->get_user_id() ) {
|
||||
$allcaps['edit_shop_subscription_status'] = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -367,7 +367,7 @@ function wcs_user_has_capability( $allcaps, $caps, $args ) {
|
|||
$user_id = $args[1];
|
||||
$subscription = wcs_get_subscription( $args[2] );
|
||||
|
||||
if ( $user_id === $subscription->get_user_id() ) {
|
||||
if ( $subscription && $user_id === $subscription->get_user_id() ) {
|
||||
$allcaps['edit_shop_subscription_line_items'] = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -375,7 +375,7 @@ function wcs_user_has_capability( $allcaps, $caps, $args ) {
|
|||
$user_id = $args[1];
|
||||
$subscription = wcs_get_subscription( $args[2] );
|
||||
|
||||
if ( $user_id === $subscription->get_user_id() ) {
|
||||
if ( $subscription && $user_id === $subscription->get_user_id() ) {
|
||||
$allcaps['switch_shop_subscription'] = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -383,7 +383,7 @@ function wcs_user_has_capability( $allcaps, $caps, $args ) {
|
|||
$user_id = $args[1];
|
||||
$subscription = wcs_get_subscription( $args[2] );
|
||||
|
||||
if ( $user_id === $subscription->get_user_id() ) {
|
||||
if ( $subscription && $user_id === $subscription->get_user_id() ) {
|
||||
$allcaps['subscribe_again'] = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -803,31 +803,12 @@ class WCS_Gifting {
|
|||
* @since 7.8.0 - Originally implemented in WooCommerce Subscriptions Gifting 2.1.0.
|
||||
*/
|
||||
public static function get_gifted_subscriptions_count() {
|
||||
global $wpdb;
|
||||
|
||||
if ( function_exists( 'wcs_is_custom_order_tables_usage_enabled' ) && wcs_is_custom_order_tables_usage_enabled() ) {
|
||||
$count = $wpdb->get_var(
|
||||
"
|
||||
SELECT COUNT(DISTINCT o.id) FROM {$wpdb->prefix}wc_orders o
|
||||
INNER JOIN {$wpdb->prefix}wc_orders_meta om ON (o.id = om.order_id)
|
||||
WHERE o.type = 'shop_subscription'
|
||||
AND o.status NOT IN ( 'auto-draft', 'trash' )
|
||||
AND om.meta_key = '_recipient_user'
|
||||
"
|
||||
);
|
||||
} else {
|
||||
$count = $wpdb->get_var(
|
||||
"
|
||||
SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p
|
||||
INNER JOIN {$wpdb->postmeta} pm ON (p.ID = pm.post_id)
|
||||
WHERE p.post_type = 'shop_subscription'
|
||||
AND p.post_status NOT IN ( 'auto-draft', 'trash' )
|
||||
AND pm.meta_key = '_recipient_user'
|
||||
"
|
||||
);
|
||||
if ( ! class_exists( \Automattic\WooCommerce_Subscriptions\Internal\Telemetry\Subscriptions::class ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return absint( $count );
|
||||
$telemetry = new \Automattic\WooCommerce_Subscriptions\Internal\Telemetry\Subscriptions();
|
||||
return $telemetry->get_gifted_subscriptions_count();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class WCSG_Email {
|
|||
*/
|
||||
public static function init() {
|
||||
add_filter( 'woocommerce_email_classes', __CLASS__ . '::add_new_recipient_customer_email', 11, 1 );
|
||||
add_filter( 'wcs_email_classes', __CLASS__ . '::add_new_recipient_customer_email', 11, 1 );
|
||||
add_action( 'woocommerce_init', __CLASS__ . '::hook_email' );
|
||||
add_action( 'wcs_gifting_email_order_details', array( __CLASS__, 'order_details' ), 10, 4 );
|
||||
add_action( 'woocommerce_subscriptions_gifting_recipient_email_details', array( __CLASS__, 'get_related_subscriptions_table' ), 10, 3 );
|
||||
|
|
@ -66,12 +67,6 @@ class WCSG_Email {
|
|||
* @param WC_Email[] $email_classes E-mail classes.
|
||||
*/
|
||||
public static function add_new_recipient_customer_email( $email_classes ) {
|
||||
|
||||
require_once 'emails/class-wcsg-email-customer-new-account.php';
|
||||
require_once 'emails/class-wcsg-email-completed-renewal-order.php';
|
||||
require_once 'emails/class-wcsg-email-processing-renewal-order.php';
|
||||
require_once 'emails/class-wcsg-email-recipient-new-initial-order.php';
|
||||
|
||||
$email_classes['WCSG_Email_Customer_New_Account'] = new WCSG_Email_Customer_New_Account();
|
||||
$email_classes['WCSG_Email_Completed_Renewal_Order'] = new WCSG_Email_Completed_Renewal_Order();
|
||||
$email_classes['WCSG_Email_Processing_Renewal_Order'] = new WCSG_Email_Processing_Renewal_Order();
|
||||
|
|
|
|||
|
|
@ -100,6 +100,11 @@ class WCSG_Email_Customer_New_Account extends WC_Email {
|
|||
* Returns content for the HTML version of the e-mail.
|
||||
*/
|
||||
public function get_content_html() {
|
||||
// Handle the email preview.
|
||||
if ( empty( $this->subscription_owner ) ) {
|
||||
$this->set_preview_data();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
wc_get_template(
|
||||
$this->template_html,
|
||||
|
|
@ -125,6 +130,11 @@ class WCSG_Email_Customer_New_Account extends WC_Email {
|
|||
* Returns content for the plain text version of the e-mail.
|
||||
*/
|
||||
public function get_content_plain() {
|
||||
// Handle the email preview.
|
||||
if ( empty( $this->subscription_owner ) ) {
|
||||
$this->set_preview_data();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
wc_get_template(
|
||||
$this->template_plain,
|
||||
|
|
@ -145,4 +155,11 @@ class WCSG_Email_Customer_New_Account extends WC_Email {
|
|||
);
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set WooCommerce email preview data.
|
||||
*/
|
||||
public function set_preview_data() {
|
||||
$this->subscription_owner = $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,13 @@ class WCSG_Email_Recipient_New_Initial_Order extends WC_Email {
|
|||
*/
|
||||
public $wcsg_sending_recipient_email;
|
||||
|
||||
/**
|
||||
* Recipient user.
|
||||
*
|
||||
* @var WP_User
|
||||
*/
|
||||
public $recipient_user;
|
||||
|
||||
/**
|
||||
* Create an instance of the class.
|
||||
*/
|
||||
|
|
@ -65,8 +72,8 @@ class WCSG_Email_Recipient_New_Initial_Order extends WC_Email {
|
|||
public function trigger( $recipient_user, $recipient_subscriptions ) {
|
||||
|
||||
if ( $recipient_user ) {
|
||||
$this->object = get_user_by( 'id', $recipient_user );
|
||||
$this->recipient = stripslashes( $this->object->user_email );
|
||||
$this->recipient_user = get_user_by( 'id', $recipient_user );
|
||||
$this->recipient = stripslashes( $this->recipient_user->user_email );
|
||||
$subscription = wcs_get_subscription( $recipient_subscriptions[0] );
|
||||
$this->subscription_owner = WCS_Gifting::get_user_display_name( $subscription->get_user_id() );
|
||||
$this->subscriptions = $recipient_subscriptions;
|
||||
|
|
@ -86,13 +93,18 @@ class WCSG_Email_Recipient_New_Initial_Order extends WC_Email {
|
|||
* Returns the content for the HTML version of the e-mail.
|
||||
*/
|
||||
public function get_content_html() {
|
||||
// Handle the email preview.
|
||||
if ( empty( $this->subscription_owner ) ) {
|
||||
$this->set_preview_data();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
wc_get_template(
|
||||
$this->template_html,
|
||||
array(
|
||||
'email_heading' => $this->get_heading(),
|
||||
'blogname' => $this->get_blogname(),
|
||||
'recipient_user' => $this->object,
|
||||
'recipient_user' => $this->recipient_user,
|
||||
'subscription_purchaser' => $this->subscription_owner,
|
||||
'subscriptions' => $this->subscriptions,
|
||||
'sent_to_admin' => false,
|
||||
|
|
@ -110,6 +122,11 @@ class WCSG_Email_Recipient_New_Initial_Order extends WC_Email {
|
|||
* Returns the content for the plain text version of the e-mail.
|
||||
*/
|
||||
public function get_content_plain() {
|
||||
// Handle the email preview.
|
||||
if ( empty( $this->subscription_owner ) ) {
|
||||
$this->set_preview_data();
|
||||
}
|
||||
|
||||
ob_start();
|
||||
wc_get_template(
|
||||
$this->template_plain,
|
||||
|
|
@ -127,7 +144,14 @@ class WCSG_Email_Recipient_New_Initial_Order extends WC_Email {
|
|||
'',
|
||||
$this->template_base
|
||||
);
|
||||
return ob_get_clean();
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set WooCommerce email preview data.
|
||||
*/
|
||||
public function set_preview_data() {
|
||||
$this->subscription_owner = WCS_Gifting::get_user_display_name( $this->subscriptions[0]->get_user_id() );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
4347
phpstan.neon
4347
phpstan.neon
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,6 @@
|
|||
# The internal namespace
|
||||
|
||||
- All the code in this directory (and hence in the `Automattic\WooCommerce_Subscriptions\Internal` namespace) is internal WooCommerce Subscriptions infrastructure code.
|
||||
- Our internal code can change at any time (there are zero guarantees of backwards compatibility), and so the classes and methods you see here should be avoided by extension developers.
|
||||
- This guidance applies to all the code entities in this namespace, even those not having an `@internal` annotation.
|
||||
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce_Subscriptions\Internal\Telemetry;
|
||||
|
||||
use Automattic\WooCommerce_Subscriptions\Internal\Utilities\Scheduled_Actions;
|
||||
|
||||
/**
|
||||
* Handles the collection of telemetry data.
|
||||
*
|
||||
* This supplements and integrates with the data collected and sent by WC_Subscriptions_Tracker.
|
||||
*
|
||||
* @internal This class may be modified, moved or removed in future releases.
|
||||
*/
|
||||
class Collector {
|
||||
public const TRANSIENT_KEY = 'wcs-tracker-data';
|
||||
public const TRANSIENT_LIFESPAN = WEEK_IN_SECONDS;
|
||||
public const SCHEDULED_ACTION_HOOK = 'wcs-collect-telemetry-data';
|
||||
public const SCHEDULED_ACTION_GROUP = 'wcs-telemetry';
|
||||
|
||||
/**
|
||||
* Sets up telemetry collection.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup(): void {
|
||||
add_filter( self::SCHEDULED_ACTION_HOOK, array( $this, 'collect_telemetry_data' ) );
|
||||
|
||||
// Every 3 days, update our telemetry ready for use the next time WC Tracker calls home. Note that we use the
|
||||
// unique flag to indicate that there should only ever be one instance of this action.
|
||||
Scheduled_Actions::schedule_recurring_action(
|
||||
HOUR_IN_SECONDS,
|
||||
3 * DAY_IN_SECONDS,
|
||||
self::SCHEDULED_ACTION_HOOK,
|
||||
array(),
|
||||
self::SCHEDULED_ACTION_GROUP,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies an array containing our collected telemetry data.
|
||||
*
|
||||
* Additionally, a 'telemetry_cache' key is added to the array, which indicates whether the data was fetched from
|
||||
* cache or generated fresh.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_telemetry_data(): array {
|
||||
// Fetch our recently cached telemetry data, if available.
|
||||
$telemetry = get_transient( self::TRANSIENT_KEY );
|
||||
|
||||
// Otherwise (if it has not yet been generated, or expired) then let's fetch it now.
|
||||
if ( ! is_array( $telemetry ) || empty( $telemetry ) ) {
|
||||
$telemetry = $this->collect_telemetry_data();
|
||||
$telemetry['telemetry_cache'] = 'miss';
|
||||
} else {
|
||||
$telemetry['telemetry_cache'] = 'hit';
|
||||
}
|
||||
|
||||
return $telemetry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the results of various telemetry queries, and stores them in the database (via the Options API).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function collect_telemetry_data(): array {
|
||||
$orders = new Orders();
|
||||
$products = new Products();
|
||||
$subscriptions = new Subscriptions();
|
||||
$start_timer = microtime( true );
|
||||
|
||||
$telemetry = array(
|
||||
'order_trends' => array(
|
||||
'by_order_type' => $orders->get_aggregated_monthly_order_data( time() - YEAR_IN_SECONDS, time() ),
|
||||
'by_payment_gateway' => $orders->get_aggregated_monthly_order_data_by_payment_gateway( time() - YEAR_IN_SECONDS, time() ),
|
||||
),
|
||||
'products' => array(
|
||||
'frequencies' => $products->get_product_frequencies(),
|
||||
'giftable' => $products->get_active_giftable_products_count(),
|
||||
),
|
||||
'subscriptions' => array(
|
||||
'gifted' => $subscriptions->get_gifted_subscriptions_count(),
|
||||
'payment_methods' => $subscriptions->get_subscriptions_by_payment_method(),
|
||||
'renewal_frequencies' => $subscriptions->get_subscriptions_by_frequency(),
|
||||
'renewing_automatically' => $subscriptions->get_active_subscriptions_renewing_automatically(),
|
||||
'renewing_manually' => $subscriptions->get_active_subscriptions_renewing_manually(),
|
||||
'subscriber_count' => $subscriptions->get_subscriber_count(),
|
||||
),
|
||||
);
|
||||
|
||||
$telemetry['generation_timestamp'] = time();
|
||||
$telemetry['total_generation_time'] = ( microtime( true ) - $start_timer ) * 1_000;
|
||||
set_transient( self::TRANSIENT_KEY, $telemetry, self::TRANSIENT_LIFESPAN );
|
||||
|
||||
return $telemetry;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce_Subscriptions\Internal\Telemetry;
|
||||
|
||||
use WC_Tracks;
|
||||
|
||||
/**
|
||||
* Monitors and locally records information about various subscription-related store events. The information is not
|
||||
* however 'sent home' unless tracking is enabled (enforced by WC_Tracks).
|
||||
*
|
||||
* @internal This class may be modified, moved or removed in future releases.
|
||||
*/
|
||||
class Events {
|
||||
private $event_recorder;
|
||||
|
||||
/**
|
||||
* Prepares the event monitoring/recording system.
|
||||
*
|
||||
* @param callable|null $event_recorder Optional. The function to use to record events. Defaults to WC_Tracks::record_event().
|
||||
*/
|
||||
public function __construct( ?callable $event_recorder = null ) {
|
||||
$this->event_recorder = $event_recorder ?? function ( string $event_name, array $event_properties = array() ) {
|
||||
// Note that the following method ensures nothing is sent home unless tracking is enabled.
|
||||
WC_Tracks::record_event( $event_name, $event_properties );
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds listeners for events where we want to send a corresponding Tracks event.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup(): void {
|
||||
add_action( 'woocommerce_new_subscription', array( $this, 'track_new_subscriptions' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the creation of a new subscription.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function track_new_subscriptions(): void {
|
||||
call_user_func( $this->event_recorder, 'wcs_new_subscription_created' );
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,241 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce_Subscriptions\Internal\Telemetry;
|
||||
|
||||
use WCSG_Admin;
|
||||
use WP_Query;
|
||||
use WP_Term;
|
||||
|
||||
/**
|
||||
* Provides high-level information, primarily intended for use with WC Tracker, about the number and range of
|
||||
* subscription products.
|
||||
*
|
||||
* @internal This class may be modified, moved or removed in future releases.
|
||||
*/
|
||||
class Products {
|
||||
/**
|
||||
* Counts the total number of active subscription products that are eligible for gifting.
|
||||
*
|
||||
* If the gifting feature is disabled, this will be zero.
|
||||
*
|
||||
* Otherwise, if gifting is enabled for all products, we exclude any products that have individually been set to
|
||||
* disabled. Similarly, if gifting is disabled for all products by default, we only count those products that have
|
||||
* been individually set to enabled.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_active_giftable_products_count(): int {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! WCSG_Admin::is_gifting_enabled() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$subscription_product_term_ids = $this->get_subscription_product_type_term_ids();
|
||||
|
||||
// Under unusual conditions, we may be missing one or both product type term IDs.
|
||||
if ( false === $subscription_product_term_ids ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$atomic_gifting_condition = WCSG_Admin::is_gifting_enabled_for_all_products()
|
||||
? "( gifting_setting.meta_value <> 'disabled' OR gifting_setting.meta_key IS NULL )"
|
||||
: "gifting_setting.meta_value = 'enabled'";
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT(*)
|
||||
FROM %i AS product
|
||||
-- Reduce the result set to products of the `subscription` and `variable_subscription` product types.
|
||||
INNER JOIN (
|
||||
SELECT product_post.ID,
|
||||
product_type.term_taxonomy_id,
|
||||
product_post.post_status
|
||||
FROM %i AS product_post
|
||||
INNER JOIN %i AS product_type ON (
|
||||
product_type.object_id = product_post.ID
|
||||
AND product_type.term_taxonomy_id IN ( %d, %d )
|
||||
)
|
||||
) p ON (
|
||||
-- For variable subscription products, the relevant taxonomy term is applied to the parent post.
|
||||
( product.ID = p.ID AND p.term_taxonomy_id = %d )
|
||||
OR ( product.post_parent = p.ID AND p.term_taxonomy_id = %d )
|
||||
)
|
||||
-- Get the gifting mode (explicitly enabled, disabled, or following the global default).
|
||||
LEFT JOIN %i AS gifting_setting ON (
|
||||
gifting_setting.post_id = product.ID
|
||||
AND gifting_setting.meta_key = '_subscription_gifting'
|
||||
)
|
||||
WHERE product.post_type IN ( 'product', 'product_variation' )
|
||||
AND product.post_status = 'publish'
|
||||
AND p.post_status = 'publish'
|
||||
AND $atomic_gifting_condition
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->posts,
|
||||
$wpdb->term_relationships,
|
||||
$subscription_product_term_ids['subscription'],
|
||||
$subscription_product_term_ids['variable_subscription'],
|
||||
$subscription_product_term_ids['subscription'],
|
||||
$subscription_product_term_ids['variable_subscription'],
|
||||
$wpdb->postmeta
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies meta query arguments, for use inside a larger set of WP_Query args, that limits results to products
|
||||
* where gifting is individually enabled or disabled, depending on the value of $enabled.
|
||||
*
|
||||
* @param bool $enabled If we are interested in products where gifting is enabled, or excluding those that are disabled.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
private function build_gifting_meta_query( bool $enabled ): array {
|
||||
$meta_query = array(
|
||||
array(
|
||||
'key' => '_subscription_gifting',
|
||||
'value' => $enabled ? 'enabled' : 'disabled',
|
||||
'compare' => $enabled ? '=' : '!=',
|
||||
),
|
||||
);
|
||||
|
||||
if ( ! $enabled ) {
|
||||
$meta_query['relation'] = 'OR';
|
||||
$meta_query[] = array(
|
||||
'key' => '_subscription_gifting',
|
||||
'compare' => 'NOT EXISTS',
|
||||
);
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
return array( 'meta_query' => $meta_query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects detailing the number of published subscription products by frequency.
|
||||
*
|
||||
* The return value is an array of objects, with each object containing the properties period, interval and product count:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* period: string,
|
||||
* interval: int,
|
||||
* count: int
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* @return object[]
|
||||
*/
|
||||
public function get_product_frequencies(): array {
|
||||
global $wpdb;
|
||||
|
||||
$subscription_product_term_ids = $this->get_subscription_product_type_term_ids();
|
||||
|
||||
// Under unusual conditions, we may be missing one or both product type term IDs.
|
||||
if ( false === $subscription_product_term_ids ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
-- Count the number of subscription products by billing period and billing interval.
|
||||
SELECT billing_period.meta_value AS period,
|
||||
billing_interval.meta_value AS `interval`,
|
||||
COUNT(*) AS count
|
||||
FROM %i AS product
|
||||
-- Reduce the result set to products of the `subscription` and `variable_subscription` product types.
|
||||
INNER JOIN (
|
||||
SELECT product_post.ID,
|
||||
product_type.term_taxonomy_id,
|
||||
product_post.post_status
|
||||
FROM %i AS product_post
|
||||
INNER JOIN %i AS product_type ON (
|
||||
product_type.object_id = product_post.ID
|
||||
AND product_type.term_taxonomy_id IN ( %d, %d )
|
||||
)
|
||||
) subscription_product ON (
|
||||
-- For variable subscription products, the relevant taxonomy term is applied to the parent post.
|
||||
( product.ID = subscription_product.ID AND subscription_product.term_taxonomy_id = %d )
|
||||
OR ( product.post_parent = subscription_product.ID AND subscription_product.term_taxonomy_id = %d )
|
||||
)
|
||||
-- Obtain the billing period interval (usually an integer, or string representation of an integer).
|
||||
LEFT JOIN %i AS billing_interval ON (
|
||||
billing_interval.post_id = product.ID
|
||||
AND billing_interval.meta_key = '_subscription_period_interval'
|
||||
)
|
||||
-- Obtain the billing period (usually one of 'day', 'week', 'month', 'year').
|
||||
LEFT JOIN %i AS billing_period ON (
|
||||
billing_period.post_id = product.ID
|
||||
AND billing_period.meta_key = '_subscription_period'
|
||||
)
|
||||
-- We are only interested in active (published) products and product variations.
|
||||
WHERE product.post_type IN ( 'product', 'product_variation' )
|
||||
AND product.post_status = 'publish'
|
||||
AND subscription_product.post_status = 'publish'
|
||||
GROUP BY billing_period.meta_value,
|
||||
billing_interval.meta_value
|
||||
ORDER BY count DESC,
|
||||
billing_period.meta_value ASC,
|
||||
billing_interval.meta_value DESC
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->posts,
|
||||
$wpdb->term_relationships,
|
||||
$subscription_product_term_ids['subscription'],
|
||||
$subscription_product_term_ids['variable_subscription'],
|
||||
$subscription_product_term_ids['subscription'],
|
||||
$subscription_product_term_ids['variable_subscription'],
|
||||
$wpdb->postmeta,
|
||||
$wpdb->postmeta,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $results as $index => &$result_set ) {
|
||||
if ( empty( $result_set->period ) || empty( $result_set->interval ) ) {
|
||||
unset( $results[ $index ] );
|
||||
continue;
|
||||
}
|
||||
|
||||
$result_set->period = (string) $result_set->period;
|
||||
$result_set->interval = (int) $result_set->interval;
|
||||
$result_set->count = (int) $result_set->count;
|
||||
}
|
||||
|
||||
return array_values( $results );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the term IDs for the subscription and variable subscription product types.
|
||||
*
|
||||
* This will be presented as a keyed array of integers, as follows (unless one or both terms are missing, in which
|
||||
* case bool false will be returned):
|
||||
*
|
||||
* [
|
||||
* 'subscription' => int,
|
||||
* 'variable_subscription' => int
|
||||
* ]
|
||||
*
|
||||
* @return int[]|false The term IDs for the subscription and variable subscription product types, else false.
|
||||
*/
|
||||
private function get_subscription_product_type_term_ids() {
|
||||
$subscription_product_term_ids = array();
|
||||
|
||||
$subscription_term = get_term_by( 'slug', 'subscription', 'product_type' );
|
||||
$variable_subscription_term = get_term_by( 'slug', 'variable-subscription', 'product_type' );
|
||||
|
||||
if ( ! is_a( $subscription_term, WP_Term::class ) || ! is_a( $variable_subscription_term, WP_Term::class ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'subscription' => (int) $subscription_term->term_id,
|
||||
'variable_subscription' => (int) $variable_subscription_term->term_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,556 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce_Subscriptions\Internal\Telemetry;
|
||||
|
||||
use WC_Payment_Gateways;
|
||||
|
||||
/**
|
||||
* Provides high-level information, primarily intended for use with WC Tracker, about the number, range,
|
||||
* and associated payment methods of subscriptions.
|
||||
*
|
||||
* @internal This class may be modified, moved or removed in future releases.
|
||||
*/
|
||||
class Subscriptions {
|
||||
/**
|
||||
* Quoted and comma separated list of subscription statuses that are considered active.
|
||||
*
|
||||
* These are held directly as a string (rather than an array of statuses) because that is how they are consumed, but
|
||||
* if we find it useful in the future to convert to an array (perhaps so they can be filtered), we can make that
|
||||
* change.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $active_subscription_statuses_clause;
|
||||
|
||||
/**
|
||||
* If HPOS is enabled.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private bool $is_hpos;
|
||||
|
||||
/**
|
||||
* The full and prefixed name of the orders table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $wc_orders_table;
|
||||
|
||||
/**
|
||||
* The full and prefixed name of the orders meta table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private string $wc_orders_meta_table;
|
||||
|
||||
/**
|
||||
* Prepares Subscriptions telemetry collection.
|
||||
*/
|
||||
public function __construct() {
|
||||
global $wpdb;
|
||||
|
||||
$this->active_subscription_statuses_clause = "'wc-active', 'wc-pending-cancel'";
|
||||
$this->is_hpos = wcs_is_custom_order_tables_usage_enabled();
|
||||
$this->wc_orders_table = $wpdb->prefix . 'wc_orders';
|
||||
$this->wc_orders_meta_table = $wpdb->prefix . 'wc_orders_meta';
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies the number of active subscribers. That is, the number of unique users who have at least one active
|
||||
* subscription.
|
||||
*
|
||||
* @param bool $active Whether to return a count of active subscribers (true) or inactive subscribers (false). Default true.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_subscriber_count( bool $active = true ): int {
|
||||
return $this->is_hpos
|
||||
? $this->get_hpos_subscriber_count( $active )
|
||||
: $this->get_cpt_subscriber_count( $active );
|
||||
}
|
||||
|
||||
/**
|
||||
* HPOS implementation of get_active_subscriber_count().
|
||||
*
|
||||
* @param bool $active Whether to return a count of active subscribers (true) or inactive subscribers (false). Default true.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_hpos_subscriber_count( bool $active = true ): int {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
$base_query = $wpdb->prepare(
|
||||
"
|
||||
FROM %i
|
||||
WHERE type = 'shop_subscription'
|
||||
AND customer_id IS NOT NULL
|
||||
AND status IN ( $this->active_subscription_statuses_clause )
|
||||
",
|
||||
$this->wc_orders_table
|
||||
);
|
||||
|
||||
if ( $active ) {
|
||||
$query = "
|
||||
SELECT COUNT( DISTINCT customer_id )
|
||||
$base_query
|
||||
";
|
||||
} else {
|
||||
$query = $wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT( DISTINCT customer_id )
|
||||
FROM %i
|
||||
WHERE type = 'shop_subscription'
|
||||
AND customer_id IS NOT NULL
|
||||
AND customer_id NOT IN (
|
||||
SELECT DISTINCT customer_id
|
||||
$base_query
|
||||
)
|
||||
",
|
||||
$this->wc_orders_table
|
||||
);
|
||||
}
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
return (int) $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* CPT implementation of get_active_subscriber_count().
|
||||
*
|
||||
* @param bool $active Whether to return a count of active subscribers (true) or inactive subscribers (false). Default true.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_cpt_subscriber_count( bool $active = true ): int {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
$base_query = $wpdb->prepare(
|
||||
"
|
||||
FROM %i AS orders
|
||||
JOIN %i AS customer ON (
|
||||
orders.ID = customer.post_id
|
||||
AND customer.meta_key = '_customer_user'
|
||||
)
|
||||
WHERE orders.post_type = 'shop_subscription'
|
||||
AND orders.post_status IN ( $this->active_subscription_statuses_clause )
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta
|
||||
);
|
||||
|
||||
if ( $active ) {
|
||||
$query = "
|
||||
SELECT COUNT( DISTINCT customer.meta_value ) AS customer_id
|
||||
$base_query
|
||||
";
|
||||
} else {
|
||||
$query = $wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT( DISTINCT customer.meta_value ) AS customer_id
|
||||
FROM %i AS orders
|
||||
JOIN %i AS customer ON (
|
||||
orders.ID = customer.post_id
|
||||
AND customer.meta_key = '_customer_user'
|
||||
)
|
||||
WHERE orders.post_type = 'shop_subscription'
|
||||
AND customer.meta_value NOT IN (
|
||||
SELECT DISTINCT customer.meta_value
|
||||
$base_query
|
||||
)
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta
|
||||
);
|
||||
}
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
return (int) $wpdb->get_var( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies the number of active subscriptions that are set to renew automatically.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_active_subscriptions_renewing_automatically(): int {
|
||||
return $this->is_hpos
|
||||
? $this->get_hpos_subscriptions_count()
|
||||
: $this->get_cpt_subscriptions_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies the number of active subscriptions that are set to renew manually.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_active_subscriptions_renewing_manually(): int {
|
||||
return $this->is_hpos
|
||||
? $this->get_hpos_subscriptions_count( false )
|
||||
: $this->get_cpt_subscriptions_count( false );
|
||||
}
|
||||
|
||||
/**
|
||||
* HPOS implementation for get_active_subscriptions_renewing_<automatically|manually>().
|
||||
*
|
||||
* @param bool $automatic_renewal If we are interested specifically in subscriptions renewing automatically (true) or manually (false). Default true.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_hpos_subscriptions_count( bool $automatic_renewal = true ): int {
|
||||
global $wpdb;
|
||||
$renewal_condition = $automatic_renewal ? '<>' : '=';
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT( 1 ) AS order_count
|
||||
FROM %i AS orders
|
||||
LEFT JOIN %i AS order_meta ON (
|
||||
orders.id = order_meta.order_id
|
||||
AND order_meta.meta_key = '_requires_manual_renewal'
|
||||
)
|
||||
WHERE orders.type = 'shop_subscription'
|
||||
AND orders.status IN ( $this->active_subscription_statuses_clause )
|
||||
AND order_meta.meta_value $renewal_condition 'true'
|
||||
",
|
||||
$this->wc_orders_table,
|
||||
$this->wc_orders_meta_table
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* CPT implementation for get_active_subscriptions_renewing_<automatically|manually>().
|
||||
*
|
||||
* @param bool $automatic_renewal If we are interested specifically in subscriptions renewing automatically (true) or manually (false). Default true.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_cpt_subscriptions_count( bool $automatic_renewal = true ): int {
|
||||
global $wpdb;
|
||||
$renewal_condition = $automatic_renewal ? '<>' : '=';
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return (int) $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT( 1 ) AS order_count
|
||||
FROM %i AS orders
|
||||
LEFT JOIN %i AS order_meta ON (
|
||||
orders.ID = order_meta.post_id
|
||||
AND order_meta.meta_key = '_requires_manual_renewal'
|
||||
|
||||
)
|
||||
WHERE orders.post_type = 'shop_subscription'
|
||||
AND orders.post_status IN ( $this->active_subscription_statuses_clause )
|
||||
AND order_meta.meta_value $renewal_condition 'true'
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects detailing the number of (active) subscriptions by frequency.
|
||||
*
|
||||
* The return value is an array of objects, with each object containing the properties period, interval and count:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* period: string,
|
||||
* interval: int,
|
||||
* count: int
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* @return object[]
|
||||
*/
|
||||
public function get_subscriptions_by_frequency(): array {
|
||||
$results = (array) (
|
||||
$this->is_hpos
|
||||
? $this->get_hpos_subscriptions_by_frequency()
|
||||
: $this->get_cpt_subscriptions_by_frequency()
|
||||
);
|
||||
|
||||
foreach ( $results as &$result_set ) {
|
||||
$result_set->period = (string) $result_set->period;
|
||||
$result_set->interval = (int) $result_set->interval;
|
||||
$result_set->count = (int) $result_set->count;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* HPOS implementation of get_subscriptions_by_frequency().
|
||||
*/
|
||||
private function get_hpos_subscriptions_by_frequency(): array {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT billing_period.meta_value AS period,
|
||||
billing_interval.meta_value AS `interval`,
|
||||
COUNT(*) AS count
|
||||
FROM %i AS orders
|
||||
LEFT JOIN %i AS billing_period ON (
|
||||
orders.id = billing_period.order_id
|
||||
AND billing_period.meta_key = '_billing_period'
|
||||
)
|
||||
LEFT JOIN %i AS billing_interval ON (
|
||||
orders.id = billing_interval.order_id
|
||||
AND billing_interval.meta_key = '_billing_interval'
|
||||
)
|
||||
WHERE orders.type = 'shop_subscription'
|
||||
AND orders.status IN ( $this->active_subscription_statuses_clause )
|
||||
GROUP BY billing_period.meta_value,
|
||||
billing_interval.meta_value
|
||||
ORDER BY count DESC,
|
||||
billing_period.meta_value ASC,
|
||||
billing_interval.meta_value DESC
|
||||
",
|
||||
$this->wc_orders_table,
|
||||
$this->wc_orders_meta_table,
|
||||
$this->wc_orders_meta_table
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* CPT implementation of get_subscriptions_by_frequency().
|
||||
*/
|
||||
private function get_cpt_subscriptions_by_frequency(): array {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT billing_period.meta_value AS period,
|
||||
billing_interval.meta_value AS `interval`,
|
||||
COUNT(*) AS count
|
||||
FROM %i AS orders
|
||||
LEFT JOIN %i AS billing_period ON (
|
||||
orders.ID = billing_period.post_id
|
||||
AND billing_period.meta_key = '_billing_period'
|
||||
)
|
||||
LEFT JOIN %i AS billing_interval ON (
|
||||
orders.ID = billing_interval.post_id
|
||||
AND billing_interval.meta_key = '_billing_interval'
|
||||
)
|
||||
WHERE orders.post_type = 'shop_subscription'
|
||||
AND orders.post_status IN ( $this->active_subscription_statuses_clause )
|
||||
GROUP BY billing_period.meta_value,
|
||||
billing_interval.meta_value
|
||||
ORDER BY count DESC,
|
||||
billing_period.meta_value ASC,
|
||||
billing_interval.meta_value DESC
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta,
|
||||
$wpdb->postmeta
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a count of subscriptions grouped by payment method.
|
||||
*
|
||||
* The return value is an array of objects, with each object containing the properties payment_method and order_count:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* payment_method: string,
|
||||
* active_subscription_count: int,
|
||||
* inactive_subscription_count: int,
|
||||
* method_renews_off_site: string, # 'yes'|'no'|'unknown'
|
||||
* manual_renewal_only: string, # 'yes'|'no'|'unknown'
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* Note that the method_renews_off_site property is set if the gateway reports that it supports off-site renewal
|
||||
* payment ('gateway_scheduled_payments'). See also payment_method_renews_off_site() for caveats on this.
|
||||
*
|
||||
* @return object[] Array of objects containing payment_method and order_count.
|
||||
*/
|
||||
public function get_subscriptions_by_payment_method(): array {
|
||||
$results = $this->is_hpos
|
||||
? $this->get_hpos_subscriptions_by_payment_method()
|
||||
: $this->get_cpt_subscriptions_by_payment_method();
|
||||
|
||||
foreach ( $results as &$result_set ) {
|
||||
$gateway_properties = $this->payment_method_properties( $result_set->payment_method );
|
||||
$result_set->payment_method = (string) $result_set->payment_method;
|
||||
$result_set->active_subscription_count = (int) $result_set->active_subscription_count;
|
||||
$result_set->inactive_subscription_count = (int) $result_set->inactive_subscription_count;
|
||||
$result_set->method_renews_off_site = $gateway_properties['gateway_scheduled_payments'];
|
||||
$result_set->manual_renewal_only = $gateway_properties['manual_renewal_only'];
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* HPOS implementation of get_subscriptions_by_payment_method().
|
||||
*/
|
||||
private function get_hpos_subscriptions_by_payment_method(): array {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT
|
||||
IFNULL( payment_method, '' ) as payment_method,
|
||||
SUM( CASE WHEN status IN ( $this->active_subscription_statuses_clause ) THEN 1 ELSE 0 END ) AS active_subscription_count,
|
||||
SUM( CASE WHEN status NOT IN ( $this->active_subscription_statuses_clause ) THEN 1 ELSE 0 END ) AS inactive_subscription_count
|
||||
FROM %i
|
||||
WHERE type = 'shop_subscription'
|
||||
GROUP BY IFNULL(payment_method, '')
|
||||
ORDER BY active_subscription_count DESC,
|
||||
inactive_subscription_count DESC;
|
||||
",
|
||||
$this->wc_orders_table
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* CPT implementation of get_subscriptions_by_payment_method().
|
||||
*/
|
||||
private function get_cpt_subscriptions_by_payment_method(): array {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- property $this->active_subscription_statuses_clause is sanitized.
|
||||
return $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT
|
||||
IFNULL(order_meta.meta_value, '') AS payment_method,
|
||||
SUM( CASE WHEN orders.post_status IN ( $this->active_subscription_statuses_clause ) THEN 1 ELSE 0 END ) AS active_subscription_count,
|
||||
SUM( CASE WHEN orders.post_status NOT IN ( $this->active_subscription_statuses_clause ) THEN 1 ELSE 0 END ) AS inactive_subscription_count
|
||||
FROM %i AS orders
|
||||
LEFT JOIN %i AS order_meta ON orders.ID = order_meta.post_id
|
||||
AND order_meta.meta_key = '_payment_method'
|
||||
WHERE orders.post_type = 'shop_subscription'
|
||||
GROUP BY IFNULL(order_meta.meta_value, '')
|
||||
ORDER BY active_subscription_count DESC,
|
||||
inactive_subscription_count DESC;
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the specified payment method supports off-site renewal payment (ie, gateway scheduled payments), and
|
||||
* if it supports subscriptions.
|
||||
*
|
||||
* Note that, just because a gateways supports 'gateway_scheduled_payments', does not mean it is supported for a
|
||||
* specific subscription.
|
||||
*
|
||||
* @param string $payment_method
|
||||
*
|
||||
* @return array {
|
||||
* gateway_scheduled_payments: string
|
||||
* manual_renewal_only: string
|
||||
* }
|
||||
*/
|
||||
private function payment_method_properties( string $payment_method ): array {
|
||||
// If a particular gateway is disabled/inactive, then we cannot determine what it does or does not support.
|
||||
$properties = array(
|
||||
'gateway_scheduled_payments' => 'unknown',
|
||||
'manual_renewal_only' => 'unknown',
|
||||
);
|
||||
|
||||
foreach ( WC_Payment_Gateways::instance()->payment_gateways() as $gateway ) {
|
||||
if ( $payment_method === $gateway->id ) {
|
||||
$properties['gateway_scheduled_payments'] = $gateway->supports( 'gateway_scheduled_payments' ) ? 'yes' : 'no';
|
||||
$properties['manual_renewal_only'] = $gateway->supports( 'subscriptions' ) ? 'no' : 'yes';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supplies the total count of gifted subscriptions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_gifted_subscriptions_count(): int {
|
||||
return $this->is_hpos
|
||||
? $this->get_hpos_gifted_subscriptions_count()
|
||||
: $this->get_cpt_gifted_subscriptions_count();
|
||||
}
|
||||
|
||||
/**
|
||||
* HPOS implementation of get_gifted_subscriptions_count().
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_hpos_gifted_subscriptions_count(): int {
|
||||
global $wpdb;
|
||||
|
||||
$count = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT(DISTINCT orders.id)
|
||||
FROM %i AS orders
|
||||
INNER JOIN %i AS orders_meta ON (orders.id = orders_meta.order_id)
|
||||
WHERE orders.type = 'shop_subscription'
|
||||
AND orders.status NOT IN ( 'auto-draft', 'trash' )
|
||||
AND orders_meta.meta_key = '_recipient_user'
|
||||
",
|
||||
$this->wc_orders_table,
|
||||
$this->wc_orders_meta_table
|
||||
)
|
||||
);
|
||||
|
||||
return absint( $count );
|
||||
}
|
||||
|
||||
/**
|
||||
* CPT implementation of get_gifted_subscriptions_count().
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function get_cpt_gifted_subscriptions_count(): int {
|
||||
global $wpdb;
|
||||
|
||||
$count = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT COUNT(DISTINCT posts.ID)
|
||||
FROM %i AS posts
|
||||
INNER JOIN %i AS posts_meta ON (posts.ID = posts_meta.post_id)
|
||||
WHERE posts.post_type = 'shop_subscription'
|
||||
AND posts.post_status NOT IN ( 'auto-draft', 'trash' )
|
||||
AND posts_meta.meta_key = '_recipient_user'
|
||||
",
|
||||
$wpdb->posts,
|
||||
$wpdb->postmeta,
|
||||
)
|
||||
);
|
||||
|
||||
return absint( $count );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Automattic\WooCommerce_Subscriptions\Internal\Utilities;
|
||||
|
||||
/**
|
||||
* Utilities to ease working with Action Scheduler, and to help safely take advantage of modern Action Scheduler
|
||||
* features in a backwards-compatible way.
|
||||
*
|
||||
* @internal This class may be modified, moved or removed in future releases.
|
||||
*/
|
||||
class Scheduled_Actions {
|
||||
/**
|
||||
* Schedules a recurring action.
|
||||
*
|
||||
* This method offers two advantages:
|
||||
*
|
||||
* 1. It automatically takes advantage of the `action_scheduler_ensure_recurring_actions` hook, if available, which
|
||||
* minimizes overhead.
|
||||
* 2. It can be called before Action Scheduler has initialized (in this case, it takes care of registering the
|
||||
* action later in the request).
|
||||
*
|
||||
* The second point in particular presents a trade-off since, unlike a direct call to as_schedule_recurring_action()
|
||||
* there is no return value to indicate success/failure. When this is needed, you should handle things directly.
|
||||
*
|
||||
* @param int $timestamp
|
||||
* @param int $interval_in_seconds
|
||||
* @param string $hook
|
||||
* @param array $args
|
||||
* @param string $group
|
||||
* @param bool $unique
|
||||
* @param int $priority
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function schedule_recurring_action(
|
||||
int $timestamp,
|
||||
int $interval_in_seconds,
|
||||
string $hook,
|
||||
array $args = array(),
|
||||
string $group = '',
|
||||
bool $unique = false,
|
||||
int $priority = 10
|
||||
) {
|
||||
// If this method is called too early, Action Scheduler will not be ready. Therefore, defer until it is ready.
|
||||
if ( ! did_action( 'action_scheduler_init' ) && ! doing_action( 'action_scheduler_init' ) ) {
|
||||
add_action( 'action_scheduler_init', fn() => self::schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args, $group, $unique, $priority ) );
|
||||
return;
|
||||
}
|
||||
|
||||
$register_action = static function () use ( $timestamp, $interval_in_seconds, $hook, $args, $group, $unique, $priority ) {
|
||||
// Older versions of Action Scheduler don't support 'uniqueness', or don't support it evenly (across data
|
||||
// stores), so we add an additional safeguard.
|
||||
if ( $unique && as_has_scheduled_action( $hook, $args, $group ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args, $group, $unique, $priority );
|
||||
};
|
||||
|
||||
// Since Action Scheduler 3.9.3 it is generally preferable to register recurring actions during the action
|
||||
// that the library provides for this purpose.
|
||||
$registration_hook = function_exists( 'as_supports' ) && as_supports( 'ensure_recurring_actions_hook' )
|
||||
? 'action_scheduler_ensure_recurring_actions'
|
||||
: 'admin_init';
|
||||
|
||||
// @phpstan-ignore return.void
|
||||
add_action( $registration_hook, $register_action );
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ foreach ( WC()->cart->get_taxes() as $tax_id => $tax_total ) {
|
|||
* Allow third-parties to filter the tax displayed.
|
||||
*
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.1.0
|
||||
* @param string The recurring cart's tax total price string for this tax code.
|
||||
* @param string $tax_amount The recurring cart's tax total price string for this tax code.
|
||||
* @param WC_Cart $recurring_cart The recurring cart.
|
||||
* @param string $recurring_code The tax code.
|
||||
* @param object $recurring_tax The recurring tax data generated by @see WC_Cart::get_tax_totals()
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ foreach ( $recurring_carts as $recurring_cart_key => $recurring_cart ) {
|
|||
* Allow third-parties to filter the tax displayed.
|
||||
*
|
||||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.1.0
|
||||
* @param string The recurring cart's total tax price string.
|
||||
* @param string $tax_amount The recurring cart's total tax price string.
|
||||
* @param WC_Cart $recurring_cart The recurring cart.
|
||||
*/
|
||||
$tax_amount = wp_kses_post( apply_filters( 'wcs_recurring_cart_tax_totals_html', wcs_cart_price_string( $recurring_cart->get_taxes_total(), $recurring_cart ), $recurring_cart ) );
|
||||
|
|
|
|||
|
|
@ -19,16 +19,14 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
WCSG_Email::recipient_email_order_items_table(
|
||||
$order,
|
||||
array(
|
||||
'show_sku' => $sent_to_admin,
|
||||
'show_image' => '',
|
||||
'image_size' => '',
|
||||
'plain_text' => $plain_text,
|
||||
'sent_to_admin' => $sent_to_admin,
|
||||
)
|
||||
WCSG_Email::recipient_email_order_items_table(
|
||||
$order,
|
||||
array(
|
||||
'show_sku' => $sent_to_admin,
|
||||
'show_image' => '',
|
||||
'image_size' => '',
|
||||
'plain_text' => $plain_text,
|
||||
'sent_to_admin' => $sent_to_admin,
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ printf( esc_html__( ' Details of the %s are shown below.', 'woocommerce-subscrip
|
|||
</p>
|
||||
<?php
|
||||
|
||||
$new_recipient = get_user_meta( $recipient_user->ID, 'wcsg_update_account', true );
|
||||
// Handle the email preview.
|
||||
$new_recipient = empty( $recipient_user ) ? 'true' : get_user_meta( $recipient_user->ID, 'wcsg_update_account', true );
|
||||
|
||||
if ( 'true' == $new_recipient ) : // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
||||
?>
|
||||
|
|
@ -49,8 +50,10 @@ if ( 'true' == $new_recipient ) : // phpcs:ignore WordPress.PHP.StrictComparison
|
|||
<?php
|
||||
endif;
|
||||
|
||||
foreach ( $subscriptions as $subscription_id ) {
|
||||
$subscription = wcs_get_subscription( $subscription_id );
|
||||
foreach ( $subscriptions as $subscription ) {
|
||||
if ( ! is_object( $subscription ) ) {
|
||||
$subscription = wcs_get_subscription( $subscription );
|
||||
}
|
||||
|
||||
do_action( 'wcs_gifting_email_order_details', $subscription, $sent_to_admin, $plain_text, $email );
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,22 @@ if ( $product->is_in_stock() ) : ?>
|
|||
<?php do_action( 'woocommerce_before_add_to_cart_form' ); ?>
|
||||
|
||||
<?php if ( ! $product->is_purchasable() && 0 !== $user_id && 'no' !== wcs_get_product_limitation( $product ) && wcs_is_product_limited_for_user( $product, $user_id ) ) : ?>
|
||||
<?php $resubscribe_link = wcs_get_users_resubscribe_link_for_product( $product->get_id() ); ?>
|
||||
<?php if ( ! empty( $resubscribe_link ) && 'any' === wcs_get_product_limitation( $product ) && wcs_user_has_subscription( $user_id, $product->get_id(), wcs_get_product_limitation( $product ) ) && ! wcs_user_has_subscription( $user_id, $product->get_id(), 'active' ) && ! wcs_user_has_subscription( $user_id, $product->get_id(), 'on-hold' ) ) : // customer has an inactive subscription, maybe offer the renewal button. ?>
|
||||
<a href="<?php echo esc_url( $resubscribe_link ); ?>" class="button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Resubscribe', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php
|
||||
if ( 'any' === wcs_get_product_limitation( $product )
|
||||
&& wcs_user_has_subscription( $user_id, $product->get_id() )
|
||||
&& ! wcs_user_has_subscription( $user_id, $product->get_id(), 'active' )
|
||||
&& ! wcs_user_has_subscription( $user_id, $product->get_id(), 'on-hold' )
|
||||
) :
|
||||
?>
|
||||
<?php
|
||||
$reactivate_link = wcs_get_user_reactivate_link_for_product( $user_id, $product );
|
||||
$resubscribe_link = wcs_get_users_resubscribe_link_for_product( $product->get_id() );
|
||||
?>
|
||||
<?php if ( ! empty( $reactivate_link ) ) : // customer has a pending cancellation subscription, maybe offer the reactivate button. ?>
|
||||
<a href="<?php echo esc_url( $reactivate_link ); ?>" class="button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Reactivate', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php elseif ( ! empty( $resubscribe_link ) ) : // customer has an inactive subscription, maybe offer the renewal button. ?>
|
||||
<a href="<?php echo esc_url( $resubscribe_link ); ?>" class="button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Resubscribe', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<p class="limited-subscription-notice notice"><?php esc_html_e( 'You have an active subscription to this product already.', 'woocommerce-subscriptions' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
|
|
|||
|
|
@ -23,9 +23,22 @@ do_action( 'woocommerce_before_add_to_cart_form' ); ?>
|
|||
<p class="stock out-of-stock"><?php esc_html_e( 'This product is currently out of stock and unavailable.', 'woocommerce-subscriptions' ); ?></p>
|
||||
<?php else : ?>
|
||||
<?php if ( ! $product->is_purchasable() && 0 !== $user_id && 'no' !== wcs_get_product_limitation( $product ) && wcs_is_product_limited_for_user( $product, $user_id ) ) : ?>
|
||||
<?php $resubscribe_link = wcs_get_users_resubscribe_link_for_product( $product->get_id() ); ?>
|
||||
<?php if ( ! empty( $resubscribe_link ) && 'any' === wcs_get_product_limitation( $product ) && wcs_user_has_subscription( $user_id, $product->get_id(), wcs_get_product_limitation( $product ) ) && ! wcs_user_has_subscription( $user_id, $product->get_id(), 'active' ) && ! wcs_user_has_subscription( $user_id, $product->get_id(), 'on-hold' ) ) : // customer has an inactive subscription, maybe offer the renewal button. ?>
|
||||
<a href="<?php echo esc_url( $resubscribe_link ); ?>" class="woocommerce-button button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Resubscribe', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php
|
||||
if ( 'any' === wcs_get_product_limitation( $product )
|
||||
&& wcs_user_has_subscription( $user_id, $product->get_id() )
|
||||
&& ! wcs_user_has_subscription( $user_id, $product->get_id(), 'active' )
|
||||
&& ! wcs_user_has_subscription( $user_id, $product->get_id(), 'on-hold' )
|
||||
) :
|
||||
?>
|
||||
<?php
|
||||
$reactivate_link = wcs_get_user_reactivate_link_for_product( $user_id, $product );
|
||||
$resubscribe_link = wcs_get_users_resubscribe_link_for_product( $product->get_id() );
|
||||
?>
|
||||
<?php if ( ! empty( $reactivate_link ) ) : // customer has a pending cancellation subscription, maybe offer the reactivate button. ?>
|
||||
<a href="<?php echo esc_url( $reactivate_link ); ?>" class="button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Reactivate', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php elseif ( ! empty( $resubscribe_link ) ) : // customer has an inactive subscription, maybe offer the renewal button. ?>
|
||||
<a href="<?php echo esc_url( $resubscribe_link ); ?>" class="woocommerce-button button product-resubscribe-link<?php echo esc_attr( wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : '' ); ?>"><?php esc_html_e( 'Resubscribe', 'woocommerce-subscriptions' ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<p class="limited-subscription-notice notice"><?php esc_html_e( 'You have an active subscription to this product already.', 'woocommerce-subscriptions' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@ if (PHP_VERSION_ID < 50600) {
|
|||
echo $err;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException($err);
|
||||
trigger_error(
|
||||
$err,
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit32625eaf0064549a4f20b6231a37a93c::getLoader();
|
||||
return ComposerAutoloaderInitcb45de1ca955f89ec737c442c7cf101c::getLoader();
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
require_once __DIR__ . '/jetpack-autoloader/class-autoloader.php';
|
||||
Autoloader::init();
|
||||
|
|
@ -1,537 +0,0 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [5.0.10] - 2025-09-15
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.9] - 2025-07-28
|
||||
### Changed
|
||||
- Exclude development files from production build of the package. [#44456]
|
||||
|
||||
## [5.0.8] - 2025-06-23
|
||||
### Fixed
|
||||
- Autoloader: Prevent double slash in autoloader path. [#44030]
|
||||
|
||||
## [5.0.7] - 2025-04-28
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.6] - 2025-03-31
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.5] - 2025-03-21
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.4] - 2025-03-17
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.3] - 2025-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.2] - 2025-02-24
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [5.0.1] - 2025-01-20
|
||||
### Changed
|
||||
- Code: Use function-style exit() and die() with a default status code of 0. [#41167]
|
||||
|
||||
## [5.0.0] - 2024-11-25
|
||||
### Removed
|
||||
- Drop support for Composer <2.2. [#40297]
|
||||
- Remove support for WordPress 6.5 and earlier. [#40200]
|
||||
|
||||
## [4.0.0] - 2024-11-14
|
||||
### Removed
|
||||
- General: Update minimum PHP version to 7.2. [#40147]
|
||||
|
||||
## [3.1.3] - 2024-11-04
|
||||
### Added
|
||||
- Enable test coverage. [#39961]
|
||||
|
||||
## [3.1.2] - 2024-10-15
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.1.1] - 2024-10-10
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.1.0] - 2024-09-06
|
||||
### Added
|
||||
- Add logic for debugging issues caused by conflicting Composer autoloaders, enabled by setting the `JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS` constant. [#38995]
|
||||
- Add logic for debugging issues caused by early class loads, enabled by setting the `JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS` constant. [#38995]
|
||||
|
||||
## [3.0.10] - 2024-08-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#39004]
|
||||
|
||||
## [3.0.9] - 2024-07-10
|
||||
### Fixed
|
||||
- Avoid a deprecation notice in `Autoloader_Locator::find_latest_autoloader()`. [#38245]
|
||||
|
||||
## [3.0.8] - 2024-05-29
|
||||
### Fixed
|
||||
- `AutoloadGenerator::__construct` no longer pretends `$io` is nullable. That never worked. [#37608]
|
||||
|
||||
## [3.0.7] - 2024-05-06
|
||||
### Fixed
|
||||
- Avoid deprecation notices when plugin path is null. [#37174]
|
||||
|
||||
## [3.0.6] - 2024-04-22
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.5] - 2024-04-11
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.4] - 2024-03-18
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.3] - 2024-03-14
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.2] - 2023-11-21
|
||||
|
||||
## [3.0.1] - 2023-11-21
|
||||
|
||||
## [3.0.0] - 2023-11-20
|
||||
### Changed
|
||||
- Updated required PHP version to >= 7.0. [#34192]
|
||||
|
||||
## [2.12.0] - 2023-09-28
|
||||
### Added
|
||||
- Add an `AutoloadGenerator::VERSION` constant, and use that for the autoloader's version in preference to whatever Composer has. [#33156]
|
||||
|
||||
## [2.11.23] - 2023-09-19
|
||||
|
||||
- Minor internal updates.
|
||||
|
||||
## [2.11.22] - 2023-08-23
|
||||
### Changed
|
||||
- Updated package dependencies. [#32605]
|
||||
|
||||
## [2.11.21] - 2023-05-22
|
||||
### Added
|
||||
- Set keywords in `composer.json`. [#30756]
|
||||
|
||||
## [2.11.20] - 2023-05-11
|
||||
|
||||
- Updated package dependencies
|
||||
|
||||
## [2.11.19] - 2023-04-25
|
||||
### Fixed
|
||||
- Fix example in README [#30225]
|
||||
|
||||
## [2.11.18] - 2023-03-28
|
||||
### Changed
|
||||
- Minor internal updates.
|
||||
|
||||
## [2.11.17] - 2023-03-27
|
||||
### Fixed
|
||||
- Don't error when processing packages specifying missing PSR paths. [#29669]
|
||||
|
||||
## [2.11.16] - 2023-02-20
|
||||
### Changed
|
||||
- Minor internal updates.
|
||||
|
||||
## [2.11.15] - 2023-01-11
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.11.14] - 2022-12-19
|
||||
### Changed
|
||||
- Use `Composer\ClassMapGenerator\ClassMapGenerator` when available (i.e. with composer 2.4). [#27812]
|
||||
|
||||
### Fixed
|
||||
- Declare fields for PHP 8.2 compatibility. [#27949]
|
||||
|
||||
## [2.11.13] - 2022-12-02
|
||||
### Changed
|
||||
- Updated package dependencies. [#27688]
|
||||
|
||||
## [2.11.12] - 2022-11-22
|
||||
### Changed
|
||||
- Updated package dependencies. [#27043]
|
||||
|
||||
## [2.11.11] - 2022-10-25
|
||||
### Changed
|
||||
- Sort data in generated `vendor/composer/jetpack_autoload_classmap.php` to avoid spurious diffs. [#26929]
|
||||
|
||||
## [2.11.10] - 2022-10-05
|
||||
|
||||
- Tests: Clear `COMPOSER_AUTH` environment variable when running Composer for tests. [#26404]
|
||||
|
||||
## [2.11.9] - 2022-09-27
|
||||
### Fixed
|
||||
- Tests: Clear `COMPOSER_AUTH` environment variable when running Composer for tests. [#26404]
|
||||
|
||||
## [2.11.8] - 2022-09-20
|
||||
### Fixed
|
||||
- Tests: skip test if it requires a version of Composer not compatible with the running version of PHP. [#26143]
|
||||
|
||||
## [2.11.7] - 2022-07-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#25158]
|
||||
|
||||
## [2.11.6] - 2022-06-21
|
||||
### Changed
|
||||
- Renaming `master` to `trunk`.
|
||||
|
||||
## [2.11.5] - 2022-05-18
|
||||
### Fixed
|
||||
- Fix new PHPCS sniffs. [#24366]
|
||||
|
||||
## [2.11.4] - 2022-04-26
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.11.3] - 2022-04-19
|
||||
### Changed
|
||||
- PHPCS: Fix `WordPress.Security.ValidatedSanitizedInput`
|
||||
|
||||
## [2.11.2] - 2022-03-29
|
||||
### Changed
|
||||
- Microperformance: Use === null instead of is_null
|
||||
|
||||
## [2.11.1] - 2022-03-08
|
||||
### Removed
|
||||
- Removed the Upgrade Handler.
|
||||
|
||||
## [2.11.0] - 2022-03-08
|
||||
### Added
|
||||
- On plugin update, pre-load all (non-PSR-4) classes from the plugin to avoid mid-upgrade fatals.
|
||||
|
||||
## [2.10.13] - 2022-03-01
|
||||
### Fixed
|
||||
- Fix tests for upstream phpunit change.
|
||||
|
||||
## [2.10.12] - 2022-01-25
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.11] - 2022-01-04
|
||||
### Changed
|
||||
- Switch to pcov for code coverage.
|
||||
- Updated package dependencies
|
||||
|
||||
## [2.10.10] - 2021-11-16
|
||||
### Added
|
||||
- Soft return if autoloader chain is not available.
|
||||
|
||||
## [2.10.9] - 2021-11-02
|
||||
### Changed
|
||||
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
|
||||
|
||||
## [2.10.8] - 2021-10-13
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.7] - 2021-10-07
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
## [2.10.6] - 2021-09-28
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.5] - 2021-08-31
|
||||
### Changed
|
||||
- Run composer update on test-php command instead of phpunit
|
||||
- Tests: update PHPUnit polyfills dependency (yoast/phpunit-polyfills).
|
||||
|
||||
## [2.10.4] - 2021-08-10
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.3] - 2021-05-25
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.2] - 2021-04-27
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [2.10.1] - 2021-03-30
|
||||
### Added
|
||||
- Composer alias for dev-master, to improve dependencies
|
||||
- Tests: Added code coverage transformation
|
||||
|
||||
### Changed
|
||||
- Update package dependencies.
|
||||
|
||||
### Fixed
|
||||
- Fix coverage test
|
||||
- Fix uninstallation fatal
|
||||
- Update tests for changed composer 2.0.9 hash.
|
||||
- Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in.
|
||||
|
||||
## [2.10.0] - 2021-02-09
|
||||
|
||||
- Autoloader: test suite refactor
|
||||
|
||||
## [2.9.1] - 2021-02-05
|
||||
|
||||
- CI: Make tests more generic
|
||||
- Autoloader: stricter type-checking on WP functions
|
||||
- Autoloader: prevent transitive plugin execution
|
||||
|
||||
## [2.9.0] - 2021-01-25
|
||||
|
||||
- Autoloader: revised latest autoloader inclusion semantics
|
||||
- Add mirror-repo information to all current composer packages
|
||||
- Monorepo: Reorganize all projects
|
||||
- Autoloader: Don't cache deactivating plugins
|
||||
|
||||
## [2.8.0] - 2020-12-18
|
||||
|
||||
## [2.7.1] - 2020-12-18
|
||||
|
||||
- Autoloader: Added realpath resolution to plugin paths
|
||||
|
||||
## [2.7.0] - 2020-12-08
|
||||
|
||||
- Autoloader: Preemptively load unknown plugins from cache
|
||||
- Removed unwanted dot
|
||||
- Pin dependencies
|
||||
- Packages: Update for PHP 8 testing
|
||||
|
||||
## [2.6.0] - 2020-11-19
|
||||
|
||||
- Autoloader: AutoloadGenerator no longer extends Composer's AutoloadGenerator class
|
||||
- Autoloader: Reuse an existing autoloader suffix if available
|
||||
- Updated PHPCS: Packages and Debugger
|
||||
|
||||
## [2.5.0] - 2020-10-08
|
||||
|
||||
- Autoloader: remove the defined('JETPACK_AUTOLOAD_DEV') checks from the tests
|
||||
|
||||
## [2.4.0] - 2020-09-28
|
||||
|
||||
- Autoloader: remove the plugins_loaded bullet point from the README
|
||||
- Packages: avoid PHPCS warnings
|
||||
- Autoloader: add PSR-0 support
|
||||
- Autoloader: Detect filtering of active_plugins
|
||||
- Autoloader: Support unoptimized PSR-4
|
||||
|
||||
## [2.3.0] - 2020-08-21
|
||||
|
||||
- Autoloader: remove the plugin update hook
|
||||
|
||||
## [2.2.0] - 2020-08-14
|
||||
|
||||
- Autoloader: don't reset the autoloader version during plugin update
|
||||
- CI: Try collect js coverage
|
||||
|
||||
## [2.1.0] - 2020-07-27
|
||||
|
||||
- Autoloader: convert '\' directory separators to '/' in plugin paths
|
||||
- Autoloader: Avoid a PHP warning when an empty string is passed to `is_directory_plugin()`.
|
||||
- Autoloader: Tests: Use a string with define
|
||||
|
||||
## [2.0.2] - 2020-07-09
|
||||
|
||||
- Autoloader: Avoid a PHP warning when an empty string is passed to `is_directory_plugin()`.
|
||||
|
||||
## [2.0.1] - 2020-07-02
|
||||
|
||||
- Autoloader: Tests: Use a string with define
|
||||
|
||||
## [2.0.0] - 2020-06-29
|
||||
|
||||
## [2.0.0-beta] - 2020-06-29
|
||||
|
||||
- Autoloader: Support Composer v2.0
|
||||
- Autoloader: use paths to identify plugins instead of the directories
|
||||
- Autoloader: fix the fatal that occurs during plugin update
|
||||
- Autoloader: add fallback check for plugin path in mu-plugins
|
||||
- Autoloader: use JETPACK__PLUGIN_DIR when looking for the jetpack plugin directory.
|
||||
- Feature Branch: Update the Autoloader
|
||||
- PHPCS: Clean up the packages
|
||||
- PHPCS Updates after WPCS 2.3
|
||||
|
||||
## [1.7.0] - 2020-04-23
|
||||
|
||||
- Jetpack: Move comment notification override back to the constructor
|
||||
|
||||
## [1.6.0] - 2020-03-26
|
||||
|
||||
- Autoloader: Remove file check to improve performance.
|
||||
|
||||
## [1.5.0] - 2020-02-25
|
||||
|
||||
- Jetpack: instantiate manager object if it's null
|
||||
|
||||
## [1.4.1] - 2020-02-14
|
||||
|
||||
- Autoloader: Load only latest version of autoload files to avoid conflicts.
|
||||
|
||||
## [1.4.0] - 2020-01-23
|
||||
|
||||
- Autoloader: Remove the ignored classes
|
||||
|
||||
## [1.3.8] - 2020-01-14
|
||||
|
||||
- Trying to add deterministic initialization.
|
||||
- Autoloader: Remove Manager_Interface and Plugin\Tracking from ignored list
|
||||
- Autoloader: Remove Jetpack_IXR_Client from ignore list
|
||||
|
||||
## [1.3.7] - 2019-12-10
|
||||
|
||||
## [1.3.6] - 2019-12-09
|
||||
|
||||
- Autoloader: Use long-form sytax for array
|
||||
|
||||
## [1.3.5] - 2019-11-26
|
||||
|
||||
- Fix/php notice status
|
||||
|
||||
## [1.3.4] - 2019-11-08
|
||||
|
||||
- Deprecate Jetpack::is_development_mode() in favor of the packaged Status()->is_development_mode()
|
||||
|
||||
## [1.3.3] - 2019-10-28
|
||||
|
||||
- Packages: Add gitattributes files to all packages that need th…
|
||||
|
||||
## [1.3.2] - 2019-09-24
|
||||
|
||||
- Autoloader: Cover scenarios where composer/autoload_files.php…
|
||||
|
||||
## [1.3.1] - 2019-09-20
|
||||
|
||||
- Docs: Unify usage of @package phpdoc tags
|
||||
|
||||
## [1.3.0] - 2019-09-14
|
||||
|
||||
- Fix for empty namespaces. #13459
|
||||
- Connection: Move the Jetpack IXR client to the package
|
||||
- Adds full connection cycle capability to the Connection package.
|
||||
- Jetpack 7.5: Back compatibility package
|
||||
|
||||
## [1.2.0] - 2019-06-24
|
||||
|
||||
- Jetpack DNA: Add full classmap support to Autoloader
|
||||
- Move Jetpack_Sync_Main from legacy to PSR-4
|
||||
|
||||
## [1.1.0] - 2019-06-19
|
||||
|
||||
- Packages: Move autoloader tests to the package
|
||||
- DNA: Move Jetpack Usage tracking to its own file
|
||||
- Jetpack DNA: More isolation of Tracks Package
|
||||
- Autoloader: Ignore XMLRPC_Connector if called too early
|
||||
- Autoloader: Ignore Jetpack_Signature if called too early
|
||||
|
||||
## 1.0.0 - 2019-06-11
|
||||
|
||||
- Add Custom Autoloader
|
||||
|
||||
[5.0.10]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.9...v5.0.10
|
||||
[5.0.9]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.8...v5.0.9
|
||||
[5.0.8]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.7...v5.0.8
|
||||
[5.0.7]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.6...v5.0.7
|
||||
[5.0.6]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.5...v5.0.6
|
||||
[5.0.5]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.4...v5.0.5
|
||||
[5.0.4]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.3...v5.0.4
|
||||
[5.0.3]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.2...v5.0.3
|
||||
[5.0.2]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.1...v5.0.2
|
||||
[5.0.1]: https://github.com/Automattic/jetpack-autoloader/compare/v5.0.0...v5.0.1
|
||||
[5.0.0]: https://github.com/Automattic/jetpack-autoloader/compare/v4.0.0...v5.0.0
|
||||
[4.0.0]: https://github.com/Automattic/jetpack-autoloader/compare/v3.1.3...v4.0.0
|
||||
[3.1.3]: https://github.com/Automattic/jetpack-autoloader/compare/v3.1.2...v3.1.3
|
||||
[3.1.2]: https://github.com/Automattic/jetpack-autoloader/compare/v3.1.1...v3.1.2
|
||||
[3.1.1]: https://github.com/Automattic/jetpack-autoloader/compare/v3.1.0...v3.1.1
|
||||
[3.1.0]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.10...v3.1.0
|
||||
[3.0.10]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.9...v3.0.10
|
||||
[3.0.9]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.8...v3.0.9
|
||||
[3.0.8]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.7...v3.0.8
|
||||
[3.0.7]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.6...v3.0.7
|
||||
[3.0.6]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.5...v3.0.6
|
||||
[3.0.5]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.4...v3.0.5
|
||||
[3.0.4]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.3...v3.0.4
|
||||
[3.0.3]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.2...v3.0.3
|
||||
[3.0.2]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.1...v3.0.2
|
||||
[3.0.1]: https://github.com/Automattic/jetpack-autoloader/compare/v3.0.0...v3.0.1
|
||||
[3.0.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.12.0...v3.0.0
|
||||
[2.12.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.23...v2.12.0
|
||||
[2.11.23]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.22...v2.11.23
|
||||
[2.11.22]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.21...v2.11.22
|
||||
[2.11.21]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.20...v2.11.21
|
||||
[2.11.20]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.19...v2.11.20
|
||||
[2.11.19]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.18...v2.11.19
|
||||
[2.11.18]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.17...v2.11.18
|
||||
[2.11.17]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.16...v2.11.17
|
||||
[2.11.16]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.15...v2.11.16
|
||||
[2.11.15]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.14...v2.11.15
|
||||
[2.11.14]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.13...v2.11.14
|
||||
[2.11.13]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.12...v2.11.13
|
||||
[2.11.12]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.11...v2.11.12
|
||||
[2.11.11]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.10...v2.11.11
|
||||
[2.11.10]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.9...v2.11.10
|
||||
[2.11.9]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.8...v2.11.9
|
||||
[2.11.8]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.7...v2.11.8
|
||||
[2.11.7]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.6...v2.11.7
|
||||
[2.11.6]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.5...v2.11.6
|
||||
[2.11.5]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.4...v2.11.5
|
||||
[2.11.4]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.3...v2.11.4
|
||||
[2.11.3]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.2...v2.11.3
|
||||
[2.11.2]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.1...v2.11.2
|
||||
[2.11.1]: https://github.com/Automattic/jetpack-autoloader/compare/v2.11.0...v2.11.1
|
||||
[2.11.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.13...v2.11.0
|
||||
[2.10.13]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.12...v2.10.13
|
||||
[2.10.12]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.11...v2.10.12
|
||||
[2.10.11]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.10...v2.10.11
|
||||
[2.10.10]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.9...v2.10.10
|
||||
[2.10.9]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.8...v2.10.9
|
||||
[2.10.8]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.7...v2.10.8
|
||||
[2.10.7]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.6...v2.10.7
|
||||
[2.10.6]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.5...v2.10.6
|
||||
[2.10.5]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.4...v2.10.5
|
||||
[2.10.4]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.3...v2.10.4
|
||||
[2.10.3]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.2...v2.10.3
|
||||
[2.10.2]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.1...v2.10.2
|
||||
[2.10.1]: https://github.com/Automattic/jetpack-autoloader/compare/v2.10.0...v2.10.1
|
||||
[2.10.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.9.1...v2.10.0
|
||||
[2.9.1]: https://github.com/Automattic/jetpack-autoloader/compare/v2.9.0...v2.9.1
|
||||
[2.9.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.8.0...v2.9.0
|
||||
[2.8.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.7.1...v2.8.0
|
||||
[2.7.1]: https://github.com/Automattic/jetpack-autoloader/compare/v2.7.0...v2.7.1
|
||||
[2.7.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.6.0...v2.7.0
|
||||
[2.6.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.5.0...v2.6.0
|
||||
[2.5.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.4.0...v2.5.0
|
||||
[2.4.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.3.0...v2.4.0
|
||||
[2.3.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.2.0...v2.3.0
|
||||
[2.2.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.1.0...v2.2.0
|
||||
[2.1.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.0.2...v2.1.0
|
||||
[2.0.2]: https://github.com/Automattic/jetpack-autoloader/compare/v2.0.1...v2.0.2
|
||||
[2.0.1]: https://github.com/Automattic/jetpack-autoloader/compare/v2.0.0...v2.0.1
|
||||
[2.0.0]: https://github.com/Automattic/jetpack-autoloader/compare/v2.0.0-beta...v2.0.0
|
||||
[2.0.0-beta]: https://github.com/Automattic/jetpack-autoloader/compare/v1.7.0...v2.0.0-beta
|
||||
[1.7.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.6.0...v1.7.0
|
||||
[1.6.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.5.0...v1.6.0
|
||||
[1.5.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.4.1...v1.5.0
|
||||
[1.4.1]: https://github.com/Automattic/jetpack-autoloader/compare/v1.4.0...v1.4.1
|
||||
[1.4.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.8...v1.4.0
|
||||
[1.3.8]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.7...v1.3.8
|
||||
[1.3.7]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.6...v1.3.7
|
||||
[1.3.6]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.5...v1.3.6
|
||||
[1.3.5]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.4...v1.3.5
|
||||
[1.3.4]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.3...v1.3.4
|
||||
[1.3.3]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.2...v1.3.3
|
||||
[1.3.2]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.1...v1.3.2
|
||||
[1.3.1]: https://github.com/Automattic/jetpack-autoloader/compare/v1.3.0...v1.3.1
|
||||
[1.3.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.1.0...v1.2.0
|
||||
[1.1.0]: https://github.com/Automattic/jetpack-autoloader/compare/v1.0.0...v1.1.0
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
A custom autoloader for Composer
|
||||
=====================================
|
||||
|
||||
This is a custom autoloader generator that uses a classmap to always load the latest version of a class.
|
||||
|
||||
The problem this autoloader is trying to solve is conflicts that arise when two or more plugins use the same package, but one of the plugins uses an older version of said package.
|
||||
|
||||
This is solved by keeping an in memory map of all the different classes that can be loaded, and updating the map with the path to the latest version of the package for the autoloader to find when we instantiate the class.
|
||||
|
||||
It diverges from the default Composer autoloader setup in the following ways:
|
||||
|
||||
* It creates `jetpack_autoload_classmap.php` and `jetpack_autoload_filemap.php` files in the `vendor/composer` directory.
|
||||
* This file includes the version numbers from each package that is used.
|
||||
* The autoloader will only load the latest version of the package no matter what plugin loads the package. This behavior is guaranteed only when every plugin that uses the package uses this autoloader. If any plugin that requires the package uses a different autoloader, this autoloader may not be able to control which version of the package is loaded.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
In your project's `composer.json`, add the following lines:
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"automattic/jetpack-autoloader": "^2"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Your project must use the default composer vendor directory, `vendor`.
|
||||
|
||||
After the next update/install, you will have a `vendor/autoload_packages.php` file.
|
||||
Load the file in your plugin via main plugin file.
|
||||
|
||||
In the main plugin you will also need to include the files like this.
|
||||
```php
|
||||
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload_packages.php';
|
||||
```
|
||||
|
||||
Working with Development Versions of Packages
|
||||
-----
|
||||
|
||||
The autoloader will attempt to use the package with the latest semantic version.
|
||||
|
||||
During development, you can force the autoloader to use development package versions by setting the `JETPACK_AUTOLOAD_DEV` constant to true. When `JETPACK_AUTOLOAD_DEV` is true, the autoloader will prefer the following versions over semantic versions:
|
||||
- `9999999-dev`
|
||||
- Versions with a `dev-` prefix.
|
||||
|
||||
|
||||
Autoloader Limitations and Caveats
|
||||
-----
|
||||
|
||||
### Plugin Updates
|
||||
|
||||
When moving a package class file, renaming a package class file, or changing a package class namespace, make sure that the class will not be loaded after a plugin update.
|
||||
|
||||
The autoloader builds the in memory classmap as soon as the autoloader is loaded. The package class file paths in the map are not updated after a plugin update. If a plugins's package class files are moved during a plugin update and a moved file is autoloaded after the update, an error will occur.
|
||||
|
||||
### Moving classes to a different package
|
||||
|
||||
Jetpack Autoloader determines the hierarchy of class versions by package version numbers. It can cause problems if a class is moved to a newer package with a lower version number, it will get overshadowed by the old package.
|
||||
|
||||
For instance, if your newer version of a class comes from a new package versioned 0.1.0, and the older version comes from a different package with a greater version number 2.0.1, the newer class will not get loaded.
|
||||
|
||||
### Jetpack Autoloader uses transient cache
|
||||
|
||||
This is a caveat to be aware of when dealing with issues. The JP Autoloader uses transients to cache a list of available plugins to speed up the lookup process. This can sometimes mask problems that arise when loading code too early. See the [Debugging](#debugging) section for more information on how to detect situations like this.
|
||||
|
||||
Debugging
|
||||
-----
|
||||
|
||||
A common cause of confusing errors is when a plugin autoloads classes during the plugin load, before the 'plugins_loaded' hook. If that plugin has an older version of the class, that older version may be loaded before a plugin providing the newer version of the class has a chance to register. Even more confusingly, this will likely be intermittent, only showing up when the autoloader's plugin cache is invalidated. To debug this situation, you can set the `JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS` constant to true.
|
||||
|
||||
Another common cause of confusing errors is when a plugin registers its own autoloader at a higher priority than the Jetpack Autoloader, and that autoloader would load packages that should be handled by the Jetpack Autoloader. Setting the `JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS` constant to true will check for standard Composer autoloaders with such a conflict.
|
||||
|
||||
|
||||
Autoloading Standards
|
||||
----
|
||||
|
||||
All new Jetpack package development should use classmap autoloading, which allows the class and file names to comply with the WordPress Coding Standards.
|
||||
|
||||
### Optimized Autoloader
|
||||
|
||||
An optimized autoloader is generated when:
|
||||
* `composer install` or `composer update` is called with `-o` or `--optimize-autoloader`
|
||||
* `composer dump-autoload` is called with `-o` or `--optimize`
|
||||
|
||||
PSR-4 and PSR-0 namespaces are converted to classmaps.
|
||||
|
||||
### Unoptimized Autoloader
|
||||
|
||||
Supports PSR-4 autoloading. PSR-0 namespaces are converted to classmaps.
|
||||
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Autoloader file writer.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
|
||||
/**
|
||||
* Class AutoloadFileWriter.
|
||||
*/
|
||||
class AutoloadFileWriter {
|
||||
|
||||
/**
|
||||
* The file comment to use.
|
||||
*/
|
||||
const COMMENT = <<<AUTOLOADER_COMMENT
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
AUTOLOADER_COMMENT;
|
||||
|
||||
/**
|
||||
* Copies autoloader files and replaces any placeholders in them.
|
||||
*
|
||||
* @param IOInterface|null $io An IO for writing to.
|
||||
* @param string $outDir The directory to place the autoloader files in.
|
||||
* @param string $suffix The suffix to use in the autoloader's namespace.
|
||||
*/
|
||||
public static function copyAutoloaderFiles( $io, $outDir, $suffix ) {
|
||||
$renameList = array(
|
||||
'autoload.php' => '../autoload_packages.php',
|
||||
);
|
||||
$ignoreList = array(
|
||||
'AutoloadGenerator.php',
|
||||
'AutoloadProcessor.php',
|
||||
'CustomAutoloaderPlugin.php',
|
||||
'ManifestGenerator.php',
|
||||
'AutoloadFileWriter.php',
|
||||
);
|
||||
|
||||
// Copy all of the autoloader files.
|
||||
$files = scandir( __DIR__ );
|
||||
foreach ( $files as $file ) {
|
||||
// Only PHP files will be copied.
|
||||
if ( substr( $file, -4 ) !== '.php' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( in_array( $file, $ignoreList, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newFile = $renameList[ $file ] ?? $file;
|
||||
$content = self::prepareAutoloaderFile( $file, $suffix );
|
||||
|
||||
$written = file_put_contents( $outDir . '/' . $newFile, $content );
|
||||
if ( $io ) {
|
||||
if ( $written ) {
|
||||
$io->writeError( " <info>Generated: $newFile</info>" );
|
||||
} else {
|
||||
$io->writeError( " <error>Error: $newFile</error>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an autoloader file to be written to the destination.
|
||||
*
|
||||
* @param String $filename a file to prepare.
|
||||
* @param String $suffix Unique suffix used in the namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function prepareAutoloaderFile( $filename, $suffix ) {
|
||||
$header = self::COMMENT;
|
||||
$header .= PHP_EOL;
|
||||
if ( $suffix === 'Current' ) {
|
||||
// Unit testing.
|
||||
$header .= 'namespace Automattic\Jetpack\Autoloader\jpCurrent;';
|
||||
} else {
|
||||
$header .= 'namespace Automattic\Jetpack\Autoloader\jp' . $suffix . '\al' . preg_replace( '/[^0-9a-zA-Z]/', '_', AutoloadGenerator::VERSION ) . ';';
|
||||
}
|
||||
$header .= PHP_EOL . PHP_EOL;
|
||||
|
||||
$sourceLoader = fopen( __DIR__ . '/' . $filename, 'r' );
|
||||
$file_contents = stream_get_contents( $sourceLoader );
|
||||
return str_replace(
|
||||
'/* HEADER */',
|
||||
$header,
|
||||
$file_contents
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,403 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Autoloader Generator.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader;
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\Config;
|
||||
use Composer\Installer\InstallationManager;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Repository\InstalledRepositoryInterface;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\Util\PackageSorter;
|
||||
|
||||
/**
|
||||
* Class AutoloadGenerator.
|
||||
*/
|
||||
class AutoloadGenerator {
|
||||
|
||||
const VERSION = '5.0.10';
|
||||
|
||||
/**
|
||||
* IO object.
|
||||
*
|
||||
* @var IOInterface IO object.
|
||||
*/
|
||||
private $io;
|
||||
|
||||
/**
|
||||
* The filesystem utility.
|
||||
*
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $filesystem;
|
||||
|
||||
/**
|
||||
* Instantiate an AutoloadGenerator object.
|
||||
*
|
||||
* @param IOInterface $io IO object.
|
||||
*/
|
||||
public function __construct( IOInterface $io ) {
|
||||
$this->io = $io;
|
||||
$this->filesystem = new Filesystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump the Jetpack autoloader files.
|
||||
*
|
||||
* @param Composer $composer The Composer object.
|
||||
* @param Config $config Config object.
|
||||
* @param InstalledRepositoryInterface $localRepo Installed Repository object.
|
||||
* @param PackageInterface $mainPackage Main Package object.
|
||||
* @param InstallationManager $installationManager Manager for installing packages.
|
||||
* @param string $targetDir Path to the current target directory.
|
||||
* @param bool $scanPsrPackages Whether or not PSR packages should be converted to a classmap.
|
||||
* @param string $suffix The autoloader suffix.
|
||||
*/
|
||||
public function dump(
|
||||
Composer $composer,
|
||||
Config $config,
|
||||
InstalledRepositoryInterface $localRepo,
|
||||
PackageInterface $mainPackage,
|
||||
InstallationManager $installationManager,
|
||||
$targetDir,
|
||||
$scanPsrPackages = false,
|
||||
$suffix = null
|
||||
) {
|
||||
$this->filesystem->ensureDirectoryExists( $config->get( 'vendor-dir' ) );
|
||||
|
||||
$packageMap = $composer->getAutoloadGenerator()->buildPackageMap( $installationManager, $mainPackage, $localRepo->getCanonicalPackages() );
|
||||
$autoloads = $this->parseAutoloads( $packageMap, $mainPackage );
|
||||
|
||||
// Convert the autoloads into a format that the manifest generator can consume more easily.
|
||||
$basePath = $this->filesystem->normalizePath( realpath( getcwd() ) );
|
||||
$vendorPath = $this->filesystem->normalizePath( realpath( $config->get( 'vendor-dir' ) ) );
|
||||
$processedAutoloads = $this->processAutoloads( $autoloads, $scanPsrPackages, $vendorPath, $basePath );
|
||||
unset( $packageMap, $autoloads );
|
||||
|
||||
// Make sure none of the legacy files remain that can lead to problems with the autoloader.
|
||||
$this->removeLegacyFiles( $vendorPath );
|
||||
|
||||
// Write all of the files now that we're done.
|
||||
$this->writeAutoloaderFiles( $vendorPath . '/jetpack-autoloader/', $suffix );
|
||||
$this->writeManifests( $vendorPath . '/' . $targetDir, $processedAutoloads );
|
||||
|
||||
if ( ! $scanPsrPackages ) {
|
||||
$this->io->writeError( '<warning>You are generating an unoptimized autoloader. If this is a production build, consider using the -o option.</warning>' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an ordered list of namespace => path mappings
|
||||
*
|
||||
* @param array $packageMap Array of array(package, installDir-relative-to-composer.json).
|
||||
* @param PackageInterface $mainPackage Main package instance.
|
||||
*
|
||||
* @return array The list of path mappings.
|
||||
*/
|
||||
public function parseAutoloads( array $packageMap, PackageInterface $mainPackage ) {
|
||||
$rootPackageMap = array_shift( $packageMap );
|
||||
|
||||
$sortedPackageMap = $this->sortPackageMap( $packageMap );
|
||||
$sortedPackageMap[] = $rootPackageMap;
|
||||
array_unshift( $packageMap, $rootPackageMap );
|
||||
|
||||
$psr0 = $this->parseAutoloadsType( $packageMap, 'psr-0', $mainPackage );
|
||||
$psr4 = $this->parseAutoloadsType( $packageMap, 'psr-4', $mainPackage );
|
||||
$classmap = $this->parseAutoloadsType( array_reverse( $sortedPackageMap ), 'classmap', $mainPackage );
|
||||
$files = $this->parseAutoloadsType( $sortedPackageMap, 'files', $mainPackage );
|
||||
|
||||
krsort( $psr0 );
|
||||
krsort( $psr4 );
|
||||
|
||||
return array(
|
||||
'psr-0' => $psr0,
|
||||
'psr-4' => $psr4,
|
||||
'classmap' => $classmap,
|
||||
'files' => $files,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts packages by dependency weight
|
||||
*
|
||||
* Packages of equal weight retain the original order
|
||||
*
|
||||
* @param array $packageMap The package map.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function sortPackageMap( array $packageMap ) {
|
||||
$packages = array();
|
||||
$paths = array();
|
||||
|
||||
foreach ( $packageMap as $item ) {
|
||||
list( $package, $path ) = $item;
|
||||
$name = $package->getName();
|
||||
$packages[ $name ] = $package;
|
||||
$paths[ $name ] = $path;
|
||||
}
|
||||
|
||||
$sortedPackages = PackageSorter::sortPackages( $packages );
|
||||
|
||||
$sortedPackageMap = array();
|
||||
|
||||
foreach ( $sortedPackages as $package ) {
|
||||
$name = $package->getName();
|
||||
$sortedPackageMap[] = array( $packages[ $name ], $paths[ $name ] );
|
||||
}
|
||||
|
||||
return $sortedPackageMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file identifier.
|
||||
*
|
||||
* @param PackageInterface $package The package instance.
|
||||
* @param string $path The path.
|
||||
*/
|
||||
protected function getFileIdentifier( PackageInterface $package, $path ) {
|
||||
return md5( $package->getName() . ':' . $path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path code for the given path.
|
||||
*
|
||||
* @param Filesystem $filesystem The filesystem instance.
|
||||
* @param string $basePath The base path.
|
||||
* @param string $vendorPath The vendor path.
|
||||
* @param string $path The path.
|
||||
*
|
||||
* @return string The path code.
|
||||
*/
|
||||
protected function getPathCode( Filesystem $filesystem, $basePath, $vendorPath, $path ) {
|
||||
if ( ! $filesystem->isAbsolutePath( $path ) ) {
|
||||
$path = $basePath . '/' . $path;
|
||||
}
|
||||
$path = $filesystem->normalizePath( $path );
|
||||
|
||||
$baseDir = '';
|
||||
if ( 0 === strpos( $path . '/', $vendorPath . '/' ) ) {
|
||||
$path = substr( $path, strlen( $vendorPath ) );
|
||||
$baseDir = '$vendorDir';
|
||||
|
||||
if ( false !== $path ) {
|
||||
$baseDir .= ' . ';
|
||||
}
|
||||
} else {
|
||||
$path = $filesystem->normalizePath( $filesystem->findShortestPath( $basePath, $path, true ) );
|
||||
if ( ! $filesystem->isAbsolutePath( $path ) ) {
|
||||
$baseDir = '$baseDir . ';
|
||||
$path = '/' . $path;
|
||||
}
|
||||
}
|
||||
|
||||
if ( strpos( $path, '.phar' ) !== false ) {
|
||||
$baseDir = "'phar://' . " . $baseDir;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
|
||||
return $baseDir . ( ( false !== $path ) ? var_export( $path, true ) : '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* This function differs from the composer parseAutoloadsType in that beside returning the path.
|
||||
* It also return the path and the version of a package.
|
||||
*
|
||||
* Supports PSR-4, PSR-0, and classmap parsing.
|
||||
*
|
||||
* @param array $packageMap Map of all the packages.
|
||||
* @param string $type Type of autoloader to use.
|
||||
* @param PackageInterface $mainPackage Instance of the Package Object.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function parseAutoloadsType( array $packageMap, $type, PackageInterface $mainPackage ) {
|
||||
$autoloads = array();
|
||||
|
||||
foreach ( $packageMap as $item ) {
|
||||
list($package, $installPath) = $item;
|
||||
$autoload = $package->getAutoload();
|
||||
$version = $package->getVersion(); // Version of the class comes from the package - should we try to parse it?
|
||||
|
||||
// Store our own actual package version, not "dev-trunk" or whatever.
|
||||
if ( $package->getName() === 'automattic/jetpack-autoloader' ) {
|
||||
$version = self::VERSION;
|
||||
}
|
||||
|
||||
if ( $package === $mainPackage ) {
|
||||
$autoload = array_merge_recursive( $autoload, $package->getDevAutoload() );
|
||||
}
|
||||
|
||||
if ( null !== $package->getTargetDir() && $package !== $mainPackage ) {
|
||||
$installPath = substr( $installPath, 0, -strlen( '/' . $package->getTargetDir() ) );
|
||||
}
|
||||
|
||||
if ( in_array( $type, array( 'psr-4', 'psr-0' ), true ) && isset( $autoload[ $type ] ) && is_array( $autoload[ $type ] ) ) {
|
||||
foreach ( $autoload[ $type ] as $namespace => $paths ) {
|
||||
$paths = is_array( $paths ) ? $paths : array( $paths );
|
||||
foreach ( $paths as $path ) {
|
||||
$relativePath = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
|
||||
$autoloads[ $namespace ][] = array(
|
||||
'path' => $relativePath,
|
||||
'version' => $version,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'classmap' === $type && isset( $autoload['classmap'] ) && is_array( $autoload['classmap'] ) ) {
|
||||
foreach ( $autoload['classmap'] as $paths ) {
|
||||
$paths = is_array( $paths ) ? $paths : array( $paths );
|
||||
foreach ( $paths as $path ) {
|
||||
$relativePath = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
|
||||
$autoloads[] = array(
|
||||
'path' => $relativePath,
|
||||
'version' => $version,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( 'files' === $type && isset( $autoload['files'] ) && is_array( $autoload['files'] ) ) {
|
||||
foreach ( $autoload['files'] as $paths ) {
|
||||
$paths = is_array( $paths ) ? $paths : array( $paths );
|
||||
foreach ( $paths as $path ) {
|
||||
$relativePath = empty( $installPath ) ? ( empty( $path ) ? '.' : $path ) : $installPath . '/' . $path;
|
||||
$autoloads[ $this->getFileIdentifier( $package, $path ) ] = array(
|
||||
'path' => $relativePath,
|
||||
'version' => $version,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $autoloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given Composer's autoloads this will convert them to a version that we can use to generate the manifests.
|
||||
*
|
||||
* When the $scanPsrPackages argument is true, PSR-4 namespaces are converted to classmaps. When $scanPsrPackages
|
||||
* is false, PSR-4 namespaces are not converted to classmaps.
|
||||
*
|
||||
* PSR-0 namespaces are always converted to classmaps.
|
||||
*
|
||||
* @param array $autoloads The autoloads we want to process.
|
||||
* @param bool $scanPsrPackages Whether or not PSR-4 packages should be converted to a classmap.
|
||||
* @param string $vendorPath The path to the vendor directory.
|
||||
* @param string $basePath The path to the current directory.
|
||||
*
|
||||
* @return array $processedAutoloads
|
||||
*/
|
||||
private function processAutoloads( $autoloads, $scanPsrPackages, $vendorPath, $basePath ) {
|
||||
$processor = new AutoloadProcessor(
|
||||
function ( $path, $excludedClasses, $namespace ) use ( $basePath ) {
|
||||
$dir = $this->filesystem->normalizePath(
|
||||
$this->filesystem->isAbsolutePath( $path ) ? $path : $basePath . '/' . $path
|
||||
);
|
||||
|
||||
// Composer 2.4 changed the name of the class.
|
||||
if ( class_exists( \Composer\ClassMapGenerator\ClassMapGenerator::class ) ) {
|
||||
if ( ! is_dir( $dir ) && ! is_file( $dir ) ) {
|
||||
return array();
|
||||
}
|
||||
$generator = new \Composer\ClassMapGenerator\ClassMapGenerator();
|
||||
$generator->scanPaths( $dir, $excludedClasses, 'classmap', empty( $namespace ) ? null : $namespace );
|
||||
return $generator->getClassMap()->getMap();
|
||||
}
|
||||
|
||||
return \Composer\Autoload\ClassMapGenerator::createMap(
|
||||
$dir,
|
||||
$excludedClasses,
|
||||
null, // Don't pass the IOInterface since the normal autoload generation will have reported already.
|
||||
empty( $namespace ) ? null : $namespace
|
||||
);
|
||||
},
|
||||
function ( $path ) use ( $basePath, $vendorPath ) {
|
||||
return $this->getPathCode( $this->filesystem, $basePath, $vendorPath, $path );
|
||||
}
|
||||
);
|
||||
|
||||
return array(
|
||||
'psr-4' => $processor->processPsr4Packages( $autoloads, $scanPsrPackages ),
|
||||
'classmap' => $processor->processClassmap( $autoloads, $scanPsrPackages ),
|
||||
'files' => $processor->processFiles( $autoloads ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the legacy autoloader files so they don't cause any problems.
|
||||
*
|
||||
* @param string $outDir The directory legacy files are written to.
|
||||
*/
|
||||
private function removeLegacyFiles( $outDir ) {
|
||||
$files = array(
|
||||
'autoload_functions.php',
|
||||
'class-autoloader-handler.php',
|
||||
'class-classes-handler.php',
|
||||
'class-files-handler.php',
|
||||
'class-plugins-handler.php',
|
||||
'class-version-selector.php',
|
||||
);
|
||||
foreach ( $files as $file ) {
|
||||
$this->filesystem->remove( $outDir . '/' . $file );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all of the autoloader files to disk.
|
||||
*
|
||||
* @param string $outDir The directory to write to.
|
||||
* @param string $suffix The unique autoloader suffix.
|
||||
*/
|
||||
private function writeAutoloaderFiles( $outDir, $suffix ) {
|
||||
$this->io->writeError( "<info>Generating jetpack autoloader ($outDir)</info>" );
|
||||
|
||||
// We will remove all autoloader files to generate this again.
|
||||
$this->filesystem->emptyDirectory( $outDir );
|
||||
|
||||
// Write the autoloader files.
|
||||
AutoloadFileWriter::copyAutoloaderFiles( $this->io, $outDir, $suffix );
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all of the manifest files to disk.
|
||||
*
|
||||
* @param string $outDir The directory to write to.
|
||||
* @param array $processedAutoloads The processed autoloads.
|
||||
*/
|
||||
private function writeManifests( $outDir, $processedAutoloads ) {
|
||||
$this->io->writeError( "<info>Generating jetpack autoloader manifests ($outDir)</info>" );
|
||||
|
||||
$manifestFiles = array(
|
||||
'classmap' => 'jetpack_autoload_classmap.php',
|
||||
'psr-4' => 'jetpack_autoload_psr4.php',
|
||||
'files' => 'jetpack_autoload_filemap.php',
|
||||
);
|
||||
|
||||
foreach ( $manifestFiles as $key => $file ) {
|
||||
// Make sure the file doesn't exist so it isn't there if we don't write it.
|
||||
$this->filesystem->remove( $outDir . '/' . $file );
|
||||
if ( empty( $processedAutoloads[ $key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = ManifestGenerator::buildManifest( $key, $file, $processedAutoloads[ $key ] );
|
||||
if ( empty( $content ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( file_put_contents( $outDir . '/' . $file, $content ) ) {
|
||||
$this->io->writeError( " <info>Generated: $file</info>" );
|
||||
} else {
|
||||
$this->io->writeError( " <error>Error: $file</error>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Autoload Processor.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader;
|
||||
|
||||
/**
|
||||
* Class AutoloadProcessor.
|
||||
*/
|
||||
class AutoloadProcessor {
|
||||
|
||||
/**
|
||||
* A callable for scanning a directory for all of its classes.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private $classmapScanner;
|
||||
|
||||
/**
|
||||
* A callable for transforming a path into one to be used in code.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private $pathCodeTransformer;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param callable $classmapScanner A callable for scanning a directory for all of its classes.
|
||||
* @param callable $pathCodeTransformer A callable for transforming a path into one to be used in code.
|
||||
*/
|
||||
public function __construct( $classmapScanner, $pathCodeTransformer ) {
|
||||
$this->classmapScanner = $classmapScanner;
|
||||
$this->pathCodeTransformer = $pathCodeTransformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the classmap autoloads into a relative path format including the version for each file.
|
||||
*
|
||||
* @param array $autoloads The autoloads we are processing.
|
||||
* @param bool $scanPsrPackages Whether or not PSR packages should be converted to a classmap.
|
||||
*
|
||||
* @return array|null $processed
|
||||
* @phan-param array{classmap:?array{path:string,version:string}[],psr-4:?array<string,array{path:string,version:string}[]>,psr-0:?array<string,array{path:string,version:string}[]>} $autoloads
|
||||
*/
|
||||
public function processClassmap( $autoloads, $scanPsrPackages ) {
|
||||
// We can't scan PSR packages if we don't actually have any.
|
||||
if ( empty( $autoloads['psr-4'] ) ) {
|
||||
$scanPsrPackages = false;
|
||||
}
|
||||
|
||||
if ( empty( $autoloads['classmap'] ) && ! $scanPsrPackages ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$excludedClasses = null;
|
||||
if ( ! empty( $autoloads['exclude-from-classmap'] ) ) {
|
||||
$excludedClasses = '{(' . implode( '|', $autoloads['exclude-from-classmap'] ) . ')}';
|
||||
}
|
||||
|
||||
$processed = array();
|
||||
|
||||
if ( $scanPsrPackages ) {
|
||||
foreach ( $autoloads['psr-4'] as $namespace => $sources ) {
|
||||
$namespace = empty( $namespace ) ? null : $namespace;
|
||||
|
||||
foreach ( $sources as $source ) {
|
||||
$classmap = call_user_func( $this->classmapScanner, $source['path'], $excludedClasses, $namespace );
|
||||
|
||||
foreach ( $classmap as $class => $path ) {
|
||||
$processed[ $class ] = array(
|
||||
'version' => $source['version'],
|
||||
'path' => call_user_func( $this->pathCodeTransformer, $path ),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PSR-0 namespaces are converted to classmaps for both optimized and unoptimized autoloaders because any new
|
||||
* development should use classmap or PSR-4 autoloading.
|
||||
*/
|
||||
if ( ! empty( $autoloads['psr-0'] ) ) {
|
||||
foreach ( $autoloads['psr-0'] as $namespace => $sources ) {
|
||||
$namespace = empty( $namespace ) ? null : $namespace;
|
||||
|
||||
foreach ( $sources as $source ) {
|
||||
$classmap = call_user_func( $this->classmapScanner, $source['path'], $excludedClasses, $namespace );
|
||||
foreach ( $classmap as $class => $path ) {
|
||||
$processed[ $class ] = array(
|
||||
'version' => $source['version'],
|
||||
'path' => call_user_func( $this->pathCodeTransformer, $path ),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $autoloads['classmap'] ) ) {
|
||||
foreach ( $autoloads['classmap'] as $package ) {
|
||||
$classmap = call_user_func( $this->classmapScanner, $package['path'], $excludedClasses, null );
|
||||
|
||||
foreach ( $classmap as $class => $path ) {
|
||||
$processed[ $class ] = array(
|
||||
'version' => $package['version'],
|
||||
'path' => call_user_func( $this->pathCodeTransformer, $path ),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ksort( $processed );
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the PSR-4 autoloads into a relative path format including the version for each file.
|
||||
*
|
||||
* @param array $autoloads The autoloads we are processing.
|
||||
* @param bool $scanPsrPackages Whether or not PSR packages should be converted to a classmap.
|
||||
*
|
||||
* @return array|null $processed
|
||||
*/
|
||||
public function processPsr4Packages( $autoloads, $scanPsrPackages ) {
|
||||
if ( $scanPsrPackages || empty( $autoloads['psr-4'] ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$processed = array();
|
||||
|
||||
foreach ( $autoloads['psr-4'] as $namespace => $packages ) {
|
||||
$namespace = empty( $namespace ) ? null : $namespace;
|
||||
$paths = array();
|
||||
|
||||
foreach ( $packages as $package ) {
|
||||
$paths[] = call_user_func( $this->pathCodeTransformer, $package['path'] );
|
||||
}
|
||||
|
||||
$processed[ $namespace ] = array(
|
||||
'version' => $package['version'],
|
||||
'path' => $paths,
|
||||
);
|
||||
}
|
||||
|
||||
return $processed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the file autoloads into a relative format including the version for each file.
|
||||
*
|
||||
* @param array $autoloads The autoloads we are processing.
|
||||
*
|
||||
* @return array|null $processed
|
||||
*/
|
||||
public function processFiles( $autoloads ) {
|
||||
if ( empty( $autoloads['files'] ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$processed = array();
|
||||
|
||||
foreach ( $autoloads['files'] as $file_id => $package ) {
|
||||
$processed[ $file_id ] = array(
|
||||
'version' => $package['version'],
|
||||
'path' => call_user_func( $this->pathCodeTransformer, $package['path'] ),
|
||||
);
|
||||
}
|
||||
|
||||
return $processed;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Custom Autoloader Composer Plugin, hooks into composer events to generate the custom autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader;
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\EventDispatcher\EventSubscriberInterface;
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Plugin\PluginInterface;
|
||||
use Composer\Script\Event;
|
||||
use Composer\Script\ScriptEvents;
|
||||
|
||||
/**
|
||||
* Class CustomAutoloaderPlugin.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
class CustomAutoloaderPlugin implements PluginInterface, EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* IO object.
|
||||
*
|
||||
* @var IOInterface IO object.
|
||||
*/
|
||||
private $io;
|
||||
|
||||
/**
|
||||
* Composer object.
|
||||
*
|
||||
* @var Composer Composer object.
|
||||
*/
|
||||
private $composer;
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
*
|
||||
* @param Composer $composer Composer object.
|
||||
* @param IOInterface $io IO object.
|
||||
*/
|
||||
public function activate( Composer $composer, IOInterface $io ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
$this->composer = $composer;
|
||||
$this->io = $io;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
* phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*
|
||||
* @param Composer $composer Composer object.
|
||||
* @param IOInterface $io IO object.
|
||||
*/
|
||||
public function deactivate( Composer $composer, IOInterface $io ) {
|
||||
/*
|
||||
* Intentionally left empty. This is a PluginInterface method.
|
||||
* phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing.
|
||||
* phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*
|
||||
* @param Composer $composer Composer object.
|
||||
* @param IOInterface $io IO object.
|
||||
*/
|
||||
public function uninstall( Composer $composer, IOInterface $io ) {
|
||||
/*
|
||||
* Intentionally left empty. This is a PluginInterface method.
|
||||
* phpcs:enable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell composer to listen for events and do something with them.
|
||||
*
|
||||
* @return array List of subscribed events.
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
return array(
|
||||
ScriptEvents::POST_AUTOLOAD_DUMP => 'postAutoloadDump',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the custom autolaoder.
|
||||
*
|
||||
* @param Event $event Script event object.
|
||||
*/
|
||||
public function postAutoloadDump( Event $event ) {
|
||||
// When the autoloader is not required by the root package we don't want to execute it.
|
||||
// This prevents unwanted transitive execution that generates unused autoloaders or
|
||||
// at worst throws fatal executions.
|
||||
if ( ! $this->isRequiredByRoot() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $this->composer->getConfig();
|
||||
|
||||
if ( 'vendor' !== $config->raw()['config']['vendor-dir'] ) {
|
||||
$this->io->writeError( "\n<error>An error occurred while generating the autoloader files:", true );
|
||||
$this->io->writeError( 'The project\'s composer.json or composer environment set a non-default vendor directory.', true );
|
||||
$this->io->writeError( 'The default composer vendor directory must be used.</error>', true );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
$installationManager = $this->composer->getInstallationManager();
|
||||
$repoManager = $this->composer->getRepositoryManager();
|
||||
$localRepo = $repoManager->getLocalRepository();
|
||||
$package = $this->composer->getPackage();
|
||||
$optimize = $event->getFlags()['optimize'];
|
||||
$suffix = $this->determineSuffix();
|
||||
|
||||
$generator = new AutoloadGenerator( $this->io );
|
||||
$generator->dump( $this->composer, $config, $localRepo, $package, $installationManager, 'composer', $optimize, $suffix );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the suffix for the autoloader class.
|
||||
*
|
||||
* Reuses an existing suffix from vendor/autoload_packages.php or vendor/autoload.php if possible.
|
||||
*
|
||||
* @return string Suffix.
|
||||
*/
|
||||
private function determineSuffix() {
|
||||
$config = $this->composer->getConfig();
|
||||
$vendorPath = $config->get( 'vendor-dir' );
|
||||
|
||||
// Command line.
|
||||
$suffix = $config->get( 'autoloader-suffix' );
|
||||
if ( $suffix ) {
|
||||
return $suffix;
|
||||
}
|
||||
|
||||
// Reuse our own suffix, if any.
|
||||
if ( is_readable( $vendorPath . '/autoload_packages.php' ) ) {
|
||||
$content = file_get_contents( $vendorPath . '/autoload_packages.php' );
|
||||
if ( preg_match( '/^namespace Automattic\\\\Jetpack\\\\Autoloader\\\\jp([^;\s]+?)(?:\\\\al[^;\s]+)?;/m', $content, $match ) ) {
|
||||
return $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Reuse Composer's suffix, if any.
|
||||
if ( is_readable( $vendorPath . '/autoload.php' ) ) {
|
||||
$content = file_get_contents( $vendorPath . '/autoload.php' );
|
||||
if ( preg_match( '{ComposerAutoloaderInit([^:\s]+)::}', $content, $match ) ) {
|
||||
return $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a random suffix.
|
||||
return md5( uniqid( '', true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether or not the root package is the one that required the autoloader.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isRequiredByRoot() {
|
||||
$package = $this->composer->getPackage();
|
||||
$requires = $package->getRequires();
|
||||
if ( ! is_array( $requires ) ) { // @phan-suppress-current-line PhanRedundantCondition -- Earlier Composer versions may not have guaranteed this.
|
||||
$requires = array();
|
||||
}
|
||||
$devRequires = $package->getDevRequires();
|
||||
if ( ! is_array( $devRequires ) ) { // @phan-suppress-current-line PhanRedundantCondition -- Earlier Composer versions may not have guaranteed this.
|
||||
$devRequires = array();
|
||||
}
|
||||
$requires = array_merge( $requires, $devRequires );
|
||||
|
||||
if ( empty( $requires ) ) {
|
||||
$this->io->writeError( "\n<error>The package is not required and this should never happen?</error>", true );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
foreach ( $requires as $require ) {
|
||||
if ( 'automattic/jetpack-autoloader' === $require->getTarget() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Manifest Generator.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_var_export
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader;
|
||||
|
||||
/**
|
||||
* Class ManifestGenerator.
|
||||
*/
|
||||
class ManifestGenerator {
|
||||
|
||||
/**
|
||||
* Builds a manifest file for the given autoloader type.
|
||||
*
|
||||
* @param string $autoloaderType The type of autoloader to build a manifest for.
|
||||
* @param string $fileName The filename of the manifest.
|
||||
* @param array $content The manifest content to generate using.
|
||||
*
|
||||
* @return string|null $manifestFile
|
||||
* @throws \InvalidArgumentException When an invalid autoloader type is given.
|
||||
*/
|
||||
public static function buildManifest( $autoloaderType, $fileName, $content ) {
|
||||
if ( empty( $content ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ( $autoloaderType ) {
|
||||
case 'classmap':
|
||||
case 'files':
|
||||
return self::buildStandardManifest( $fileName, $content );
|
||||
case 'psr-4':
|
||||
return self::buildPsr4Manifest( $fileName, $content );
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException( 'An invalid manifest type of ' . $autoloaderType . ' was passed!' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the contents for the standard manifest file.
|
||||
*
|
||||
* @param string $fileName The filename we are building.
|
||||
* @param array $manifestData The formatted data for the manifest.
|
||||
*
|
||||
* @return string|null $manifestFile
|
||||
*/
|
||||
private static function buildStandardManifest( $fileName, $manifestData ) {
|
||||
$fileContent = PHP_EOL;
|
||||
foreach ( $manifestData as $key => $data ) {
|
||||
$key = var_export( $key, true );
|
||||
$versionCode = var_export( $data['version'], true );
|
||||
$fileContent .= <<<MANIFEST_CODE
|
||||
$key => array(
|
||||
'version' => $versionCode,
|
||||
'path' => {$data['path']}
|
||||
),
|
||||
MANIFEST_CODE;
|
||||
$fileContent .= PHP_EOL;
|
||||
}
|
||||
|
||||
return self::buildFile( $fileName, $fileContent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the contents for the PSR-4 manifest file.
|
||||
*
|
||||
* @param string $fileName The filename we are building.
|
||||
* @param array $namespaces The formatted PSR-4 data for the manifest.
|
||||
*
|
||||
* @return string|null $manifestFile
|
||||
*/
|
||||
private static function buildPsr4Manifest( $fileName, $namespaces ) {
|
||||
$fileContent = PHP_EOL;
|
||||
foreach ( $namespaces as $namespace => $data ) {
|
||||
$namespaceCode = var_export( $namespace, true );
|
||||
$versionCode = var_export( $data['version'], true );
|
||||
$pathCode = 'array( ' . implode( ', ', $data['path'] ) . ' )';
|
||||
$fileContent .= <<<MANIFEST_CODE
|
||||
$namespaceCode => array(
|
||||
'version' => $versionCode,
|
||||
'path' => $pathCode
|
||||
),
|
||||
MANIFEST_CODE;
|
||||
$fileContent .= PHP_EOL;
|
||||
}
|
||||
|
||||
return self::buildFile( $fileName, $fileContent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the PHP that will be used in the file.
|
||||
*
|
||||
* @param string $fileName The filename we are building.
|
||||
* @param string $content The content to be written into the file.
|
||||
*
|
||||
* @return string $fileContent
|
||||
*/
|
||||
private static function buildFile( $fileName, $content ) {
|
||||
return <<<INCLUDE_FILE
|
||||
<?php
|
||||
|
||||
// This file `$fileName` was auto generated by automattic/jetpack-autoloader.
|
||||
|
||||
\$vendorDir = dirname(__DIR__);
|
||||
\$baseDir = dirname(\$vendorDir);
|
||||
|
||||
return array($content);
|
||||
|
||||
INCLUDE_FILE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
require_once __DIR__ . '/jetpack-autoloader/class-autoloader.php';
|
||||
Autoloader::init();
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
use Automattic\Jetpack\Autoloader\AutoloadGenerator;
|
||||
|
||||
/**
|
||||
* This class selects the package version for the autoloader.
|
||||
*/
|
||||
class Autoloader_Handler {
|
||||
|
||||
/**
|
||||
* The PHP_Autoloader instance.
|
||||
*
|
||||
* @var PHP_Autoloader
|
||||
*/
|
||||
private $php_autoloader;
|
||||
|
||||
/**
|
||||
* The Hook_Manager instance.
|
||||
*
|
||||
* @var Hook_Manager
|
||||
*/
|
||||
private $hook_manager;
|
||||
|
||||
/**
|
||||
* The Manifest_Reader instance.
|
||||
*
|
||||
* @var Manifest_Reader
|
||||
*/
|
||||
private $manifest_reader;
|
||||
|
||||
/**
|
||||
* The Version_Selector instance.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param PHP_Autoloader $php_autoloader The PHP_Autoloader instance.
|
||||
* @param Hook_Manager $hook_manager The Hook_Manager instance.
|
||||
* @param Manifest_Reader $manifest_reader The Manifest_Reader instance.
|
||||
* @param Version_Selector $version_selector The Version_Selector instance.
|
||||
*/
|
||||
public function __construct( $php_autoloader, $hook_manager, $manifest_reader, $version_selector ) {
|
||||
$this->php_autoloader = $php_autoloader;
|
||||
$this->hook_manager = $hook_manager;
|
||||
$this->manifest_reader = $manifest_reader;
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether or not an autoloader is currently in the process of initializing.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_initializing() {
|
||||
// If no version has been set it means that no autoloader has started initializing yet.
|
||||
global $jetpack_autoloader_latest_version;
|
||||
if ( ! isset( $jetpack_autoloader_latest_version ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When the version is set but the classmap is not it ALWAYS means that this is the
|
||||
// latest autoloader and is being included by an older one.
|
||||
global $jetpack_packages_classmap;
|
||||
if ( empty( $jetpack_packages_classmap ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Version 2.4.0 added a new global and altered the reset semantics. We need to check
|
||||
// the other global as well since it may also point at initialization.
|
||||
// Note: We don't need to check for the class first because every autoloader that
|
||||
// will set the latest version global requires this class in the classmap.
|
||||
$replacing_version = $jetpack_packages_classmap[ AutoloadGenerator::class ]['version'];
|
||||
if ( $this->version_selector->is_dev_version( $replacing_version ) || version_compare( $replacing_version, '2.4.0.0', '>=' ) ) {
|
||||
global $jetpack_autoloader_loader;
|
||||
if ( ! isset( $jetpack_autoloader_loader ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates an autoloader using the given plugins and activates it.
|
||||
*
|
||||
* @param string[] $plugins The plugins to initialize the autoloader for.
|
||||
*/
|
||||
public function activate_autoloader( $plugins ) {
|
||||
global $jetpack_packages_psr4;
|
||||
$jetpack_packages_psr4 = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_psr4.php', $jetpack_packages_psr4 );
|
||||
|
||||
global $jetpack_packages_classmap;
|
||||
$jetpack_packages_classmap = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_classmap.php', $jetpack_packages_classmap );
|
||||
|
||||
global $jetpack_packages_filemap;
|
||||
$jetpack_packages_filemap = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_filemap.php', $jetpack_packages_filemap );
|
||||
|
||||
$loader = new Version_Loader(
|
||||
$this->version_selector,
|
||||
$jetpack_packages_classmap,
|
||||
$jetpack_packages_psr4,
|
||||
$jetpack_packages_filemap
|
||||
);
|
||||
|
||||
$this->php_autoloader->register_autoloader( $loader );
|
||||
|
||||
// Now that the autoloader is active we can load the filemap.
|
||||
$loader->load_filemap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the active autoloader and all related global state.
|
||||
*/
|
||||
public function reset_autoloader() {
|
||||
$this->php_autoloader->unregister_autoloader();
|
||||
$this->hook_manager->reset();
|
||||
|
||||
// Clear all of the autoloader globals so that older autoloaders don't do anything strange.
|
||||
global $jetpack_autoloader_latest_version;
|
||||
$jetpack_autoloader_latest_version = null;
|
||||
|
||||
global $jetpack_packages_classmap;
|
||||
$jetpack_packages_classmap = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
|
||||
global $jetpack_packages_psr4;
|
||||
$jetpack_packages_psr4 = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
|
||||
global $jetpack_packages_filemap;
|
||||
$jetpack_packages_filemap = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
use Automattic\Jetpack\Autoloader\AutoloadGenerator;
|
||||
|
||||
/**
|
||||
* This class locates autoloaders.
|
||||
*/
|
||||
class Autoloader_Locator {
|
||||
|
||||
/**
|
||||
* The object for comparing autoloader versions.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Version_Selector $version_selector The version selector object.
|
||||
*/
|
||||
public function __construct( $version_selector ) {
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the plugin with the latest autoloader.
|
||||
*
|
||||
* @param array $plugin_paths An array of plugin paths.
|
||||
* @param string $latest_version The latest version reference. @phan-output-reference.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function find_latest_autoloader( $plugin_paths, &$latest_version ) {
|
||||
$latest_plugin = null;
|
||||
|
||||
foreach ( $plugin_paths as $plugin_path ) {
|
||||
$version = $this->get_autoloader_version( $plugin_path );
|
||||
if ( ! $version || ! $this->version_selector->is_version_update_required( $latest_version, $version ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$latest_version = $version;
|
||||
$latest_plugin = $plugin_path;
|
||||
}
|
||||
|
||||
return $latest_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the autoloader.
|
||||
*
|
||||
* @param string $plugin_path The path to the plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_autoloader_path( $plugin_path ) {
|
||||
return trailingslashit( $plugin_path ) . 'vendor/autoload_packages.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version for the autoloader.
|
||||
*
|
||||
* @param string $plugin_path The path to the plugin.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_autoloader_version( $plugin_path ) {
|
||||
$classmap = trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php';
|
||||
if ( ! file_exists( $classmap ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classmap = require $classmap;
|
||||
if ( isset( $classmap[ AutoloadGenerator::class ] ) ) {
|
||||
return $classmap[ AutoloadGenerator::class ]['version'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles management of the actual PHP autoloader.
|
||||
*/
|
||||
class Autoloader {
|
||||
|
||||
/**
|
||||
* Checks to see whether or not the autoloader should be initialized and then initializes it if so.
|
||||
*
|
||||
* @param Container|null $container The container we want to use for autoloader initialization. If none is given
|
||||
* then a container will be created automatically.
|
||||
*/
|
||||
public static function init( $container = null ) {
|
||||
// The container holds and manages the lifecycle of our dependencies
|
||||
// to make them easier to work with and increase flexibility.
|
||||
if ( ! isset( $container ) ) {
|
||||
require_once __DIR__ . '/class-container.php';
|
||||
$container = new Container();
|
||||
}
|
||||
|
||||
// phpcs:disable Generic.Commenting.DocComment.MissingShort
|
||||
|
||||
/** @var Autoloader_Handler $autoloader_handler */
|
||||
$autoloader_handler = $container->get( Autoloader_Handler::class );
|
||||
|
||||
// If the autoloader is already initializing it means that it has included us as the latest.
|
||||
$was_included_by_autoloader = $autoloader_handler->is_initializing();
|
||||
|
||||
/** @var Plugin_Locator $plugin_locator */
|
||||
$plugin_locator = $container->get( Plugin_Locator::class );
|
||||
|
||||
/** @var Plugins_Handler $plugins_handler */
|
||||
$plugins_handler = $container->get( Plugins_Handler::class );
|
||||
|
||||
// The current plugin is the one that we are attempting to initialize here.
|
||||
$current_plugin = $plugin_locator->find_current_plugin();
|
||||
|
||||
// The active plugins are those that we were able to discover on the site. This list will not
|
||||
// include mu-plugins, those activated by code, or those who are hidden by filtering. We also
|
||||
// want to take care to not consider the current plugin unknown if it was included by an
|
||||
// autoloader. This avoids the case where a plugin will be marked "active" while deactivated
|
||||
// due to it having the latest autoloader.
|
||||
$active_plugins = $plugins_handler->get_active_plugins( true, ! $was_included_by_autoloader );
|
||||
|
||||
// The cached plugins are all of those that were active or discovered by the autoloader during a previous request.
|
||||
// Note that it's possible this list will include plugins that have since been deactivated, but after a request
|
||||
// the cache should be updated and the deactivated plugins will be removed.
|
||||
$cached_plugins = $plugins_handler->get_cached_plugins();
|
||||
|
||||
// We combine the active list and cached list to preemptively load classes for plugins that are
|
||||
// presently unknown but will be loaded during the request. While this may result in us considering packages in
|
||||
// deactivated plugins there shouldn't be any problems as a result and the eventual consistency is sufficient.
|
||||
$all_plugins = array_merge( $active_plugins, $cached_plugins );
|
||||
|
||||
// In particular we also include the current plugin to address the case where it is the latest autoloader
|
||||
// but also unknown (and not cached). We don't want it in the active list because we don't know that it
|
||||
// is active but we need it in the all plugins list so that it is considered by the autoloader.
|
||||
$all_plugins[] = $current_plugin;
|
||||
|
||||
// We require uniqueness in the array to avoid processing the same plugin more than once.
|
||||
$all_plugins = array_values( array_unique( $all_plugins ) );
|
||||
|
||||
/** @var Latest_Autoloader_Guard $guard */
|
||||
$guard = $container->get( Latest_Autoloader_Guard::class );
|
||||
if ( $guard->should_stop_init( $current_plugin, $all_plugins, $was_included_by_autoloader ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the autoloader using the handler now that we're ready.
|
||||
$autoloader_handler->activate_autoloader( $all_plugins );
|
||||
|
||||
/** @var Hook_Manager $hook_manager */
|
||||
$hook_manager = $container->get( Hook_Manager::class );
|
||||
|
||||
// Register a shutdown handler to clean up the autoloader.
|
||||
$hook_manager->add_action( 'shutdown', new Shutdown_Handler( $plugins_handler, $cached_plugins, $was_included_by_autoloader ) );
|
||||
|
||||
// Register a plugins_loaded handler to check for conflicting autoloaders.
|
||||
$hook_manager->add_action( 'plugins_loaded', array( $guard, 'check_for_conflicting_autoloaders' ), 1 );
|
||||
|
||||
// phpcs:enable Generic.Commenting.DocComment.MissingShort
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class manages the files and dependencies of the autoloader.
|
||||
*/
|
||||
class Container {
|
||||
|
||||
/**
|
||||
* Since each autoloader's class files exist within their own namespace we need a map to
|
||||
* convert between the local class and a shared key. Note that no version checking is
|
||||
* performed on these dependencies and the first autoloader to register will be the
|
||||
* one that is utilized.
|
||||
*/
|
||||
const SHARED_DEPENDENCY_KEYS = array(
|
||||
Hook_Manager::class => 'Hook_Manager',
|
||||
);
|
||||
|
||||
/**
|
||||
* A map of all the dependencies we've registered with the container and created.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dependencies;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->dependencies = array();
|
||||
|
||||
$this->register_shared_dependencies();
|
||||
$this->register_dependencies();
|
||||
$this->initialize_globals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a dependency out of the container.
|
||||
*
|
||||
* @param string $class The class to fetch.
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \InvalidArgumentException When a class that isn't registered with the container is fetched.
|
||||
*/
|
||||
public function get( $class ) {
|
||||
if ( ! isset( $this->dependencies[ $class ] ) ) {
|
||||
throw new \InvalidArgumentException( "Class '$class' is not registered with the container." );
|
||||
}
|
||||
|
||||
return $this->dependencies[ $class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all of the dependencies that are shared between all instances of the autoloader.
|
||||
*/
|
||||
private function register_shared_dependencies() {
|
||||
global $jetpack_autoloader_container_shared;
|
||||
if ( ! isset( $jetpack_autoloader_container_shared ) ) {
|
||||
$jetpack_autoloader_container_shared = array();
|
||||
}
|
||||
|
||||
$key = self::SHARED_DEPENDENCY_KEYS[ Hook_Manager::class ];
|
||||
if ( ! isset( $jetpack_autoloader_container_shared[ $key ] ) ) {
|
||||
require_once __DIR__ . '/class-hook-manager.php';
|
||||
$jetpack_autoloader_container_shared[ $key ] = new Hook_Manager();
|
||||
}
|
||||
$this->dependencies[ Hook_Manager::class ] = &$jetpack_autoloader_container_shared[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all of the dependencies with the container.
|
||||
*/
|
||||
private function register_dependencies() {
|
||||
require_once __DIR__ . '/class-path-processor.php';
|
||||
$this->dependencies[ Path_Processor::class ] = new Path_Processor();
|
||||
|
||||
require_once __DIR__ . '/class-plugin-locator.php';
|
||||
$this->dependencies[ Plugin_Locator::class ] = new Plugin_Locator(
|
||||
$this->get( Path_Processor::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-version-selector.php';
|
||||
$this->dependencies[ Version_Selector::class ] = new Version_Selector();
|
||||
|
||||
require_once __DIR__ . '/class-autoloader-locator.php';
|
||||
$this->dependencies[ Autoloader_Locator::class ] = new Autoloader_Locator(
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-php-autoloader.php';
|
||||
$this->dependencies[ PHP_Autoloader::class ] = new PHP_Autoloader();
|
||||
|
||||
require_once __DIR__ . '/class-manifest-reader.php';
|
||||
$this->dependencies[ Manifest_Reader::class ] = new Manifest_Reader(
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-plugins-handler.php';
|
||||
$this->dependencies[ Plugins_Handler::class ] = new Plugins_Handler(
|
||||
$this->get( Plugin_Locator::class ),
|
||||
$this->get( Path_Processor::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-autoloader-handler.php';
|
||||
$this->dependencies[ Autoloader_Handler::class ] = new Autoloader_Handler(
|
||||
$this->get( PHP_Autoloader::class ),
|
||||
$this->get( Hook_Manager::class ),
|
||||
$this->get( Manifest_Reader::class ),
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-latest-autoloader-guard.php';
|
||||
$this->dependencies[ Latest_Autoloader_Guard::class ] = new Latest_Autoloader_Guard(
|
||||
$this->get( Plugins_Handler::class ),
|
||||
$this->get( Autoloader_Handler::class ),
|
||||
$this->get( Autoloader_Locator::class )
|
||||
);
|
||||
|
||||
// Register any classes that we will use elsewhere.
|
||||
require_once __DIR__ . '/class-version-loader.php';
|
||||
require_once __DIR__ . '/class-shutdown-handler.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes any of the globals needed by the autoloader.
|
||||
*/
|
||||
private function initialize_globals() {
|
||||
/*
|
||||
* This global was retired in version 2.9. The value is set to 'false' to maintain
|
||||
* compatibility with older versions of the autoloader.
|
||||
*/
|
||||
global $jetpack_autoloader_including_latest;
|
||||
$jetpack_autoloader_including_latest = false;
|
||||
|
||||
// Not all plugins can be found using the locator. In cases where a plugin loads the autoloader
|
||||
// but was not discoverable, we will record them in this array to track them as "active".
|
||||
global $jetpack_autoloader_activating_plugins_paths;
|
||||
if ( ! isset( $jetpack_autoloader_activating_plugins_paths ) ) {
|
||||
$jetpack_autoloader_activating_plugins_paths = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* Allows the latest autoloader to register hooks that can be removed when the autoloader is reset.
|
||||
*/
|
||||
class Hook_Manager {
|
||||
|
||||
/**
|
||||
* An array containing all of the hooks that we've registered.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $registered_hooks;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->registered_hooks = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an action to WordPress and registers it internally.
|
||||
*
|
||||
* @param string $tag The name of the action which is hooked.
|
||||
* @param callable $callable The function to call.
|
||||
* @param int $priority Used to specify the priority of the action.
|
||||
* @param int $accepted_args Used to specify the number of arguments the callable accepts.
|
||||
*/
|
||||
public function add_action( $tag, $callable, $priority = 10, $accepted_args = 1 ) {
|
||||
$this->registered_hooks[ $tag ][] = array(
|
||||
'priority' => $priority,
|
||||
'callable' => $callable,
|
||||
);
|
||||
|
||||
add_action( $tag, $callable, $priority, $accepted_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to WordPress and registers it internally.
|
||||
*
|
||||
* @param string $tag The name of the filter which is hooked.
|
||||
* @param callable $callable The function to call.
|
||||
* @param int $priority Used to specify the priority of the filter.
|
||||
* @param int $accepted_args Used to specify the number of arguments the callable accepts.
|
||||
*/
|
||||
public function add_filter( $tag, $callable, $priority = 10, $accepted_args = 1 ) {
|
||||
$this->registered_hooks[ $tag ][] = array(
|
||||
'priority' => $priority,
|
||||
'callable' => $callable,
|
||||
);
|
||||
|
||||
add_filter( $tag, $callable, $priority, $accepted_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the registered hooks.
|
||||
*/
|
||||
public function reset() {
|
||||
foreach ( $this->registered_hooks as $tag => $hooks ) {
|
||||
foreach ( $hooks as $hook ) {
|
||||
remove_filter( $tag, $hook['callable'], $hook['priority'] );
|
||||
}
|
||||
}
|
||||
$this->registered_hooks = array();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class ensures that we're only executing the latest autoloader.
|
||||
*/
|
||||
class Latest_Autoloader_Guard {
|
||||
|
||||
/**
|
||||
* The Plugins_Handler instance.
|
||||
*
|
||||
* @var Plugins_Handler
|
||||
*/
|
||||
private $plugins_handler;
|
||||
|
||||
/**
|
||||
* The Autoloader_Handler instance.
|
||||
*
|
||||
* @var Autoloader_Handler
|
||||
*/
|
||||
private $autoloader_handler;
|
||||
|
||||
/**
|
||||
* The Autoloader_locator instance.
|
||||
*
|
||||
* @var Autoloader_Locator
|
||||
*/
|
||||
private $autoloader_locator;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Plugins_Handler $plugins_handler The Plugins_Handler instance.
|
||||
* @param Autoloader_Handler $autoloader_handler The Autoloader_Handler instance.
|
||||
* @param Autoloader_Locator $autoloader_locator The Autoloader_Locator instance.
|
||||
*/
|
||||
public function __construct( $plugins_handler, $autoloader_handler, $autoloader_locator ) {
|
||||
$this->plugins_handler = $plugins_handler;
|
||||
$this->autoloader_handler = $autoloader_handler;
|
||||
$this->autoloader_locator = $autoloader_locator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the autoloader should be initialized. Note that this function
|
||||
* has the side-effect of actually loading the latest autoloader in the event that this
|
||||
* is not it.
|
||||
*
|
||||
* @param string $current_plugin The current plugin we're checking.
|
||||
* @param string[] $plugins The active plugins to check for autoloaders in.
|
||||
* @param bool $was_included_by_autoloader Indicates whether or not this autoloader was included by another.
|
||||
*
|
||||
* @return bool True if we should stop initialization, otherwise false.
|
||||
*/
|
||||
public function should_stop_init( $current_plugin, $plugins, $was_included_by_autoloader ) {
|
||||
global $jetpack_autoloader_latest_version;
|
||||
|
||||
// We need to reset the autoloader when the plugins change because
|
||||
// that means the autoloader was generated with a different list.
|
||||
if ( $this->plugins_handler->have_plugins_changed( $plugins ) ) {
|
||||
$this->autoloader_handler->reset_autoloader();
|
||||
}
|
||||
|
||||
// When the latest autoloader has already been found we don't need to search for it again.
|
||||
// We should take care however because this will also trigger if the autoloader has been
|
||||
// included by an older one.
|
||||
if ( isset( $jetpack_autoloader_latest_version ) && ! $was_included_by_autoloader ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$latest_plugin = $this->autoloader_locator->find_latest_autoloader( $plugins, $jetpack_autoloader_latest_version );
|
||||
if ( isset( $latest_plugin ) && $latest_plugin !== $current_plugin ) {
|
||||
require $this->autoloader_locator->get_autoloader_path( $latest_plugin );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for conflicting autoloaders.
|
||||
*
|
||||
* A common source of strange and confusing problems is when another plugin
|
||||
* registers a Composer autoloader at a higher priority that us. If enabled,
|
||||
* check for this problem and warn about it.
|
||||
*
|
||||
* Called from the plugins_loaded hook.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @return void
|
||||
*/
|
||||
public function check_for_conflicting_autoloaders() {
|
||||
if ( ! defined( 'JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS' ) || ! JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $jetpack_autoloader_loader;
|
||||
if ( ! isset( $jetpack_autoloader_loader ) ) {
|
||||
return;
|
||||
}
|
||||
$prefixes = array();
|
||||
foreach ( ( $jetpack_autoloader_loader->get_class_map() ?? array() ) as $classname => $data ) {
|
||||
$parts = explode( '\\', trim( $classname, '\\' ) );
|
||||
array_pop( $parts );
|
||||
while ( $parts ) {
|
||||
$prefixes[ implode( '\\', $parts ) . '\\' ] = true;
|
||||
array_pop( $parts );
|
||||
}
|
||||
}
|
||||
foreach ( ( $jetpack_autoloader_loader->get_psr4_map() ?? array() ) as $prefix => $data ) {
|
||||
$parts = explode( '\\', trim( $prefix, '\\' ) );
|
||||
while ( $parts ) {
|
||||
$prefixes[ implode( '\\', $parts ) . '\\' ] = true;
|
||||
array_pop( $parts );
|
||||
}
|
||||
}
|
||||
|
||||
$autoload_chain = spl_autoload_functions();
|
||||
if ( ! $autoload_chain ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $autoload_chain as $autoloader ) {
|
||||
// No need to check anything after us.
|
||||
if ( is_array( $autoloader ) && is_string( $autoloader[0] ) && substr( $autoloader[0], 0, strlen( __NAMESPACE__ ) + 1 ) === __NAMESPACE__ . '\\' ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We can check Composer autoloaders easily enough.
|
||||
if ( is_array( $autoloader ) && $autoloader[0] instanceof \Composer\Autoload\ClassLoader && is_callable( array( $autoloader[0], 'getPrefixesPsr4' ) ) ) {
|
||||
$composer_autoloader = $autoloader[0];
|
||||
foreach ( $composer_autoloader->getClassMap() as $classname => $path ) {
|
||||
if ( $jetpack_autoloader_loader->find_class_file( $classname ) ) {
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the classes we handle (e.g. $classname => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
foreach ( $composer_autoloader->getPrefixesPsr4() as $prefix => $paths ) {
|
||||
if ( isset( $prefixes[ $prefix ] ) ) {
|
||||
$path = array_pop( $paths );
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the namespaces we handle (e.g. $prefix => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
foreach ( $composer_autoloader->getPrefixes() as $prefix => $paths ) {
|
||||
if ( isset( $prefixes[ $prefix ] ) ) {
|
||||
$path = array_pop( $paths );
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the namespaces we handle (e.g. $prefix => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class reads autoloader manifest files.
|
||||
*/
|
||||
class Manifest_Reader {
|
||||
|
||||
/**
|
||||
* The Version_Selector object.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Version_Selector $version_selector The Version_Selector object.
|
||||
*/
|
||||
public function __construct( $version_selector ) {
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all of the manifests in the given plugin paths.
|
||||
*
|
||||
* @param array $plugin_paths The paths to the plugins we're loading the manifest in.
|
||||
* @param string $manifest_path The path that we're loading the manifest from in each plugin.
|
||||
* @param array $path_map The path map to add the contents of the manifests to.
|
||||
*
|
||||
* @return array $path_map The path map we've built using the manifests in each plugin.
|
||||
*/
|
||||
public function read_manifests( $plugin_paths, $manifest_path, &$path_map ) {
|
||||
$file_paths = array_map(
|
||||
function ( $path ) use ( $manifest_path ) {
|
||||
return trailingslashit( $path ) . $manifest_path;
|
||||
},
|
||||
$plugin_paths
|
||||
);
|
||||
|
||||
foreach ( $file_paths as $path ) {
|
||||
$this->register_manifest( $path, $path_map );
|
||||
}
|
||||
|
||||
return $path_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin's manifest file with the path map.
|
||||
*
|
||||
* @param string $manifest_path The absolute path to the manifest that we're loading.
|
||||
* @param array $path_map The path map to add the contents of the manifest to.
|
||||
*/
|
||||
protected function register_manifest( $manifest_path, &$path_map ) {
|
||||
if ( ! is_readable( $manifest_path ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manifest = require $manifest_path;
|
||||
if ( ! is_array( $manifest ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $manifest as $key => $data ) {
|
||||
$this->register_record( $key, $data, $path_map );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an entry from the manifest in the path map.
|
||||
*
|
||||
* @param string $key The identifier for the entry we're registering.
|
||||
* @param array $data The data for the entry we're registering.
|
||||
* @param array $path_map The path map to add the contents of the manifest to.
|
||||
*/
|
||||
protected function register_record( $key, $data, &$path_map ) {
|
||||
if ( isset( $path_map[ $key ]['version'] ) ) {
|
||||
$selected_version = $path_map[ $key ]['version'];
|
||||
} else {
|
||||
$selected_version = null;
|
||||
}
|
||||
|
||||
if ( $this->version_selector->is_version_update_required( $selected_version, $data['version'] ) ) {
|
||||
$path_map[ $key ] = array(
|
||||
'version' => $data['version'],
|
||||
'path' => $data['path'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles dealing with paths for the autoloader.
|
||||
*/
|
||||
class Path_Processor {
|
||||
/**
|
||||
* Given a path this will replace any of the path constants with a token to represent it.
|
||||
*
|
||||
* @param string $path The path we want to process.
|
||||
*
|
||||
* @return string The tokenized path.
|
||||
*/
|
||||
public function tokenize_path_constants( $path ) {
|
||||
$path = wp_normalize_path( $path );
|
||||
|
||||
$constants = $this->get_normalized_constants();
|
||||
foreach ( $constants as $constant => $constant_path ) {
|
||||
$len = strlen( $constant_path );
|
||||
if ( substr( $path, 0, $len ) !== $constant_path ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return substr_replace( $path, '{{' . $constant . '}}', 0, $len );
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a path this will replace any of the path constant tokens with the expanded path.
|
||||
*
|
||||
* @param string $tokenized_path The path we want to process.
|
||||
*
|
||||
* @return string The expanded path.
|
||||
*/
|
||||
public function untokenize_path_constants( $tokenized_path ) {
|
||||
$tokenized_path = wp_normalize_path( $tokenized_path );
|
||||
|
||||
$constants = $this->get_normalized_constants();
|
||||
foreach ( $constants as $constant => $constant_path ) {
|
||||
$constant = '{{' . $constant . '}}';
|
||||
|
||||
$len = strlen( $constant );
|
||||
if ( substr( $tokenized_path, 0, $len ) !== $constant ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->get_real_path( substr_replace( $tokenized_path, $constant_path, 0, $len ) );
|
||||
}
|
||||
|
||||
return $tokenized_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a file and an array of places it might be, this will find the absolute path and return it.
|
||||
*
|
||||
* @param string $file The plugin or theme file to resolve.
|
||||
* @param array $directories_to_check The directories we should check for the file if it isn't an absolute path.
|
||||
*
|
||||
* @return string|false Returns the absolute path to the directory, otherwise false.
|
||||
*/
|
||||
public function find_directory_with_autoloader( $file, $directories_to_check ) {
|
||||
$file = wp_normalize_path( $file );
|
||||
|
||||
if ( ! $this->is_absolute_path( $file ) ) {
|
||||
$file = $this->find_absolute_plugin_path( $file, $directories_to_check );
|
||||
if ( ! isset( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We need the real path for consistency with __DIR__ paths.
|
||||
$file = $this->get_real_path( $file );
|
||||
|
||||
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
|
||||
$directory = @is_file( $file ) ? dirname( $file ) : $file;
|
||||
if ( ! @is_file( $directory . '/vendor/composer/jetpack_autoload_classmap.php' ) ) {
|
||||
return false;
|
||||
}
|
||||
// phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged
|
||||
|
||||
return $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches an array of normalized paths keyed by the constant they came from.
|
||||
*
|
||||
* @return string[] The normalized paths keyed by the constant.
|
||||
*/
|
||||
private function get_normalized_constants() {
|
||||
$raw_constants = array(
|
||||
// Order the constants from most-specific to least-specific.
|
||||
'WP_PLUGIN_DIR',
|
||||
'WPMU_PLUGIN_DIR',
|
||||
'WP_CONTENT_DIR',
|
||||
'ABSPATH',
|
||||
);
|
||||
|
||||
$constants = array();
|
||||
foreach ( $raw_constants as $raw ) {
|
||||
if ( ! defined( $raw ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = wp_normalize_path( constant( $raw ) );
|
||||
if ( isset( $path ) ) {
|
||||
$constants[ $raw ] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
return $constants;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not a path is absolute.
|
||||
*
|
||||
* @param string $path The path to check.
|
||||
*
|
||||
* @return bool True if the path is absolute, otherwise false.
|
||||
*/
|
||||
private function is_absolute_path( $path ) {
|
||||
if ( empty( $path ) || 0 === strlen( $path ) || '.' === $path[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Absolute paths on Windows may begin with a drive letter.
|
||||
if ( preg_match( '/^[a-zA-Z]:[\/\\\\]/', $path ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// A path starting with / or \ is absolute; anything else is relative.
|
||||
return ( '/' === $path[0] || '\\' === $path[0] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a file and a list of directories to check, this method will try to figure out
|
||||
* the absolute path to the file in question.
|
||||
*
|
||||
* @param string $normalized_path The normalized path to the plugin or theme file to resolve.
|
||||
* @param array $directories_to_check The directories we should check for the file if it isn't an absolute path.
|
||||
*
|
||||
* @return string|null The absolute path to the plugin file, otherwise null.
|
||||
*/
|
||||
private function find_absolute_plugin_path( $normalized_path, $directories_to_check ) {
|
||||
// We're only able to find the absolute path for plugin/theme PHP files.
|
||||
if ( ! is_string( $normalized_path ) || '.php' !== substr( $normalized_path, -4 ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ( $directories_to_check as $directory ) {
|
||||
$normalized_check = wp_normalize_path( trailingslashit( $directory ) ) . $normalized_path;
|
||||
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
|
||||
if ( @is_file( $normalized_check ) ) {
|
||||
return $normalized_check;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a path this will figure out the real path that we should be using.
|
||||
*
|
||||
* @param string $path The path to resolve.
|
||||
*
|
||||
* @return string The resolved path.
|
||||
*/
|
||||
private function get_real_path( $path ) {
|
||||
// We want to resolve symbolic links for consistency with __DIR__ paths.
|
||||
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
|
||||
$real_path = @realpath( $path );
|
||||
if ( false === $real_path ) {
|
||||
// Let the autoloader deal with paths that don't exist.
|
||||
$real_path = $path;
|
||||
}
|
||||
|
||||
// Using realpath will make it platform-specific so we must normalize it after.
|
||||
if ( $path !== $real_path ) {
|
||||
$real_path = wp_normalize_path( $real_path );
|
||||
}
|
||||
|
||||
return $real_path;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles management of the actual PHP autoloader.
|
||||
*/
|
||||
class PHP_Autoloader {
|
||||
|
||||
/**
|
||||
* Registers the autoloader with PHP so that it can begin autoloading classes.
|
||||
*
|
||||
* @param Version_Loader $version_loader The class loader to use in the autoloader.
|
||||
*/
|
||||
public function register_autoloader( $version_loader ) {
|
||||
// Make sure no other autoloaders are registered.
|
||||
$this->unregister_autoloader();
|
||||
|
||||
// Set the global so that it can be used to load classes.
|
||||
global $jetpack_autoloader_loader;
|
||||
$jetpack_autoloader_loader = $version_loader;
|
||||
|
||||
// Ensure that the autoloader is first to avoid contention with others.
|
||||
spl_autoload_register( array( self::class, 'load_class' ), true, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the active autoloader so that it will no longer autoload classes.
|
||||
*/
|
||||
public function unregister_autoloader() {
|
||||
// Remove any v2 autoloader that we've already registered.
|
||||
$autoload_chain = spl_autoload_functions();
|
||||
if ( ! $autoload_chain ) {
|
||||
return;
|
||||
}
|
||||
foreach ( $autoload_chain as $autoloader ) {
|
||||
// We can identify a v2 autoloader using the namespace.
|
||||
$namespace_check = null;
|
||||
|
||||
// Functions are recorded as strings.
|
||||
if ( is_string( $autoloader ) ) {
|
||||
$namespace_check = $autoloader;
|
||||
} elseif ( is_array( $autoloader ) && is_string( $autoloader[0] ) ) {
|
||||
// Static method calls have the class as the first array element.
|
||||
$namespace_check = $autoloader[0];
|
||||
} else {
|
||||
// Since the autoloader has only ever been a function or a static method we don't currently need to check anything else.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for the namespace without the generated suffix.
|
||||
if ( 'Automattic\\Jetpack\\Autoloader\\jp' === substr( $namespace_check, 0, 32 ) ) {
|
||||
spl_autoload_unregister( $autoloader );
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the global now that the autoloader has been unregistered.
|
||||
global $jetpack_autoloader_loader;
|
||||
$jetpack_autoloader_loader = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a class file if one could be found.
|
||||
*
|
||||
* Note: This function is static so that the autoloader can be easily unregistered. If
|
||||
* it was a class method we would have to unwrap the object to check the namespace.
|
||||
*
|
||||
* @param string $class_name The name of the class to autoload.
|
||||
*
|
||||
* @return bool Indicates whether or not a class file was loaded.
|
||||
*/
|
||||
public static function load_class( $class_name ) {
|
||||
global $jetpack_autoloader_loader;
|
||||
if ( ! isset( $jetpack_autoloader_loader ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = $jetpack_autoloader_loader->find_class_file( $class_name );
|
||||
if ( ! isset( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A common source of strange and confusing problems is when a vendor
|
||||
// file is autoloaded before all plugins have had a chance to register
|
||||
// with the autoloader. Detect that, if a development constant is set.
|
||||
if ( defined( 'JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS' ) && JETPACK_AUTOLOAD_DEBUG_EARLY_LOADS &&
|
||||
( strpos( $file, '/vendor/' ) !== false || strpos( $file, '/jetpack_vendor/' ) !== false ) &&
|
||||
is_callable( 'did_action' ) && ! did_action( 'plugins_loaded' )
|
||||
) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_wp_debug_backtrace_summary -- This is a debug log message.
|
||||
$msg = "Jetpack Autoloader: Autoloading `$class_name` before the plugins_loaded hook may cause strange and confusing problems. " . wp_debug_backtrace_summary( '', 1 );
|
||||
wp_trigger_error( '', $msg );
|
||||
}
|
||||
|
||||
require $file;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class scans the WordPress installation to find active plugins.
|
||||
*/
|
||||
class Plugin_Locator {
|
||||
|
||||
/**
|
||||
* The path processor for finding plugin paths.
|
||||
*
|
||||
* @var Path_Processor
|
||||
*/
|
||||
private $path_processor;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Path_Processor $path_processor The Path_Processor instance.
|
||||
*/
|
||||
public function __construct( $path_processor ) {
|
||||
$this->path_processor = $path_processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the current plugin.
|
||||
*
|
||||
* @return string $path The path to the current plugin.
|
||||
*
|
||||
* @throws \RuntimeException If the current plugin does not have an autoloader.
|
||||
*/
|
||||
public function find_current_plugin() {
|
||||
// Escape from `vendor/__DIR__` to root plugin directory.
|
||||
$plugin_directory = dirname( __DIR__, 2 );
|
||||
|
||||
// Use the path processor to ensure that this is an autoloader we're referencing.
|
||||
$path = $this->path_processor->find_directory_with_autoloader( $plugin_directory, array() );
|
||||
if ( false === $path ) {
|
||||
throw new \RuntimeException( 'Failed to locate plugin ' . $plugin_directory );
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a given option for plugin paths.
|
||||
*
|
||||
* @param string $option_name The option that we want to check for plugin information.
|
||||
* @param bool $site_option Indicates whether or not we want to check the site option.
|
||||
*
|
||||
* @return array $plugin_paths The list of absolute paths we've found.
|
||||
*/
|
||||
public function find_using_option( $option_name, $site_option = false ) {
|
||||
$raw = $site_option ? get_site_option( $option_name ) : get_option( $option_name );
|
||||
if ( false === $raw ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return $this->convert_plugins_to_paths( $raw );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for plugins in the `action` request parameter.
|
||||
*
|
||||
* @param string[] $allowed_actions The actions that we're allowed to return plugins for.
|
||||
*
|
||||
* @return array $plugin_paths The list of absolute paths we've found.
|
||||
*/
|
||||
public function find_using_request_action( $allowed_actions ) {
|
||||
/**
|
||||
* Note: we're not actually checking the nonce here because it's too early
|
||||
* in the execution. The pluggable functions are not yet loaded to give
|
||||
* plugins a chance to plug their versions. Therefore we're doing the bare
|
||||
* minimum: checking whether the nonce exists and it's in the right place.
|
||||
* The request will fail later if the nonce doesn't pass the check.
|
||||
*/
|
||||
if ( empty( $_REQUEST['_wpnonce'] ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated just below.
|
||||
$action = isset( $_REQUEST['action'] ) ? wp_unslash( $_REQUEST['action'] ) : false;
|
||||
if ( ! in_array( $action, $allowed_actions, true ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$plugin_slugs = array();
|
||||
switch ( $action ) {
|
||||
case 'activate':
|
||||
case 'deactivate':
|
||||
if ( empty( $_REQUEST['plugin'] ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated by convert_plugins_to_paths.
|
||||
$plugin_slugs[] = wp_unslash( $_REQUEST['plugin'] );
|
||||
break;
|
||||
|
||||
case 'activate-selected':
|
||||
case 'deactivate-selected':
|
||||
if ( empty( $_REQUEST['checked'] ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated by convert_plugins_to_paths.
|
||||
$plugin_slugs = wp_unslash( $_REQUEST['checked'] );
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->convert_plugins_to_paths( $plugin_slugs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of plugin slugs or paths, this will convert them to absolute paths and filter
|
||||
* out the plugins that are not directory plugins. Note that array keys will also be included
|
||||
* if they are plugin paths!
|
||||
*
|
||||
* @param string[] $plugins Plugin paths or slugs to filter.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function convert_plugins_to_paths( $plugins ) {
|
||||
if ( ! is_array( $plugins ) || empty( $plugins ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// We're going to look for plugins in the standard directories.
|
||||
$path_constants = array( WP_PLUGIN_DIR, WPMU_PLUGIN_DIR );
|
||||
|
||||
$plugin_paths = array();
|
||||
foreach ( $plugins as $key => $value ) {
|
||||
$path = $this->path_processor->find_directory_with_autoloader( $key, $path_constants );
|
||||
if ( $path ) {
|
||||
$plugin_paths[] = $path;
|
||||
}
|
||||
|
||||
$path = $this->path_processor->find_directory_with_autoloader( $value, $path_constants );
|
||||
if ( $path ) {
|
||||
$plugin_paths[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
return $plugin_paths;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles locating and caching all of the active plugins.
|
||||
*/
|
||||
class Plugins_Handler {
|
||||
/**
|
||||
* The transient key for plugin paths.
|
||||
*/
|
||||
const TRANSIENT_KEY = 'jetpack_autoloader_plugin_paths';
|
||||
|
||||
/**
|
||||
* The locator for finding plugins in different locations.
|
||||
*
|
||||
* @var Plugin_Locator
|
||||
*/
|
||||
private $plugin_locator;
|
||||
|
||||
/**
|
||||
* The processor for transforming cached paths.
|
||||
*
|
||||
* @var Path_Processor
|
||||
*/
|
||||
private $path_processor;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Plugin_Locator $plugin_locator The locator for finding active plugins.
|
||||
* @param Path_Processor $path_processor The processor for transforming cached paths.
|
||||
*/
|
||||
public function __construct( $plugin_locator, $path_processor ) {
|
||||
$this->plugin_locator = $plugin_locator;
|
||||
$this->path_processor = $path_processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the active plugins we can find.
|
||||
*
|
||||
* @param bool $include_deactivating When true, plugins deactivating this request will be considered active.
|
||||
* @param bool $record_unknown When true, the current plugin will be marked as active and recorded when unknown.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_active_plugins( $include_deactivating, $record_unknown ) {
|
||||
global $jetpack_autoloader_activating_plugins_paths;
|
||||
|
||||
// We're going to build a unique list of plugins from a few different sources
|
||||
// to find all of our "active" plugins. While we need to return an integer
|
||||
// array, we're going to use an associative array internally to reduce
|
||||
// the amount of time that we're going to spend checking uniqueness
|
||||
// and merging different arrays together to form the output.
|
||||
$active_plugins = array();
|
||||
|
||||
// Make sure that plugins which have activated this request are considered as "active" even though
|
||||
// they probably won't be present in any option.
|
||||
if ( is_array( $jetpack_autoloader_activating_plugins_paths ) ) {
|
||||
foreach ( $jetpack_autoloader_activating_plugins_paths as $path ) {
|
||||
$active_plugins[ $path ] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
// This option contains all of the plugins that have been activated.
|
||||
$plugins = $this->plugin_locator->find_using_option( 'active_plugins' );
|
||||
foreach ( $plugins as $path ) {
|
||||
$active_plugins[ $path ] = $path;
|
||||
}
|
||||
|
||||
// This option contains all of the multisite plugins that have been activated.
|
||||
if ( is_multisite() ) {
|
||||
$plugins = $this->plugin_locator->find_using_option( 'active_sitewide_plugins', true );
|
||||
foreach ( $plugins as $path ) {
|
||||
$active_plugins[ $path ] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
// These actions contain plugins that are being activated/deactivated during this request.
|
||||
$plugins = $this->plugin_locator->find_using_request_action( array( 'activate', 'activate-selected', 'deactivate', 'deactivate-selected' ) );
|
||||
foreach ( $plugins as $path ) {
|
||||
$active_plugins[ $path ] = $path;
|
||||
}
|
||||
|
||||
// When the current plugin isn't considered "active" there's a problem.
|
||||
// Since we're here, the plugin is active and currently being loaded.
|
||||
// We can support this case (mu-plugins and non-standard activation)
|
||||
// by adding the current plugin to the active list and marking it
|
||||
// as an unknown (activating) plugin. This also has the benefit
|
||||
// of causing a reset because the active plugins list has
|
||||
// been changed since it was saved in the global.
|
||||
$current_plugin = $this->plugin_locator->find_current_plugin();
|
||||
if ( $record_unknown && ! in_array( $current_plugin, $active_plugins, true ) ) {
|
||||
$active_plugins[ $current_plugin ] = $current_plugin;
|
||||
$jetpack_autoloader_activating_plugins_paths[] = $current_plugin;
|
||||
}
|
||||
|
||||
// When deactivating plugins aren't desired we should entirely remove them from the active list.
|
||||
if ( ! $include_deactivating ) {
|
||||
// These actions contain plugins that are being deactivated during this request.
|
||||
$plugins = $this->plugin_locator->find_using_request_action( array( 'deactivate', 'deactivate-selected' ) );
|
||||
foreach ( $plugins as $path ) {
|
||||
unset( $active_plugins[ $path ] );
|
||||
}
|
||||
}
|
||||
|
||||
// Transform the array so that we don't have to worry about the keys interacting with other array types later.
|
||||
return array_values( $active_plugins );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all of the cached plugins if there are any.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_cached_plugins() {
|
||||
$cached = get_transient( self::TRANSIENT_KEY );
|
||||
if ( ! is_array( $cached ) || empty( $cached ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// We need to expand the tokens to an absolute path for this webserver.
|
||||
return array_map( array( $this->path_processor, 'untokenize_path_constants' ), $cached );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the plugin list to the cache.
|
||||
*
|
||||
* @param array $plugins The plugin list to save to the cache.
|
||||
*/
|
||||
public function cache_plugins( $plugins ) {
|
||||
// We store the paths in a tokenized form so that that webservers with different absolute paths don't break.
|
||||
$plugins = array_map( array( $this->path_processor, 'tokenize_path_constants' ), $plugins );
|
||||
|
||||
set_transient( self::TRANSIENT_KEY, $plugins );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether or not the plugin list given has changed when compared to the
|
||||
* shared `$jetpack_autoloader_cached_plugin_paths` global. This allows us to deal
|
||||
* with cases where the active list may change due to filtering..
|
||||
*
|
||||
* @param string[] $plugins The plugins list to check against the global cache.
|
||||
*
|
||||
* @return bool True if the plugins have changed, otherwise false.
|
||||
*/
|
||||
public function have_plugins_changed( $plugins ) {
|
||||
global $jetpack_autoloader_cached_plugin_paths;
|
||||
|
||||
if ( $jetpack_autoloader_cached_plugin_paths !== $plugins ) {
|
||||
$jetpack_autoloader_cached_plugin_paths = $plugins;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles the shutdown of the autoloader.
|
||||
*/
|
||||
class Shutdown_Handler {
|
||||
|
||||
/**
|
||||
* The Plugins_Handler instance.
|
||||
*
|
||||
* @var Plugins_Handler
|
||||
*/
|
||||
private $plugins_handler;
|
||||
|
||||
/**
|
||||
* The plugins cached by this autoloader.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private $cached_plugins;
|
||||
|
||||
/**
|
||||
* Indicates whether or not this autoloader was included by another.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $was_included_by_autoloader;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Plugins_Handler $plugins_handler The Plugins_Handler instance to use.
|
||||
* @param string[] $cached_plugins The plugins cached by the autoloaer.
|
||||
* @param bool $was_included_by_autoloader Indicates whether or not the autoloader was included by another.
|
||||
*/
|
||||
public function __construct( $plugins_handler, $cached_plugins, $was_included_by_autoloader ) {
|
||||
$this->plugins_handler = $plugins_handler;
|
||||
$this->cached_plugins = $cached_plugins;
|
||||
$this->was_included_by_autoloader = $was_included_by_autoloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the shutdown of the autoloader.
|
||||
*/
|
||||
public function __invoke() {
|
||||
// Don't save a broken cache if an error happens during some plugin's initialization.
|
||||
if ( ! did_action( 'plugins_loaded' ) ) {
|
||||
// Ensure that the cache is emptied to prevent consecutive failures if the cache is to blame.
|
||||
if ( ! empty( $this->cached_plugins ) ) {
|
||||
$this->plugins_handler->cache_plugins( array() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the active plugins fresh since the list we pulled earlier might not contain
|
||||
// plugins that were activated but did not reset the autoloader. This happens
|
||||
// when a plugin is in the cache but not "active" when the autoloader loads.
|
||||
// We also want to make sure that plugins which are deactivating are not
|
||||
// considered "active" so that they will be removed from the cache now.
|
||||
try {
|
||||
$active_plugins = $this->plugins_handler->get_active_plugins( false, ! $this->was_included_by_autoloader );
|
||||
} catch ( \Exception $ex ) {
|
||||
// When the package is deleted before shutdown it will throw an exception.
|
||||
// In the event this happens we should erase the cache.
|
||||
if ( ! empty( $this->cached_plugins ) ) {
|
||||
$this->plugins_handler->cache_plugins( array() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The paths should be sorted for easy comparisons with those loaded from the cache.
|
||||
// Note we don't need to sort the cached entries because they're already sorted.
|
||||
sort( $active_plugins );
|
||||
|
||||
// We don't want to waste time saving a cache that hasn't changed.
|
||||
if ( $this->cached_plugins === $active_plugins ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->plugins_handler->cache_plugins( $active_plugins );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class loads other classes based on given parameters.
|
||||
*/
|
||||
class Version_Loader {
|
||||
|
||||
/**
|
||||
* The Version_Selector object.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* A map of available classes and their version and file path.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $classmap;
|
||||
|
||||
/**
|
||||
* A map of PSR-4 namespaces and their version and directory path.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $psr4_map;
|
||||
|
||||
/**
|
||||
* A map of all the files that we should load.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $filemap;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Version_Selector $version_selector The Version_Selector object.
|
||||
* @param array $classmap The verioned classmap to load using.
|
||||
* @param array $psr4_map The versioned PSR-4 map to load using.
|
||||
* @param array $filemap The versioned filemap to load.
|
||||
*/
|
||||
public function __construct( $version_selector, $classmap, $psr4_map, $filemap ) {
|
||||
$this->version_selector = $version_selector;
|
||||
$this->classmap = $classmap;
|
||||
$this->psr4_map = $psr4_map;
|
||||
$this->filemap = $filemap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the classmap.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @return array<string, array>
|
||||
*/
|
||||
public function get_class_map() {
|
||||
return $this->classmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the psr-4 mappings.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @return array<string, array>
|
||||
*/
|
||||
public function get_psr4_map() {
|
||||
return $this->psr4_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the file path for the given class.
|
||||
*
|
||||
* @param string $class_name The class to find.
|
||||
*
|
||||
* @return string|null $file_path The path to the file if found, null if no class was found.
|
||||
*/
|
||||
public function find_class_file( $class_name ) {
|
||||
$data = $this->select_newest_file(
|
||||
$this->classmap[ $class_name ] ?? null,
|
||||
$this->find_psr4_file( $class_name )
|
||||
);
|
||||
if ( ! isset( $data ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $data['path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all of the files in the filemap.
|
||||
*/
|
||||
public function load_filemap() {
|
||||
if ( empty( $this->filemap ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $this->filemap as $file_identifier => $file_data ) {
|
||||
if ( empty( $GLOBALS['__composer_autoload_files'][ $file_identifier ] ) ) {
|
||||
require_once $file_data['path'];
|
||||
|
||||
$GLOBALS['__composer_autoload_files'][ $file_identifier ] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares different class sources and returns the newest.
|
||||
*
|
||||
* @param array|null $classmap_data The classmap class data.
|
||||
* @param array|null $psr4_data The PSR-4 class data.
|
||||
*
|
||||
* @return array|null $data
|
||||
*/
|
||||
private function select_newest_file( $classmap_data, $psr4_data ) {
|
||||
if ( ! isset( $classmap_data ) ) {
|
||||
return $psr4_data;
|
||||
} elseif ( ! isset( $psr4_data ) ) {
|
||||
return $classmap_data;
|
||||
}
|
||||
|
||||
if ( $this->version_selector->is_version_update_required( $classmap_data['version'], $psr4_data['version'] ) ) {
|
||||
return $psr4_data;
|
||||
}
|
||||
|
||||
return $classmap_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the file for a given class in a PSR-4 namespace.
|
||||
*
|
||||
* @param string $class_name The class to find.
|
||||
*
|
||||
* @return array|null $data The version and path path to the file if found, null otherwise.
|
||||
*/
|
||||
private function find_psr4_file( $class_name ) {
|
||||
if ( empty( $this->psr4_map ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't bother with classes that have no namespace.
|
||||
$class_index = strrpos( $class_name, '\\' );
|
||||
if ( ! $class_index ) {
|
||||
return null;
|
||||
}
|
||||
$class_for_path = str_replace( '\\', '/', $class_name );
|
||||
|
||||
// Search for the namespace by iteratively cutting off the last segment until
|
||||
// we find a match. This allows us to check the most-specific namespaces
|
||||
// first as well as minimize the amount of time spent looking.
|
||||
for (
|
||||
$class_namespace = substr( $class_name, 0, $class_index );
|
||||
! empty( $class_namespace );
|
||||
$class_namespace = substr( $class_namespace, 0, strrpos( $class_namespace, '\\' ) )
|
||||
) {
|
||||
$namespace = $class_namespace . '\\';
|
||||
if ( ! isset( $this->psr4_map[ $namespace ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$data = $this->psr4_map[ $namespace ];
|
||||
|
||||
foreach ( $data['path'] as $path ) {
|
||||
$path .= '/' . substr( $class_for_path, strlen( $namespace ) ) . '.php';
|
||||
if ( file_exists( $path ) ) {
|
||||
return array(
|
||||
'version' => $data['version'],
|
||||
'path' => $path,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
/* HEADER */ // phpcs:ignore
|
||||
|
||||
/**
|
||||
* Used to select package versions.
|
||||
*/
|
||||
class Version_Selector {
|
||||
|
||||
/**
|
||||
* Checks whether the selected package version should be updated. Composer development
|
||||
* package versions ('9999999-dev' or versions that start with 'dev-') are favored
|
||||
* when the JETPACK_AUTOLOAD_DEV constant is set to true.
|
||||
*
|
||||
* @param String $selected_version The currently selected package version.
|
||||
* @param String $compare_version The package version that is being evaluated to
|
||||
* determine if the version needs to be updated.
|
||||
*
|
||||
* @return bool Returns true if the selected package version should be updated,
|
||||
* else false.
|
||||
*/
|
||||
public function is_version_update_required( $selected_version, $compare_version ) {
|
||||
$use_dev_versions = defined( 'JETPACK_AUTOLOAD_DEV' ) && JETPACK_AUTOLOAD_DEV;
|
||||
|
||||
if ( $selected_version === null ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $use_dev_versions && $this->is_dev_version( $selected_version ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->is_dev_version( $compare_version ) ) {
|
||||
if ( $use_dev_versions ) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( version_compare( $selected_version, $compare_version, '<' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given package version is a development version.
|
||||
*
|
||||
* @param String $version The package version.
|
||||
*
|
||||
* @return bool True if the version is a dev version, else false.
|
||||
*/
|
||||
public function is_dev_version( $version ) {
|
||||
if ( 'dev-' === substr( $version, 0, 4 ) || '9999999-dev' === $version ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [3.0.8] - 2025-04-28
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.7] - 2025-04-14
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.6] - 2025-03-31
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.5] - 2025-03-21
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.4] - 2025-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.3] - 2025-03-05
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [3.0.2] - 2025-02-24
|
||||
### Changed
|
||||
- Update dependencies.
|
||||
|
||||
## [3.0.1] - 2024-11-25
|
||||
### Changed
|
||||
- Updated package dependencies. [#40258]
|
||||
|
||||
## [3.0.0] - 2024-11-14
|
||||
### Removed
|
||||
- General: Update minimum PHP version to 7.2. [#40147]
|
||||
|
||||
## [2.0.5] - 2024-11-04
|
||||
### Added
|
||||
- Enable test coverage. [#39961]
|
||||
|
||||
## [2.0.4] - 2024-08-23
|
||||
### Changed
|
||||
- Updated package dependencies. [#39004]
|
||||
|
||||
## [2.0.3] - 2024-05-29
|
||||
### Fixed
|
||||
- Fix phpdoc type on `Constants::set_constant()` value parameter. [#37606]
|
||||
|
||||
## [2.0.2] - 2024-04-30
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [2.0.1] - 2024-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [2.0.0] - 2023-11-20
|
||||
### Changed
|
||||
- Updated required PHP version to >= 7.0. [#34192]
|
||||
|
||||
## [1.6.23] - 2023-08-23
|
||||
### Changed
|
||||
- Updated package dependencies. [#32605]
|
||||
|
||||
## [1.6.22] - 2023-04-10
|
||||
### Added
|
||||
- Add Jetpack Autoloader package suggestion. [#29988]
|
||||
|
||||
## [1.6.21] - 2023-02-20
|
||||
### Changed
|
||||
- Minor internal updates.
|
||||
|
||||
## [1.6.20] - 2022-12-02
|
||||
### Changed
|
||||
- Updated package dependencies. [#27688]
|
||||
|
||||
## [1.6.19] - 2022-11-22
|
||||
### Changed
|
||||
- Updated package dependencies. [#27043]
|
||||
|
||||
## [1.6.18] - 2022-07-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#25158]
|
||||
|
||||
## [1.6.17] - 2022-06-21
|
||||
### Changed
|
||||
- Renaming master to trunk.
|
||||
|
||||
## [1.6.16] - 2022-04-26
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.15] - 2022-01-25
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.14] - 2022-01-04
|
||||
### Changed
|
||||
- Switch to pcov for code coverage.
|
||||
- Updated package dependencies
|
||||
|
||||
## [1.6.13] - 2021-12-14
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.12] - 2021-11-22
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
## [1.6.11] - 2021-11-02
|
||||
### Changed
|
||||
- Set `convertDeprecationsToExceptions` true in PHPUnit config.
|
||||
- Update PHPUnit configs to include just what needs coverage rather than include everything then try to exclude stuff that doesn't.
|
||||
|
||||
## [1.6.10] - 2021-10-26
|
||||
### Fixed
|
||||
- Updated is_true docblock to be more accurate.
|
||||
|
||||
## [1.6.9] - 2021-10-13
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.8] - 2021-10-06
|
||||
### Changed
|
||||
- Updated package dependencies
|
||||
|
||||
## [1.6.7] - 2021-09-28
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.6] - 2021-08-30
|
||||
### Changed
|
||||
- Run composer update on test-php command instead of phpunit
|
||||
- Tests: update PHPUnit polyfills dependency (yoast/phpunit-polyfills).
|
||||
- Updated versions in annotations
|
||||
|
||||
## [1.6.5] - 2021-05-25
|
||||
### Changed
|
||||
- Updated package dependencies.
|
||||
|
||||
## [1.6.4] - 2021-04-08
|
||||
### Changed
|
||||
- Packaging and build changes, no change to the package itself.
|
||||
|
||||
## [1.6.3] - 2021-03-30
|
||||
### Added
|
||||
- Composer alias for dev-master, to improve dependencies
|
||||
|
||||
### Changed
|
||||
- Update package dependencies.
|
||||
|
||||
### Fixed
|
||||
- Use `composer update` rather than `install` in scripts, as composer.lock isn't checked in.
|
||||
|
||||
## [1.6.2] - 2021-02-05
|
||||
|
||||
- CI: Make tests more generic
|
||||
|
||||
## [1.6.1] - 2021-01-19
|
||||
|
||||
- Add mirror-repo information to all current composer packages
|
||||
- Monorepo: Reorganize all projects
|
||||
|
||||
## [1.6.0] - 2020-12-14
|
||||
|
||||
- Update dependency brain/monkey to v2.6.0
|
||||
- Pin dependencies
|
||||
- Packages: Update for PHP 8 testing
|
||||
|
||||
## [1.5.1] - 2020-10-28
|
||||
|
||||
- Updated PHPCS: Packages and Debugger
|
||||
|
||||
## [1.5.0] - 2020-08-13
|
||||
|
||||
- CI: Try collect js coverage
|
||||
- Docker: Add package testing shortcut
|
||||
|
||||
## [1.4.0] - 2020-07-01
|
||||
|
||||
- Package Unit tests: update test file names to make sure they runs in Travis
|
||||
|
||||
## [1.3.0] - 2020-06-22
|
||||
|
||||
- PHPCS: Clean up the packages
|
||||
|
||||
## [1.2.0] - 2020-04-15
|
||||
|
||||
- Use jp.com redirect in all links
|
||||
- Connection: add a filter for setting Jetpack api constants
|
||||
|
||||
## [1.1.3] - 2019-11-08
|
||||
|
||||
- Packages: Use classmap instead of PSR-4
|
||||
|
||||
## [1.1.2] - 2019-10-28
|
||||
|
||||
- Packages: Add gitattributes files to all packages that need th…
|
||||
|
||||
## [1.1.1] - 2019-09-20
|
||||
|
||||
- Docs: Unify usage of @package phpdoc tags
|
||||
|
||||
## [1.1.0] - 2019-09-14
|
||||
|
||||
## 1.0.0 - 2019-07-09
|
||||
|
||||
- Packages: Finish the constants package
|
||||
|
||||
[3.0.8]: https://github.com/Automattic/jetpack-constants/compare/v3.0.7...v3.0.8
|
||||
[3.0.7]: https://github.com/Automattic/jetpack-constants/compare/v3.0.6...v3.0.7
|
||||
[3.0.6]: https://github.com/Automattic/jetpack-constants/compare/v3.0.5...v3.0.6
|
||||
[3.0.5]: https://github.com/Automattic/jetpack-constants/compare/v3.0.4...v3.0.5
|
||||
[3.0.4]: https://github.com/Automattic/jetpack-constants/compare/v3.0.3...v3.0.4
|
||||
[3.0.3]: https://github.com/Automattic/jetpack-constants/compare/v3.0.2...v3.0.3
|
||||
[3.0.2]: https://github.com/Automattic/jetpack-constants/compare/v3.0.1...v3.0.2
|
||||
[3.0.1]: https://github.com/Automattic/jetpack-constants/compare/v3.0.0...v3.0.1
|
||||
[3.0.0]: https://github.com/Automattic/jetpack-constants/compare/v2.0.5...v3.0.0
|
||||
[2.0.5]: https://github.com/Automattic/jetpack-constants/compare/v2.0.4...v2.0.5
|
||||
[2.0.4]: https://github.com/Automattic/jetpack-constants/compare/v2.0.3...v2.0.4
|
||||
[2.0.3]: https://github.com/Automattic/jetpack-constants/compare/v2.0.2...v2.0.3
|
||||
[2.0.2]: https://github.com/Automattic/jetpack-constants/compare/v2.0.1...v2.0.2
|
||||
[2.0.1]: https://github.com/Automattic/jetpack-constants/compare/v2.0.0...v2.0.1
|
||||
[2.0.0]: https://github.com/Automattic/jetpack-constants/compare/v1.6.23...v2.0.0
|
||||
[1.6.23]: https://github.com/Automattic/jetpack-constants/compare/v1.6.22...v1.6.23
|
||||
[1.6.22]: https://github.com/Automattic/jetpack-constants/compare/v1.6.21...v1.6.22
|
||||
[1.6.21]: https://github.com/Automattic/jetpack-constants/compare/v1.6.20...v1.6.21
|
||||
[1.6.20]: https://github.com/Automattic/jetpack-constants/compare/v1.6.19...v1.6.20
|
||||
[1.6.19]: https://github.com/Automattic/jetpack-constants/compare/v1.6.18...v1.6.19
|
||||
[1.6.18]: https://github.com/Automattic/jetpack-constants/compare/v1.6.17...v1.6.18
|
||||
[1.6.17]: https://github.com/Automattic/jetpack-constants/compare/v1.6.16...v1.6.17
|
||||
[1.6.16]: https://github.com/Automattic/jetpack-constants/compare/v1.6.15...v1.6.16
|
||||
[1.6.15]: https://github.com/Automattic/jetpack-constants/compare/v1.6.14...v1.6.15
|
||||
[1.6.14]: https://github.com/Automattic/jetpack-constants/compare/v1.6.13...v1.6.14
|
||||
[1.6.13]: https://github.com/Automattic/jetpack-constants/compare/v1.6.12...v1.6.13
|
||||
[1.6.12]: https://github.com/Automattic/jetpack-constants/compare/v1.6.11...v1.6.12
|
||||
[1.6.11]: https://github.com/Automattic/jetpack-constants/compare/v1.6.10...v1.6.11
|
||||
[1.6.10]: https://github.com/Automattic/jetpack-constants/compare/v1.6.9...v1.6.10
|
||||
[1.6.9]: https://github.com/Automattic/jetpack-constants/compare/v1.6.8...v1.6.9
|
||||
[1.6.8]: https://github.com/Automattic/jetpack-constants/compare/v1.6.7...v1.6.8
|
||||
[1.6.7]: https://github.com/Automattic/jetpack-constants/compare/v1.6.6...v1.6.7
|
||||
[1.6.6]: https://github.com/Automattic/jetpack-constants/compare/v1.6.5...v1.6.6
|
||||
[1.6.5]: https://github.com/Automattic/jetpack-constants/compare/v1.6.4...v1.6.5
|
||||
[1.6.4]: https://github.com/Automattic/jetpack-constants/compare/v1.6.3...v1.6.4
|
||||
[1.6.3]: https://github.com/Automattic/jetpack-constants/compare/v1.6.2...v1.6.3
|
||||
[1.6.2]: https://github.com/Automattic/jetpack-constants/compare/v1.6.1...v1.6.2
|
||||
[1.6.1]: https://github.com/Automattic/jetpack-constants/compare/v1.6.0...v1.6.1
|
||||
[1.6.0]: https://github.com/Automattic/jetpack-constants/compare/v1.5.1...v1.6.0
|
||||
[1.5.1]: https://github.com/Automattic/jetpack-constants/compare/v1.5.0...v1.5.1
|
||||
[1.5.0]: https://github.com/Automattic/jetpack-constants/compare/v1.4.0...v1.5.0
|
||||
[1.4.0]: https://github.com/Automattic/jetpack-constants/compare/v1.3.0...v1.4.0
|
||||
[1.3.0]: https://github.com/Automattic/jetpack-constants/compare/v1.2.0...v1.3.0
|
||||
[1.2.0]: https://github.com/Automattic/jetpack-constants/compare/v1.1.3...v1.2.0
|
||||
[1.1.3]: https://github.com/Automattic/jetpack-constants/compare/v1.1.2...v1.1.3
|
||||
[1.1.2]: https://github.com/Automattic/jetpack-constants/compare/v1.1.1...v1.1.2
|
||||
[1.1.1]: https://github.com/Automattic/jetpack-constants/compare/v1.1.0...v1.1.1
|
||||
[1.1.0]: https://github.com/Automattic/jetpack-constants/compare/v1.0.0...v1.1.0
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# Jetpack Constants
|
||||
|
||||
A simple constant manager for Jetpack.
|
||||
|
||||
Testing constants is hard. Once you define a constant in PHP, it's defined. Constants Manager is an abstraction layer so that unit tests can set constants for tests.
|
||||
|
||||
### Usage
|
||||
|
||||
Retrieve the value of a constant `CONSTANT_NAME` (returns `null` if it's not defined):
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
$constant_value = Constants::get_constant( 'CONSTANT_NAME' );
|
||||
```
|
||||
|
||||
Set the value of a constant `CONSTANT_NAME` to a particular value:
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
$value = 'some value';
|
||||
Constants::set_constant( 'CONSTANT_NAME', $value );
|
||||
```
|
||||
|
||||
Check whether a constant `CONSTANT_NAME` is defined:
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
$defined = Constants::is_defined( 'CONSTANT_NAME' );
|
||||
```
|
||||
|
||||
Check whether a constant `CONSTANT_NAME` is truthy:
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
$is_truthy = Constants::is_true( 'CONSTANT_NAME' );
|
||||
```
|
||||
|
||||
Delete the `CONSTANT_NAME` constant:
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
Constants::clear_single_constant( 'CONSTANT_NAME' );
|
||||
```
|
||||
|
||||
Delete all known constants:
|
||||
|
||||
```php
|
||||
use Automattic\Jetpack\Constants;
|
||||
|
||||
Constants::clear_constants();
|
||||
```
|
||||
## Using this package in your WordPress plugin
|
||||
|
||||
If you plan on using this package in your WordPress plugin, we would recommend that you use [Jetpack Autoloader](https://packagist.org/packages/automattic/jetpack-autoloader) as your autoloader. This will allow for maximum interoperability with other plugins that use this package as well.
|
||||
|
||||
## Security
|
||||
|
||||
Need to report a security vulnerability? Go to [https://automattic.com/security/](https://automattic.com/security/) or directly to our security bug bounty site [https://hackerone.com/automattic](https://hackerone.com/automattic).
|
||||
|
||||
## License
|
||||
|
||||
jetpack-constants is licensed under [GNU General Public License v2 (or later)](./LICENSE.txt)
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
/**
|
||||
* A constants manager for Jetpack.
|
||||
*
|
||||
* @package automattic/jetpack-constants
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack;
|
||||
|
||||
/**
|
||||
* Class Automattic\Jetpack\Constants
|
||||
*
|
||||
* Testing constants is hard. Once you define a constant, it's defined. Constants Manager is an
|
||||
* abstraction layer so that unit tests can set "constants" for tests.
|
||||
*
|
||||
* To test your code, you'll need to swap out `defined( 'CONSTANT' )` with `Automattic\Jetpack\Constants::is_defined( 'CONSTANT' )`
|
||||
* and replace `CONSTANT` with `Automattic\Jetpack\Constants::get_constant( 'CONSTANT' )`. Then in the unit test, you can set the
|
||||
* constant with `Automattic\Jetpack\Constants::set_constant( 'CONSTANT', $value )` and then clean up after each test with something like
|
||||
* this:
|
||||
*
|
||||
* function tearDown() {
|
||||
* Automattic\Jetpack\Constants::clear_constants();
|
||||
* }
|
||||
*/
|
||||
class Constants {
|
||||
/**
|
||||
* A container for all defined constants.
|
||||
*
|
||||
* @access public
|
||||
* @static
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $set_constants = array();
|
||||
|
||||
/**
|
||||
* Checks if a "constant" has been set in constants Manager
|
||||
* and has a truthy value (e.g. not null, not false, not 0, any string).
|
||||
*
|
||||
* @param string $name The name of the constant.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_true( $name ) {
|
||||
return self::is_defined( $name ) && self::get_constant( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a "constant" has been set in constants Manager, and if not,
|
||||
* checks if the constant was defined with define( 'name', 'value ).
|
||||
*
|
||||
* @param string $name The name of the constant.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_defined( $name ) {
|
||||
return array_key_exists( $name, self::$set_constants )
|
||||
? true
|
||||
: defined( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve the "constant" from constants Manager, and if it hasn't been set,
|
||||
* then attempts to get the constant with the constant() function. If that also hasn't
|
||||
* been set, attempts to get a value from filters.
|
||||
*
|
||||
* @param string $name The name of the constant.
|
||||
*
|
||||
* @return mixed null if the constant does not exist or the value of the constant.
|
||||
*/
|
||||
public static function get_constant( $name ) {
|
||||
if ( array_key_exists( $name, self::$set_constants ) ) {
|
||||
return self::$set_constants[ $name ];
|
||||
}
|
||||
|
||||
if ( defined( $name ) ) {
|
||||
return constant( $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the value of the constant.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*
|
||||
* @param null The constant value to be filtered. The default is null.
|
||||
* @param String $name The constant name.
|
||||
*/
|
||||
return apply_filters( 'jetpack_constant_default_value', null, $name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the "constant" within constants Manager.
|
||||
*
|
||||
* @param string $name The name of the constant.
|
||||
* @param int|float|string|bool|array|null $value The value of the constant.
|
||||
*/
|
||||
public static function set_constant( $name, $value ) {
|
||||
self::$set_constants[ $name ] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will unset a "constant" from constants Manager if the constant exists.
|
||||
*
|
||||
* @param string $name The name of the constant.
|
||||
*
|
||||
* @return bool Whether the constant was removed.
|
||||
*/
|
||||
public static function clear_single_constant( $name ) {
|
||||
if ( ! array_key_exists( $name, self::$set_constants ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unset( self::$set_constants[ $name ] );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all of the constants within constants Manager.
|
||||
*/
|
||||
public static function clear_constants() {
|
||||
self::$set_constants = array();
|
||||
}
|
||||
}
|
||||
|
|
@ -26,23 +26,12 @@ use Composer\Semver\VersionParser;
|
|||
*/
|
||||
class InstalledVersions
|
||||
{
|
||||
/**
|
||||
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
|
||||
* @internal
|
||||
*/
|
||||
private static $selfDir = null;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||
*/
|
||||
private static $installed;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private static $installedIsLocalDir;
|
||||
|
||||
/**
|
||||
* @var bool|null
|
||||
*/
|
||||
|
|
@ -320,24 +309,6 @@ class InstalledVersions
|
|||
{
|
||||
self::$installed = $data;
|
||||
self::$installedByVendor = array();
|
||||
|
||||
// when using reload, we disable the duplicate protection to ensure that self::$installed data is
|
||||
// always returned, but we cannot know whether it comes from the installed.php in __DIR__ or not,
|
||||
// so we have to assume it does not, and that may result in duplicate data being returned when listing
|
||||
// all installed packages for example
|
||||
self::$installedIsLocalDir = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private static function getSelfDir()
|
||||
{
|
||||
if (self::$selfDir === null) {
|
||||
self::$selfDir = strtr(__DIR__, '\\', '/');
|
||||
}
|
||||
|
||||
return self::$selfDir;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -351,27 +322,19 @@ class InstalledVersions
|
|||
}
|
||||
|
||||
$installed = array();
|
||||
$copiedLocalDir = false;
|
||||
|
||||
if (self::$canGetVendors) {
|
||||
$selfDir = self::getSelfDir();
|
||||
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||
$vendorDir = strtr($vendorDir, '\\', '/');
|
||||
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||
$installed[] = self::$installedByVendor[$vendorDir];
|
||||
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||
$required = require $vendorDir.'/composer/installed.php';
|
||||
self::$installedByVendor[$vendorDir] = $required;
|
||||
$installed[] = $required;
|
||||
if (self::$installed === null && $vendorDir.'/composer' === $selfDir) {
|
||||
self::$installed = $required;
|
||||
self::$installedIsLocalDir = true;
|
||||
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||
self::$installed = $installed[count($installed) - 1];
|
||||
}
|
||||
}
|
||||
if (self::$installedIsLocalDir && $vendorDir.'/composer' === $selfDir) {
|
||||
$copiedLocalDir = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -387,7 +350,7 @@ class InstalledVersions
|
|||
}
|
||||
}
|
||||
|
||||
if (self::$installed !== array() && !$copiedLocalDir) {
|
||||
if (self::$installed !== array()) {
|
||||
$installed[] = self::$installed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ $vendorDir = dirname(__DIR__);
|
|||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadFileWriter' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadFileWriter.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadGenerator' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadGenerator.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadProcessor' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadProcessor.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\CustomAutoloaderPlugin' => $vendorDir . '/automattic/jetpack-autoloader/src/CustomAutoloaderPlugin.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\ManifestGenerator' => $vendorDir . '/automattic/jetpack-autoloader/src/ManifestGenerator.php',
|
||||
'Automattic\\Jetpack\\Constants' => $vendorDir . '/automattic/jetpack-constants/src/class-constants.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Collector' => $baseDir . '/src/Internal/Telemetry/Collector.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Events' => $baseDir . '/src/Internal/Telemetry/Events.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Orders' => $baseDir . '/src/Internal/Telemetry/Orders.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Products' => $baseDir . '/src/Internal/Telemetry/Products.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Subscriptions' => $baseDir . '/src/Internal/Telemetry/Subscriptions.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Scheduled_Actions' => $baseDir . '/src/Internal/Utilities/Scheduled_Actions.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Composer\\Installers\\AglInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AglInstaller.php',
|
||||
'Composer\\Installers\\AkauntingInstaller' => $vendorDir . '/composer/installers/src/Composer/Installers/AkauntingInstaller.php',
|
||||
|
|
|
|||
|
|
@ -8,5 +8,4 @@ $baseDir = dirname($vendorDir);
|
|||
return array(
|
||||
'Composer\\Installers\\' => array($vendorDir . '/composer/installers/src/Composer/Installers'),
|
||||
'Automattic\\WooCommerce_Subscriptions\\' => array($baseDir . '/src'),
|
||||
'Automattic\\Jetpack\\Autoloader\\' => array($vendorDir . '/automattic/jetpack-autoloader/src'),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInit32625eaf0064549a4f20b6231a37a93c
|
||||
class ComposerAutoloaderInitcb45de1ca955f89ec737c442c7cf101c
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
|
|
@ -24,12 +24,12 @@ class ComposerAutoloaderInit32625eaf0064549a4f20b6231a37a93c
|
|||
|
||||
require __DIR__ . '/platform_check.php';
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInit32625eaf0064549a4f20b6231a37a93c', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitcb45de1ca955f89ec737c442c7cf101c', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit32625eaf0064549a4f20b6231a37a93c', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitcb45de1ca955f89ec737c442c7cf101c', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit32625eaf0064549a4f20b6231a37a93c::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c::getInitializer($loader));
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit32625eaf0064549a4f20b6231a37a93c
|
||||
class ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'C' =>
|
||||
|
|
@ -14,7 +14,6 @@ class ComposerStaticInit32625eaf0064549a4f20b6231a37a93c
|
|||
'A' =>
|
||||
array (
|
||||
'Automattic\\WooCommerce_Subscriptions\\' => 37,
|
||||
'Automattic\\Jetpack\\Autoloader\\' => 30,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -27,18 +26,16 @@ class ComposerStaticInit32625eaf0064549a4f20b6231a37a93c
|
|||
array (
|
||||
0 => __DIR__ . '/../..' . '/src',
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadFileWriter' => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src/AutoloadFileWriter.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadGenerator' => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src/AutoloadGenerator.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadProcessor' => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src/AutoloadProcessor.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\CustomAutoloaderPlugin' => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src/CustomAutoloaderPlugin.php',
|
||||
'Automattic\\Jetpack\\Autoloader\\ManifestGenerator' => __DIR__ . '/..' . '/automattic/jetpack-autoloader/src/ManifestGenerator.php',
|
||||
'Automattic\\Jetpack\\Constants' => __DIR__ . '/..' . '/automattic/jetpack-constants/src/class-constants.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Collector' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Collector.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Events' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Events.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Orders' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Orders.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Products' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Products.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Telemetry\\Subscriptions' => __DIR__ . '/../..' . '/src/Internal/Telemetry/Subscriptions.php',
|
||||
'Automattic\\WooCommerce_Subscriptions\\Internal\\Utilities\\Scheduled_Actions' => __DIR__ . '/../..' . '/src/Internal/Utilities/Scheduled_Actions.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Composer\\Installers\\AglInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AglInstaller.php',
|
||||
'Composer\\Installers\\AkauntingInstaller' => __DIR__ . '/..' . '/composer/installers/src/Composer/Installers/AkauntingInstaller.php',
|
||||
|
|
@ -168,9 +165,9 @@ class ComposerStaticInit32625eaf0064549a4f20b6231a37a93c
|
|||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit32625eaf0064549a4f20b6231a37a93c::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit32625eaf0064549a4f20b6231a37a93c::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit32625eaf0064549a4f20b6231a37a93c::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitcb45de1ca955f89ec737c442c7cf101c::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,72 +1,59 @@
|
|||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "automattic/jetpack-autoloader",
|
||||
"version": "v5.0.10",
|
||||
"version_normalized": "5.0.10.0",
|
||||
"name": "automattic/jetpack-constants",
|
||||
"version": "v3.0.8",
|
||||
"version_normalized": "3.0.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Automattic/jetpack-autoloader.git",
|
||||
"reference": "f7e2142139b925fac0a167ed0cbc71e2592bd9a0"
|
||||
"url": "https://github.com/Automattic/jetpack-constants.git",
|
||||
"reference": "f9bf00ab48956b8326209e7c0baf247a0ed721c4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/f7e2142139b925fac0a167ed0cbc71e2592bd9a0",
|
||||
"reference": "f7e2142139b925fac0a167ed0cbc71e2592bd9a0",
|
||||
"url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/f9bf00ab48956b8326209e7c0baf247a0ed721c4",
|
||||
"reference": "f9bf00ab48956b8326209e7c0baf247a0ed721c4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-plugin-api": "^2.2",
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"automattic/jetpack-changelogger": "^6.0.7",
|
||||
"automattic/jetpack-changelogger": "^6.0.5",
|
||||
"automattic/phpunit-select-config": "^1.0.3",
|
||||
"composer/composer": "^2.2",
|
||||
"brain/monkey": "^2.6.2",
|
||||
"yoast/phpunit-polyfills": "^4.0.0"
|
||||
},
|
||||
"time": "2025-09-15T14:36:53+00:00",
|
||||
"type": "composer-plugin",
|
||||
"suggest": {
|
||||
"automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package."
|
||||
},
|
||||
"time": "2025-04-28T15:12:45+00:00",
|
||||
"type": "jetpack-library",
|
||||
"extra": {
|
||||
"class": "Automattic\\Jetpack\\Autoloader\\CustomAutoloaderPlugin",
|
||||
"autotagger": true,
|
||||
"mirror-repo": "Automattic/jetpack-autoloader",
|
||||
"mirror-repo": "Automattic/jetpack-constants",
|
||||
"branch-alias": {
|
||||
"dev-trunk": "5.0.x-dev"
|
||||
"dev-trunk": "3.0.x-dev"
|
||||
},
|
||||
"changelogger": {
|
||||
"link-template": "https://github.com/Automattic/jetpack-autoloader/compare/v${old}...v${new}"
|
||||
},
|
||||
"version-constants": {
|
||||
"::VERSION": "src/AutoloadGenerator.php"
|
||||
"link-template": "https://github.com/Automattic/jetpack-constants/compare/v${old}...v${new}"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Automattic\\Jetpack\\Autoloader\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/AutoloadGenerator.php"
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"description": "Creates a custom autoloader for a plugin or theme.",
|
||||
"keywords": [
|
||||
"autoload",
|
||||
"autoloader",
|
||||
"composer",
|
||||
"jetpack",
|
||||
"plugin",
|
||||
"wordpress"
|
||||
],
|
||||
"description": "A wrapper for defining constants in a more testable way.",
|
||||
"support": {
|
||||
"source": "https://github.com/Automattic/jetpack-autoloader/tree/v5.0.10"
|
||||
"source": "https://github.com/Automattic/jetpack-constants/tree/v3.0.8"
|
||||
},
|
||||
"install-path": "../automattic/jetpack-autoloader"
|
||||
"install-path": "../automattic/jetpack-constants"
|
||||
},
|
||||
{
|
||||
"name": "composer/installers",
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'woocommerce/woocommerce-subscriptions',
|
||||
'pretty_version' => 'dev-release/7.9.0',
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'reference' => '9114ff6422e5a37b9ccca8c6954172b07ffd9cae',
|
||||
'pretty_version' => 'dev-release/8.0.0',
|
||||
'version' => 'dev-release/8.0.0',
|
||||
'reference' => 'fae6f1f47d4716196c53f3d73845d84afd815c63',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev' => false,
|
||||
),
|
||||
'versions' => array(
|
||||
'automattic/jetpack-autoloader' => array(
|
||||
'pretty_version' => 'v5.0.10',
|
||||
'version' => '5.0.10.0',
|
||||
'reference' => 'f7e2142139b925fac0a167ed0cbc71e2592bd9a0',
|
||||
'type' => 'composer-plugin',
|
||||
'install_path' => __DIR__ . '/../automattic/jetpack-autoloader',
|
||||
'automattic/jetpack-constants' => array(
|
||||
'pretty_version' => 'v3.0.8',
|
||||
'version' => '3.0.8.0',
|
||||
'reference' => 'f9bf00ab48956b8326209e7c0baf247a0ed721c4',
|
||||
'type' => 'jetpack-library',
|
||||
'install_path' => __DIR__ . '/../automattic/jetpack-constants',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
|
|
@ -29,9 +29,9 @@
|
|||
'dev_requirement' => false,
|
||||
),
|
||||
'woocommerce/woocommerce-subscriptions' => array(
|
||||
'pretty_version' => 'dev-release/7.9.0',
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'reference' => '9114ff6422e5a37b9ccca8c6954172b07ffd9cae',
|
||||
'pretty_version' => 'dev-release/8.0.0',
|
||||
'version' => 'dev-release/8.0.0',
|
||||
'reference' => 'fae6f1f47d4716196c53f3d73845d84afd815c63',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
|
|
|||
|
|
@ -1,577 +0,0 @@
|
|||
<?php
|
||||
|
||||
// This file `jetpack_autoload_classmap.php` was auto generated by automattic/jetpack-autoloader.
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Autoloader' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-autoloader.php'
|
||||
),
|
||||
'Autoloader_Handler' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-autoloader-handler.php'
|
||||
),
|
||||
'Autoloader_Locator' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-autoloader-locator.php'
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadFileWriter' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadFileWriter.php'
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadGenerator' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadGenerator.php'
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\AutoloadProcessor' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/AutoloadProcessor.php'
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\CustomAutoloaderPlugin' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/CustomAutoloaderPlugin.php'
|
||||
),
|
||||
'Automattic\\Jetpack\\Autoloader\\ManifestGenerator' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/ManifestGenerator.php'
|
||||
),
|
||||
'Composer\\Installers\\AglInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/AglInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\AkauntingInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/AkauntingInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\AnnotateCmsInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\AsgardInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/AsgardInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\AttogramInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/AttogramInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\BaseInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/BaseInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\BitrixInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/BitrixInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\BonefishInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/BonefishInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\BotbleInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/BotbleInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\CakePHPInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/CakePHPInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ChefInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ChefInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\CiviCrmInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/CiviCrmInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ClanCatsFrameworkInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\CockpitInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/CockpitInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\CodeIgniterInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\Concrete5Installer' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/Concrete5Installer.php'
|
||||
),
|
||||
'Composer\\Installers\\ConcreteCMSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ConcreteCMSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\CroogoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/CroogoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\DecibelInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/DecibelInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\DframeInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/DframeInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\DokuWikiInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/DokuWikiInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\DolibarrInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/DolibarrInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\DrupalInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/DrupalInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ElggInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ElggInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\EliasisInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/EliasisInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ExpressionEngineInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\EzPlatformInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/EzPlatformInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ForkCMSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ForkCMSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\FuelInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/FuelInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\FuelphpInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/FuelphpInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\GravInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/GravInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\HuradInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/HuradInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ImageCMSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ImageCMSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\Installer' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/Installer.php'
|
||||
),
|
||||
'Composer\\Installers\\ItopInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ItopInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\KanboardInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/KanboardInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\KnownInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/KnownInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\KodiCMSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/KodiCMSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\KohanaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/KohanaInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\LanManagementSystemInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\LaravelInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/LaravelInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\LavaLiteInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/LavaLiteInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\LithiumInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/LithiumInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MODULEWorkInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MODXEvoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MODXEvoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MagentoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MagentoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MajimaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MajimaInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MakoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MakoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MantisBTInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MantisBTInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MatomoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MatomoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MauticInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MauticInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MayaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MayaInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MediaWikiInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MediaWikiInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MiaoxingInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MiaoxingInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MicroweberInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MicroweberInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ModxInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ModxInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\MoodleInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/MoodleInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\OctoberInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/OctoberInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\OntoWikiInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/OntoWikiInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\OsclassInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/OsclassInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\OxidInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/OxidInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PPIInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PPIInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PantheonInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PantheonInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PhiftyInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PhiftyInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PhpBBInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PhpBBInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PiwikInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PiwikInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PlentymarketsInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\Plugin' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/Plugin.php'
|
||||
),
|
||||
'Composer\\Installers\\PortoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PortoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PrestashopInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PrestashopInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ProcessWireInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ProcessWireInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PuppetInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PuppetInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\PxcmsInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/PxcmsInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\RadPHPInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/RadPHPInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ReIndexInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ReIndexInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\Redaxo5Installer' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/Redaxo5Installer.php'
|
||||
),
|
||||
'Composer\\Installers\\RedaxoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/RedaxoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\RoundcubeInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/RoundcubeInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\SMFInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/SMFInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ShopwareInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ShopwareInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\SilverStripeInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/SilverStripeInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\SiteDirectInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/SiteDirectInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\StarbugInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/StarbugInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\SyDESInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/SyDESInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\SyliusInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/SyliusInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\TaoInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/TaoInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\TastyIgniterInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/TastyIgniterInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\TheliaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/TheliaInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\TuskInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/TuskInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\UserFrostingInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/UserFrostingInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\VanillaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/VanillaInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\VgmcpInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/VgmcpInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\WHMCSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/WHMCSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\WinterInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/WinterInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\WolfCMSInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/WolfCMSInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\WordPressInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/WordPressInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\YawikInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/YawikInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ZendInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ZendInstaller.php'
|
||||
),
|
||||
'Composer\\Installers\\ZikulaInstaller' => array(
|
||||
'version' => '2.3.0.0',
|
||||
'path' => $vendorDir . '/composer/installers/src/Composer/Installers/ZikulaInstaller.php'
|
||||
),
|
||||
'Container' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-container.php'
|
||||
),
|
||||
'Hook_Manager' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-hook-manager.php'
|
||||
),
|
||||
'Latest_Autoloader_Guard' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-latest-autoloader-guard.php'
|
||||
),
|
||||
'Manifest_Reader' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-manifest-reader.php'
|
||||
),
|
||||
'PHP_Autoloader' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-php-autoloader.php'
|
||||
),
|
||||
'Path_Processor' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-path-processor.php'
|
||||
),
|
||||
'Plugin_Locator' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-plugin-locator.php'
|
||||
),
|
||||
'Plugins_Handler' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-plugins-handler.php'
|
||||
),
|
||||
'Shutdown_Handler' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-shutdown-handler.php'
|
||||
),
|
||||
'Version_Loader' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-version-loader.php'
|
||||
),
|
||||
'Version_Selector' => array(
|
||||
'version' => '5.0.10',
|
||||
'path' => $vendorDir . '/automattic/jetpack-autoloader/src/class-version-selector.php'
|
||||
),
|
||||
'WCSG_Admin' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-admin.php'
|
||||
),
|
||||
'WCSG_Admin_Order' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/admin/class-wcsg-admin-order.php'
|
||||
),
|
||||
'WCSG_Admin_System_Status' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-admin-system-status.php'
|
||||
),
|
||||
'WCSG_Admin_Welcome_Announcement' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-admin-welcome-announcement.php'
|
||||
),
|
||||
'WCSG_Blocks_Integration' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-blocks-integration.php'
|
||||
),
|
||||
'WCSG_Cart' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-cart.php'
|
||||
),
|
||||
'WCSG_Checkout' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-checkout.php'
|
||||
),
|
||||
'WCSG_Download_Handler' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-download-handler.php'
|
||||
),
|
||||
'WCSG_Email' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-email.php'
|
||||
),
|
||||
'WCSG_Email_Completed_Renewal_Order' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/emails/class-wcsg-email-completed-renewal-order.php'
|
||||
),
|
||||
'WCSG_Email_Customer_New_Account' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/emails/class-wcsg-email-customer-new-account.php'
|
||||
),
|
||||
'WCSG_Email_Processing_Renewal_Order' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/emails/class-wcsg-email-processing-renewal-order.php'
|
||||
),
|
||||
'WCSG_Email_Recipient_New_Initial_Order' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/emails/class-wcsg-email-recipient-new-initial-order.php'
|
||||
),
|
||||
'WCSG_Memberships_Integration' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-memberships-integration.php'
|
||||
),
|
||||
'WCSG_Privacy' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/privacy/class-wcsg-privacy.php'
|
||||
),
|
||||
'WCSG_Privacy_Erasers' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/privacy/class-wcsg-privacy-erasers.php'
|
||||
),
|
||||
'WCSG_Privacy_Exporters' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/privacy/class-wcsg-privacy-exporters.php'
|
||||
),
|
||||
'WCSG_Product' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-product.php'
|
||||
),
|
||||
'WCSG_Query' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-query.php'
|
||||
),
|
||||
'WCSG_Recipient_Addresses' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-recipient-addresses.php'
|
||||
),
|
||||
'WCSG_Recipient_Details' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-recipient-details.php'
|
||||
),
|
||||
'WCSG_Recipient_Management' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-recipient-management.php'
|
||||
),
|
||||
'WCSG_Template_Loader' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcsg-template-loader.php'
|
||||
),
|
||||
'WCS_Gifting' => array(
|
||||
'version' => 'dev-release/7.9.0',
|
||||
'path' => $baseDir . '/includes/gifting/class-wcs-gifting.php'
|
||||
),
|
||||
);
|
||||
|
|
@ -19,7 +19,8 @@ if ($issues) {
|
|||
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||
}
|
||||
}
|
||||
throw new \RuntimeException(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues)
|
||||
trigger_error(
|
||||
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,147 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
use Automattic\Jetpack\Autoloader\AutoloadGenerator;
|
||||
|
||||
/**
|
||||
* This class selects the package version for the autoloader.
|
||||
*/
|
||||
class Autoloader_Handler {
|
||||
|
||||
/**
|
||||
* The PHP_Autoloader instance.
|
||||
*
|
||||
* @var PHP_Autoloader
|
||||
*/
|
||||
private $php_autoloader;
|
||||
|
||||
/**
|
||||
* The Hook_Manager instance.
|
||||
*
|
||||
* @var Hook_Manager
|
||||
*/
|
||||
private $hook_manager;
|
||||
|
||||
/**
|
||||
* The Manifest_Reader instance.
|
||||
*
|
||||
* @var Manifest_Reader
|
||||
*/
|
||||
private $manifest_reader;
|
||||
|
||||
/**
|
||||
* The Version_Selector instance.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param PHP_Autoloader $php_autoloader The PHP_Autoloader instance.
|
||||
* @param Hook_Manager $hook_manager The Hook_Manager instance.
|
||||
* @param Manifest_Reader $manifest_reader The Manifest_Reader instance.
|
||||
* @param Version_Selector $version_selector The Version_Selector instance.
|
||||
*/
|
||||
public function __construct( $php_autoloader, $hook_manager, $manifest_reader, $version_selector ) {
|
||||
$this->php_autoloader = $php_autoloader;
|
||||
$this->hook_manager = $hook_manager;
|
||||
$this->manifest_reader = $manifest_reader;
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether or not an autoloader is currently in the process of initializing.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_initializing() {
|
||||
// If no version has been set it means that no autoloader has started initializing yet.
|
||||
global $jetpack_autoloader_latest_version;
|
||||
if ( ! isset( $jetpack_autoloader_latest_version ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// When the version is set but the classmap is not it ALWAYS means that this is the
|
||||
// latest autoloader and is being included by an older one.
|
||||
global $jetpack_packages_classmap;
|
||||
if ( empty( $jetpack_packages_classmap ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Version 2.4.0 added a new global and altered the reset semantics. We need to check
|
||||
// the other global as well since it may also point at initialization.
|
||||
// Note: We don't need to check for the class first because every autoloader that
|
||||
// will set the latest version global requires this class in the classmap.
|
||||
$replacing_version = $jetpack_packages_classmap[ AutoloadGenerator::class ]['version'];
|
||||
if ( $this->version_selector->is_dev_version( $replacing_version ) || version_compare( $replacing_version, '2.4.0.0', '>=' ) ) {
|
||||
global $jetpack_autoloader_loader;
|
||||
if ( ! isset( $jetpack_autoloader_loader ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates an autoloader using the given plugins and activates it.
|
||||
*
|
||||
* @param string[] $plugins The plugins to initialize the autoloader for.
|
||||
*/
|
||||
public function activate_autoloader( $plugins ) {
|
||||
global $jetpack_packages_psr4;
|
||||
$jetpack_packages_psr4 = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_psr4.php', $jetpack_packages_psr4 );
|
||||
|
||||
global $jetpack_packages_classmap;
|
||||
$jetpack_packages_classmap = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_classmap.php', $jetpack_packages_classmap );
|
||||
|
||||
global $jetpack_packages_filemap;
|
||||
$jetpack_packages_filemap = array();
|
||||
$this->manifest_reader->read_manifests( $plugins, 'vendor/composer/jetpack_autoload_filemap.php', $jetpack_packages_filemap );
|
||||
|
||||
$loader = new Version_Loader(
|
||||
$this->version_selector,
|
||||
$jetpack_packages_classmap,
|
||||
$jetpack_packages_psr4,
|
||||
$jetpack_packages_filemap
|
||||
);
|
||||
|
||||
$this->php_autoloader->register_autoloader( $loader );
|
||||
|
||||
// Now that the autoloader is active we can load the filemap.
|
||||
$loader->load_filemap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the active autoloader and all related global state.
|
||||
*/
|
||||
public function reset_autoloader() {
|
||||
$this->php_autoloader->unregister_autoloader();
|
||||
$this->hook_manager->reset();
|
||||
|
||||
// Clear all of the autoloader globals so that older autoloaders don't do anything strange.
|
||||
global $jetpack_autoloader_latest_version;
|
||||
$jetpack_autoloader_latest_version = null;
|
||||
|
||||
global $jetpack_packages_classmap;
|
||||
$jetpack_packages_classmap = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
|
||||
global $jetpack_packages_psr4;
|
||||
$jetpack_packages_psr4 = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
|
||||
global $jetpack_packages_filemap;
|
||||
$jetpack_packages_filemap = array(); // Must be array to avoid exceptions in old autoloaders!
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
use Automattic\Jetpack\Autoloader\AutoloadGenerator;
|
||||
|
||||
/**
|
||||
* This class locates autoloaders.
|
||||
*/
|
||||
class Autoloader_Locator {
|
||||
|
||||
/**
|
||||
* The object for comparing autoloader versions.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Version_Selector $version_selector The version selector object.
|
||||
*/
|
||||
public function __construct( $version_selector ) {
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the plugin with the latest autoloader.
|
||||
*
|
||||
* @param array $plugin_paths An array of plugin paths.
|
||||
* @param string $latest_version The latest version reference. @phan-output-reference.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function find_latest_autoloader( $plugin_paths, &$latest_version ) {
|
||||
$latest_plugin = null;
|
||||
|
||||
foreach ( $plugin_paths as $plugin_path ) {
|
||||
$version = $this->get_autoloader_version( $plugin_path );
|
||||
if ( ! $version || ! $this->version_selector->is_version_update_required( $latest_version, $version ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$latest_version = $version;
|
||||
$latest_plugin = $plugin_path;
|
||||
}
|
||||
|
||||
return $latest_plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the autoloader.
|
||||
*
|
||||
* @param string $plugin_path The path to the plugin.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_autoloader_path( $plugin_path ) {
|
||||
return trailingslashit( $plugin_path ) . 'vendor/autoload_packages.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version for the autoloader.
|
||||
*
|
||||
* @param string $plugin_path The path to the plugin.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function get_autoloader_version( $plugin_path ) {
|
||||
$classmap = trailingslashit( $plugin_path ) . 'vendor/composer/jetpack_autoload_classmap.php';
|
||||
if ( ! file_exists( $classmap ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classmap = require $classmap;
|
||||
if ( isset( $classmap[ AutoloadGenerator::class ] ) ) {
|
||||
return $classmap[ AutoloadGenerator::class ]['version'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class handles management of the actual PHP autoloader.
|
||||
*/
|
||||
class Autoloader {
|
||||
|
||||
/**
|
||||
* Checks to see whether or not the autoloader should be initialized and then initializes it if so.
|
||||
*
|
||||
* @param Container|null $container The container we want to use for autoloader initialization. If none is given
|
||||
* then a container will be created automatically.
|
||||
*/
|
||||
public static function init( $container = null ) {
|
||||
// The container holds and manages the lifecycle of our dependencies
|
||||
// to make them easier to work with and increase flexibility.
|
||||
if ( ! isset( $container ) ) {
|
||||
require_once __DIR__ . '/class-container.php';
|
||||
$container = new Container();
|
||||
}
|
||||
|
||||
// phpcs:disable Generic.Commenting.DocComment.MissingShort
|
||||
|
||||
/** @var Autoloader_Handler $autoloader_handler */
|
||||
$autoloader_handler = $container->get( Autoloader_Handler::class );
|
||||
|
||||
// If the autoloader is already initializing it means that it has included us as the latest.
|
||||
$was_included_by_autoloader = $autoloader_handler->is_initializing();
|
||||
|
||||
/** @var Plugin_Locator $plugin_locator */
|
||||
$plugin_locator = $container->get( Plugin_Locator::class );
|
||||
|
||||
/** @var Plugins_Handler $plugins_handler */
|
||||
$plugins_handler = $container->get( Plugins_Handler::class );
|
||||
|
||||
// The current plugin is the one that we are attempting to initialize here.
|
||||
$current_plugin = $plugin_locator->find_current_plugin();
|
||||
|
||||
// The active plugins are those that we were able to discover on the site. This list will not
|
||||
// include mu-plugins, those activated by code, or those who are hidden by filtering. We also
|
||||
// want to take care to not consider the current plugin unknown if it was included by an
|
||||
// autoloader. This avoids the case where a plugin will be marked "active" while deactivated
|
||||
// due to it having the latest autoloader.
|
||||
$active_plugins = $plugins_handler->get_active_plugins( true, ! $was_included_by_autoloader );
|
||||
|
||||
// The cached plugins are all of those that were active or discovered by the autoloader during a previous request.
|
||||
// Note that it's possible this list will include plugins that have since been deactivated, but after a request
|
||||
// the cache should be updated and the deactivated plugins will be removed.
|
||||
$cached_plugins = $plugins_handler->get_cached_plugins();
|
||||
|
||||
// We combine the active list and cached list to preemptively load classes for plugins that are
|
||||
// presently unknown but will be loaded during the request. While this may result in us considering packages in
|
||||
// deactivated plugins there shouldn't be any problems as a result and the eventual consistency is sufficient.
|
||||
$all_plugins = array_merge( $active_plugins, $cached_plugins );
|
||||
|
||||
// In particular we also include the current plugin to address the case where it is the latest autoloader
|
||||
// but also unknown (and not cached). We don't want it in the active list because we don't know that it
|
||||
// is active but we need it in the all plugins list so that it is considered by the autoloader.
|
||||
$all_plugins[] = $current_plugin;
|
||||
|
||||
// We require uniqueness in the array to avoid processing the same plugin more than once.
|
||||
$all_plugins = array_values( array_unique( $all_plugins ) );
|
||||
|
||||
/** @var Latest_Autoloader_Guard $guard */
|
||||
$guard = $container->get( Latest_Autoloader_Guard::class );
|
||||
if ( $guard->should_stop_init( $current_plugin, $all_plugins, $was_included_by_autoloader ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the autoloader using the handler now that we're ready.
|
||||
$autoloader_handler->activate_autoloader( $all_plugins );
|
||||
|
||||
/** @var Hook_Manager $hook_manager */
|
||||
$hook_manager = $container->get( Hook_Manager::class );
|
||||
|
||||
// Register a shutdown handler to clean up the autoloader.
|
||||
$hook_manager->add_action( 'shutdown', new Shutdown_Handler( $plugins_handler, $cached_plugins, $was_included_by_autoloader ) );
|
||||
|
||||
// Register a plugins_loaded handler to check for conflicting autoloaders.
|
||||
$hook_manager->add_action( 'plugins_loaded', array( $guard, 'check_for_conflicting_autoloaders' ), 1 );
|
||||
|
||||
// phpcs:enable Generic.Commenting.DocComment.MissingShort
|
||||
}
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class manages the files and dependencies of the autoloader.
|
||||
*/
|
||||
class Container {
|
||||
|
||||
/**
|
||||
* Since each autoloader's class files exist within their own namespace we need a map to
|
||||
* convert between the local class and a shared key. Note that no version checking is
|
||||
* performed on these dependencies and the first autoloader to register will be the
|
||||
* one that is utilized.
|
||||
*/
|
||||
const SHARED_DEPENDENCY_KEYS = array(
|
||||
Hook_Manager::class => 'Hook_Manager',
|
||||
);
|
||||
|
||||
/**
|
||||
* A map of all the dependencies we've registered with the container and created.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dependencies;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->dependencies = array();
|
||||
|
||||
$this->register_shared_dependencies();
|
||||
$this->register_dependencies();
|
||||
$this->initialize_globals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a dependency out of the container.
|
||||
*
|
||||
* @param string $class The class to fetch.
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \InvalidArgumentException When a class that isn't registered with the container is fetched.
|
||||
*/
|
||||
public function get( $class ) {
|
||||
if ( ! isset( $this->dependencies[ $class ] ) ) {
|
||||
throw new \InvalidArgumentException( "Class '$class' is not registered with the container." );
|
||||
}
|
||||
|
||||
return $this->dependencies[ $class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all of the dependencies that are shared between all instances of the autoloader.
|
||||
*/
|
||||
private function register_shared_dependencies() {
|
||||
global $jetpack_autoloader_container_shared;
|
||||
if ( ! isset( $jetpack_autoloader_container_shared ) ) {
|
||||
$jetpack_autoloader_container_shared = array();
|
||||
}
|
||||
|
||||
$key = self::SHARED_DEPENDENCY_KEYS[ Hook_Manager::class ];
|
||||
if ( ! isset( $jetpack_autoloader_container_shared[ $key ] ) ) {
|
||||
require_once __DIR__ . '/class-hook-manager.php';
|
||||
$jetpack_autoloader_container_shared[ $key ] = new Hook_Manager();
|
||||
}
|
||||
$this->dependencies[ Hook_Manager::class ] = &$jetpack_autoloader_container_shared[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all of the dependencies with the container.
|
||||
*/
|
||||
private function register_dependencies() {
|
||||
require_once __DIR__ . '/class-path-processor.php';
|
||||
$this->dependencies[ Path_Processor::class ] = new Path_Processor();
|
||||
|
||||
require_once __DIR__ . '/class-plugin-locator.php';
|
||||
$this->dependencies[ Plugin_Locator::class ] = new Plugin_Locator(
|
||||
$this->get( Path_Processor::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-version-selector.php';
|
||||
$this->dependencies[ Version_Selector::class ] = new Version_Selector();
|
||||
|
||||
require_once __DIR__ . '/class-autoloader-locator.php';
|
||||
$this->dependencies[ Autoloader_Locator::class ] = new Autoloader_Locator(
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-php-autoloader.php';
|
||||
$this->dependencies[ PHP_Autoloader::class ] = new PHP_Autoloader();
|
||||
|
||||
require_once __DIR__ . '/class-manifest-reader.php';
|
||||
$this->dependencies[ Manifest_Reader::class ] = new Manifest_Reader(
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-plugins-handler.php';
|
||||
$this->dependencies[ Plugins_Handler::class ] = new Plugins_Handler(
|
||||
$this->get( Plugin_Locator::class ),
|
||||
$this->get( Path_Processor::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-autoloader-handler.php';
|
||||
$this->dependencies[ Autoloader_Handler::class ] = new Autoloader_Handler(
|
||||
$this->get( PHP_Autoloader::class ),
|
||||
$this->get( Hook_Manager::class ),
|
||||
$this->get( Manifest_Reader::class ),
|
||||
$this->get( Version_Selector::class )
|
||||
);
|
||||
|
||||
require_once __DIR__ . '/class-latest-autoloader-guard.php';
|
||||
$this->dependencies[ Latest_Autoloader_Guard::class ] = new Latest_Autoloader_Guard(
|
||||
$this->get( Plugins_Handler::class ),
|
||||
$this->get( Autoloader_Handler::class ),
|
||||
$this->get( Autoloader_Locator::class )
|
||||
);
|
||||
|
||||
// Register any classes that we will use elsewhere.
|
||||
require_once __DIR__ . '/class-version-loader.php';
|
||||
require_once __DIR__ . '/class-shutdown-handler.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes any of the globals needed by the autoloader.
|
||||
*/
|
||||
private function initialize_globals() {
|
||||
/*
|
||||
* This global was retired in version 2.9. The value is set to 'false' to maintain
|
||||
* compatibility with older versions of the autoloader.
|
||||
*/
|
||||
global $jetpack_autoloader_including_latest;
|
||||
$jetpack_autoloader_including_latest = false;
|
||||
|
||||
// Not all plugins can be found using the locator. In cases where a plugin loads the autoloader
|
||||
// but was not discoverable, we will record them in this array to track them as "active".
|
||||
global $jetpack_autoloader_activating_plugins_paths;
|
||||
if ( ! isset( $jetpack_autoloader_activating_plugins_paths ) ) {
|
||||
$jetpack_autoloader_activating_plugins_paths = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
/**
|
||||
* Allows the latest autoloader to register hooks that can be removed when the autoloader is reset.
|
||||
*/
|
||||
class Hook_Manager {
|
||||
|
||||
/**
|
||||
* An array containing all of the hooks that we've registered.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $registered_hooks;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->registered_hooks = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an action to WordPress and registers it internally.
|
||||
*
|
||||
* @param string $tag The name of the action which is hooked.
|
||||
* @param callable $callable The function to call.
|
||||
* @param int $priority Used to specify the priority of the action.
|
||||
* @param int $accepted_args Used to specify the number of arguments the callable accepts.
|
||||
*/
|
||||
public function add_action( $tag, $callable, $priority = 10, $accepted_args = 1 ) {
|
||||
$this->registered_hooks[ $tag ][] = array(
|
||||
'priority' => $priority,
|
||||
'callable' => $callable,
|
||||
);
|
||||
|
||||
add_action( $tag, $callable, $priority, $accepted_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to WordPress and registers it internally.
|
||||
*
|
||||
* @param string $tag The name of the filter which is hooked.
|
||||
* @param callable $callable The function to call.
|
||||
* @param int $priority Used to specify the priority of the filter.
|
||||
* @param int $accepted_args Used to specify the number of arguments the callable accepts.
|
||||
*/
|
||||
public function add_filter( $tag, $callable, $priority = 10, $accepted_args = 1 ) {
|
||||
$this->registered_hooks[ $tag ][] = array(
|
||||
'priority' => $priority,
|
||||
'callable' => $callable,
|
||||
);
|
||||
|
||||
add_filter( $tag, $callable, $priority, $accepted_args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the registered hooks.
|
||||
*/
|
||||
public function reset() {
|
||||
foreach ( $this->registered_hooks as $tag => $hooks ) {
|
||||
foreach ( $hooks as $hook ) {
|
||||
remove_filter( $tag, $hook['callable'], $hook['priority'] );
|
||||
}
|
||||
}
|
||||
$this->registered_hooks = array();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class ensures that we're only executing the latest autoloader.
|
||||
*/
|
||||
class Latest_Autoloader_Guard {
|
||||
|
||||
/**
|
||||
* The Plugins_Handler instance.
|
||||
*
|
||||
* @var Plugins_Handler
|
||||
*/
|
||||
private $plugins_handler;
|
||||
|
||||
/**
|
||||
* The Autoloader_Handler instance.
|
||||
*
|
||||
* @var Autoloader_Handler
|
||||
*/
|
||||
private $autoloader_handler;
|
||||
|
||||
/**
|
||||
* The Autoloader_locator instance.
|
||||
*
|
||||
* @var Autoloader_Locator
|
||||
*/
|
||||
private $autoloader_locator;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Plugins_Handler $plugins_handler The Plugins_Handler instance.
|
||||
* @param Autoloader_Handler $autoloader_handler The Autoloader_Handler instance.
|
||||
* @param Autoloader_Locator $autoloader_locator The Autoloader_Locator instance.
|
||||
*/
|
||||
public function __construct( $plugins_handler, $autoloader_handler, $autoloader_locator ) {
|
||||
$this->plugins_handler = $plugins_handler;
|
||||
$this->autoloader_handler = $autoloader_handler;
|
||||
$this->autoloader_locator = $autoloader_locator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the autoloader should be initialized. Note that this function
|
||||
* has the side-effect of actually loading the latest autoloader in the event that this
|
||||
* is not it.
|
||||
*
|
||||
* @param string $current_plugin The current plugin we're checking.
|
||||
* @param string[] $plugins The active plugins to check for autoloaders in.
|
||||
* @param bool $was_included_by_autoloader Indicates whether or not this autoloader was included by another.
|
||||
*
|
||||
* @return bool True if we should stop initialization, otherwise false.
|
||||
*/
|
||||
public function should_stop_init( $current_plugin, $plugins, $was_included_by_autoloader ) {
|
||||
global $jetpack_autoloader_latest_version;
|
||||
|
||||
// We need to reset the autoloader when the plugins change because
|
||||
// that means the autoloader was generated with a different list.
|
||||
if ( $this->plugins_handler->have_plugins_changed( $plugins ) ) {
|
||||
$this->autoloader_handler->reset_autoloader();
|
||||
}
|
||||
|
||||
// When the latest autoloader has already been found we don't need to search for it again.
|
||||
// We should take care however because this will also trigger if the autoloader has been
|
||||
// included by an older one.
|
||||
if ( isset( $jetpack_autoloader_latest_version ) && ! $was_included_by_autoloader ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$latest_plugin = $this->autoloader_locator->find_latest_autoloader( $plugins, $jetpack_autoloader_latest_version );
|
||||
if ( isset( $latest_plugin ) && $latest_plugin !== $current_plugin ) {
|
||||
require $this->autoloader_locator->get_autoloader_path( $latest_plugin );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for conflicting autoloaders.
|
||||
*
|
||||
* A common source of strange and confusing problems is when another plugin
|
||||
* registers a Composer autoloader at a higher priority that us. If enabled,
|
||||
* check for this problem and warn about it.
|
||||
*
|
||||
* Called from the plugins_loaded hook.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @return void
|
||||
*/
|
||||
public function check_for_conflicting_autoloaders() {
|
||||
if ( ! defined( 'JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS' ) || ! JETPACK_AUTOLOAD_DEBUG_CONFLICTING_LOADERS ) {
|
||||
return;
|
||||
}
|
||||
|
||||
global $jetpack_autoloader_loader;
|
||||
if ( ! isset( $jetpack_autoloader_loader ) ) {
|
||||
return;
|
||||
}
|
||||
$prefixes = array();
|
||||
foreach ( ( $jetpack_autoloader_loader->get_class_map() ?? array() ) as $classname => $data ) {
|
||||
$parts = explode( '\\', trim( $classname, '\\' ) );
|
||||
array_pop( $parts );
|
||||
while ( $parts ) {
|
||||
$prefixes[ implode( '\\', $parts ) . '\\' ] = true;
|
||||
array_pop( $parts );
|
||||
}
|
||||
}
|
||||
foreach ( ( $jetpack_autoloader_loader->get_psr4_map() ?? array() ) as $prefix => $data ) {
|
||||
$parts = explode( '\\', trim( $prefix, '\\' ) );
|
||||
while ( $parts ) {
|
||||
$prefixes[ implode( '\\', $parts ) . '\\' ] = true;
|
||||
array_pop( $parts );
|
||||
}
|
||||
}
|
||||
|
||||
$autoload_chain = spl_autoload_functions();
|
||||
if ( ! $autoload_chain ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $autoload_chain as $autoloader ) {
|
||||
// No need to check anything after us.
|
||||
if ( is_array( $autoloader ) && is_string( $autoloader[0] ) && substr( $autoloader[0], 0, strlen( __NAMESPACE__ ) + 1 ) === __NAMESPACE__ . '\\' ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We can check Composer autoloaders easily enough.
|
||||
if ( is_array( $autoloader ) && $autoloader[0] instanceof \Composer\Autoload\ClassLoader && is_callable( array( $autoloader[0], 'getPrefixesPsr4' ) ) ) {
|
||||
$composer_autoloader = $autoloader[0];
|
||||
foreach ( $composer_autoloader->getClassMap() as $classname => $path ) {
|
||||
if ( $jetpack_autoloader_loader->find_class_file( $classname ) ) {
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the classes we handle (e.g. $classname => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
foreach ( $composer_autoloader->getPrefixesPsr4() as $prefix => $paths ) {
|
||||
if ( isset( $prefixes[ $prefix ] ) ) {
|
||||
$path = array_pop( $paths );
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the namespaces we handle (e.g. $prefix => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
foreach ( $composer_autoloader->getPrefixes() as $prefix => $paths ) {
|
||||
if ( isset( $prefixes[ $prefix ] ) ) {
|
||||
$path = array_pop( $paths );
|
||||
$msg = "A Composer autoloader is registered with a higher priority than the Jetpack Autoloader and would also handle some of the namespaces we handle (e.g. $prefix => $path). This may cause strange and confusing problems.";
|
||||
wp_trigger_error( '', $msg );
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* This file was automatically generated by automattic/jetpack-autoloader.
|
||||
*
|
||||
* @package automattic/jetpack-autoloader
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Autoloader\jp32625eaf0064549a4f20b6231a37a93c\al5_0_10;
|
||||
|
||||
// phpcs:ignore
|
||||
|
||||
/**
|
||||
* This class reads autoloader manifest files.
|
||||
*/
|
||||
class Manifest_Reader {
|
||||
|
||||
/**
|
||||
* The Version_Selector object.
|
||||
*
|
||||
* @var Version_Selector
|
||||
*/
|
||||
private $version_selector;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*
|
||||
* @param Version_Selector $version_selector The Version_Selector object.
|
||||
*/
|
||||
public function __construct( $version_selector ) {
|
||||
$this->version_selector = $version_selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all of the manifests in the given plugin paths.
|
||||
*
|
||||
* @param array $plugin_paths The paths to the plugins we're loading the manifest in.
|
||||
* @param string $manifest_path The path that we're loading the manifest from in each plugin.
|
||||
* @param array $path_map The path map to add the contents of the manifests to.
|
||||
*
|
||||
* @return array $path_map The path map we've built using the manifests in each plugin.
|
||||
*/
|
||||
public function read_manifests( $plugin_paths, $manifest_path, &$path_map ) {
|
||||
$file_paths = array_map(
|
||||
function ( $path ) use ( $manifest_path ) {
|
||||
return trailingslashit( $path ) . $manifest_path;
|
||||
},
|
||||
$plugin_paths
|
||||
);
|
||||
|
||||
foreach ( $file_paths as $path ) {
|
||||
$this->register_manifest( $path, $path_map );
|
||||
}
|
||||
|
||||
return $path_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin's manifest file with the path map.
|
||||
*
|
||||
* @param string $manifest_path The absolute path to the manifest that we're loading.
|
||||
* @param array $path_map The path map to add the contents of the manifest to.
|
||||
*/
|
||||
protected function register_manifest( $manifest_path, &$path_map ) {
|
||||
if ( ! is_readable( $manifest_path ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manifest = require $manifest_path;
|
||||
if ( ! is_array( $manifest ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $manifest as $key => $data ) {
|
||||
$this->register_record( $key, $data, $path_map );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an entry from the manifest in the path map.
|
||||
*
|
||||
* @param string $key The identifier for the entry we're registering.
|
||||
* @param array $data The data for the entry we're registering.
|
||||
* @param array $path_map The path map to add the contents of the manifest to.
|
||||
*/
|
||||
protected function register_record( $key, $data, &$path_map ) {
|
||||
if ( isset( $path_map[ $key ]['version'] ) ) {
|
||||
$selected_version = $path_map[ $key ]['version'];
|
||||
} else {
|
||||
$selected_version = null;
|
||||
}
|
||||
|
||||
if ( $this->version_selector->is_version_update_required( $selected_version, $data['version'] ) ) {
|
||||
$path_map[ $key ] = array(
|
||||
'version' => $data['version'],
|
||||
'path' => $data['path'],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue