initial commit

This commit is contained in:
2021-12-10 12:03:04 +00:00
commit c46c7ddbf0
3643 changed files with 582794 additions and 0 deletions
assets
css
_animation.scss_fonts.scss_mixins.scss_variables.scssactivation-rtl.cssactivation.cssactivation.scssadmin-rtl.cssadmin.cssadmin.scssauth-rtl.cssauth.cssauth.scssdashboard-rtl.cssdashboard-setup-rtl.cssdashboard-setup.cssdashboard-setup.scssdashboard.cssdashboard.scsshelper-rtl.csshelper.csshelper.scss
jquery-ui
marketplace-suggestions-rtl.cssmarketplace-suggestions.cssmarketplace-suggestions.scssmenu-rtl.cssmenu.cssmenu.scssnetwork-order-widget-rtl.cssnetwork-order-widget.cssnetwork-order-widget.scss
photoswipe
prettyPhoto-rtl.cssprettyPhoto.cssprettyPhoto.scssprivacy-rtl.cssprivacy.cssprivacy.scssreports-print-rtl.cssreports-print.cssreports-print.scssselect2.cssselect2.scsstwenty-nineteen-rtl.csstwenty-nineteen.csstwenty-nineteen.scsstwenty-seventeen-rtl.csstwenty-seventeen.csstwenty-seventeen.scsstwenty-twenty-one-admin-rtl.csstwenty-twenty-one-admin.csstwenty-twenty-one-admin.scsstwenty-twenty-one-rtl.csstwenty-twenty-one.csstwenty-twenty-one.scsstwenty-twenty-rtl.csstwenty-twenty.csstwenty-twenty.scsswc-setup-rtl.csswc-setup.csswc-setup.scsswoocommerce-layout-rtl.csswoocommerce-layout.csswoocommerce-layout.scsswoocommerce-rtl.csswoocommerce-smallscreen-rtl.csswoocommerce-smallscreen.csswoocommerce-smallscreen.scsswoocommerce.csswoocommerce.scss
fonts
images
js
accounting
admin
flexslider
frontend
jquery-blockui
jquery-cookie
jquery-flot
jquery-payment
jquery-qrcode
jquery-serializejson
jquery-tiptip
jquery-ui-touch-punch
js-cookie
photoswipe
prettyPhoto
round
select2
selectWoo
stupidtable
zeroclipboard
zoom
i18n
includes
abstracts
admin
class-wc-admin-addons.phpclass-wc-admin-api-keys-table-list.phpclass-wc-admin-api-keys.phpclass-wc-admin-assets.phpclass-wc-admin-attributes.phpclass-wc-admin-customize.phpclass-wc-admin-dashboard-setup.phpclass-wc-admin-dashboard.phpclass-wc-admin-duplicate-product.phpclass-wc-admin-exporters.phpclass-wc-admin-help.phpclass-wc-admin-importers.phpclass-wc-admin-log-table-list.phpclass-wc-admin-menus.phpclass-wc-admin-meta-boxes.phpclass-wc-admin-notices.phpclass-wc-admin-permalink-settings.phpclass-wc-admin-pointers.phpclass-wc-admin-post-types.phpclass-wc-admin-profile.phpclass-wc-admin-reports.phpclass-wc-admin-settings.phpclass-wc-admin-setup-wizard.phpclass-wc-admin-status.phpclass-wc-admin-taxonomies.phpclass-wc-admin-webhooks-table-list.phpclass-wc-admin-webhooks.phpclass-wc-admin.php
helper
importers
list-tables
marketplace-suggestions
meta-boxes
notes
plugin-updates
reports
settings
views
wc-admin-functions.phpwc-meta-box-functions.php
blocks
class-wc-ajax.phpclass-wc-api.phpclass-wc-auth.phpclass-wc-autoloader.phpclass-wc-background-emailer.phpclass-wc-background-updater.phpclass-wc-breadcrumb.phpclass-wc-cache-helper.phpclass-wc-cart-fees.phpclass-wc-cart-session.phpclass-wc-cart-totals.phpclass-wc-cart.phpclass-wc-checkout.phpclass-wc-cli.phpclass-wc-comments.phpclass-wc-countries.phpclass-wc-coupon.phpclass-wc-customer-download-log.phpclass-wc-customer-download.phpclass-wc-customer.phpclass-wc-data-exception.phpclass-wc-data-store.phpclass-wc-datetime.phpclass-wc-deprecated-action-hooks.phpclass-wc-deprecated-filter-hooks.phpclass-wc-discounts.phpclass-wc-download-handler.phpclass-wc-emails.phpclass-wc-embed.phpclass-wc-form-handler.phpclass-wc-frontend-scripts.phpclass-wc-geo-ip.phpclass-wc-geolite-integration.phpclass-wc-geolocation.phpclass-wc-https.phpclass-wc-install.phpclass-wc-integrations.phpclass-wc-log-levels.phpclass-wc-logger.phpclass-wc-meta-data.phpclass-wc-order-factory.phpclass-wc-order-item-coupon.phpclass-wc-order-item-fee.phpclass-wc-order-item-meta.phpclass-wc-order-item-product.phpclass-wc-order-item-shipping.phpclass-wc-order-item-tax.phpclass-wc-order-item.phpclass-wc-order-query.phpclass-wc-order-refund.phpclass-wc-order.phpclass-wc-payment-gateways.phpclass-wc-payment-tokens.phpclass-wc-post-data.phpclass-wc-post-types.phpclass-wc-privacy-background-process.phpclass-wc-privacy-erasers.phpclass-wc-privacy-exporters.phpclass-wc-privacy.phpclass-wc-product-attribute.phpclass-wc-product-download.phpclass-wc-product-external.phpclass-wc-product-factory.phpclass-wc-product-grouped.phpclass-wc-product-query.phpclass-wc-product-simple.phpclass-wc-product-variable.phpclass-wc-product-variation.phpclass-wc-query.phpclass-wc-rate-limiter.phpclass-wc-regenerate-images-request.phpclass-wc-regenerate-images.phpclass-wc-register-wp-admin-settings.phpclass-wc-rest-authentication.phpclass-wc-rest-exception.phpclass-wc-session-handler.phpclass-wc-shipping-rate.phpclass-wc-shipping-zone.phpclass-wc-shipping-zones.phpclass-wc-shipping.phpclass-wc-shortcodes.phpclass-wc-structured-data.phpclass-wc-tax.phpclass-wc-template-loader.phpclass-wc-tracker.phpclass-wc-validation.phpclass-wc-webhook.phpclass-woocommerce.php
cli
customizer
data-stores
emails
export
gateways
import
integrations
interfaces
legacy
libraries
log-handlers
payment-tokens
queue
rest-api
Controllers
Telemetry
Version1
Version2
Version3
class-wc-rest-controller.phpclass-wc-rest-coupons-controller.phpclass-wc-rest-crud-controller.phpclass-wc-rest-customer-downloads-controller.phpclass-wc-rest-customers-controller.phpclass-wc-rest-data-continents-controller.phpclass-wc-rest-data-controller.phpclass-wc-rest-data-countries-controller.phpclass-wc-rest-data-currencies-controller.phpclass-wc-rest-network-orders-controller.phpclass-wc-rest-order-notes-controller.phpclass-wc-rest-order-refunds-controller.phpclass-wc-rest-orders-controller.phpclass-wc-rest-payment-gateways-controller.phpclass-wc-rest-posts-controller.phpclass-wc-rest-product-attribute-terms-controller.phpclass-wc-rest-product-attributes-controller.phpclass-wc-rest-product-categories-controller.phpclass-wc-rest-product-reviews-controller.phpclass-wc-rest-product-shipping-classes-controller.phpclass-wc-rest-product-tags-controller.phpclass-wc-rest-product-variations-controller.phpclass-wc-rest-products-controller.phpclass-wc-rest-report-coupons-totals-controller.phpclass-wc-rest-report-customers-totals-controller.phpclass-wc-rest-report-orders-totals-controller.phpclass-wc-rest-report-products-totals-controller.phpclass-wc-rest-report-reviews-totals-controller.phpclass-wc-rest-report-sales-controller.phpclass-wc-rest-report-top-sellers-controller.phpclass-wc-rest-reports-controller.phpclass-wc-rest-setting-options-controller.phpclass-wc-rest-settings-controller.phpclass-wc-rest-shipping-methods-controller.phpclass-wc-rest-shipping-zone-locations-controller.phpclass-wc-rest-shipping-zone-methods-controller.phpclass-wc-rest-shipping-zones-controller-base.phpclass-wc-rest-shipping-zones-controller.phpclass-wc-rest-system-status-controller.phpclass-wc-rest-system-status-tools-controller.phpclass-wc-rest-tax-classes-controller.phpclass-wc-rest-taxes-controller.phpclass-wc-rest-terms-controller.phpclass-wc-rest-webhooks-controller.php
Package.phpServer.php
Utilities
shipping
shortcodes
theme-support
tracks
traits
walkers
wc-account-functions.phpwc-attribute-functions.phpwc-cart-functions.phpwc-conditional-functions.phpwc-core-functions.phpwc-coupon-functions.phpwc-deprecated-functions.phpwc-formatting-functions.phpwc-notice-functions.phpwc-order-functions.phpwc-order-item-functions.phpwc-page-functions.phpwc-product-functions.phpwc-rest-functions.phpwc-stock-functions.phpwc-template-functions.phpwc-template-hooks.phpwc-term-functions.phpwc-update-functions.phpwc-user-functions.phpwc-webhook-functions.phpwc-widget-functions.php
wccom-site
widgets
lib/packages/League/Container
license.txt
packages
action-scheduler
action-scheduler.php
classes
ActionScheduler_ActionClaim.phpActionScheduler_ActionFactory.phpActionScheduler_AdminView.phpActionScheduler_AsyncRequest_QueueRunner.phpActionScheduler_Compatibility.phpActionScheduler_DataController.phpActionScheduler_DateTime.phpActionScheduler_Exception.phpActionScheduler_FatalErrorMonitor.phpActionScheduler_InvalidActionException.phpActionScheduler_ListTable.phpActionScheduler_LogEntry.phpActionScheduler_NullLogEntry.phpActionScheduler_OptionLock.phpActionScheduler_QueueCleaner.phpActionScheduler_QueueRunner.phpActionScheduler_Versions.phpActionScheduler_WPCommentCleaner.phpActionScheduler_wcSystemStatus.php
WP_CLI
abstracts
actions
data-stores
migration
schedules
schema
deprecated
functions.php
lib
license.txtreadme.txt
woocommerce-admin
chunk-src-version-param.js
dist
activity-panels-help
activity-panels-inbox
analytics-report-categories
analytics-report-customers
analytics-report-orders
analytics-report-products
analytics-report-stock
analytics-report
analytics-settings
app
beta-features-tracking-modal
chunks
components
csv-export
currency
customer-effort-score
dashboard-charts
dashboard
data
date
experimental
explat
homescreen
leaderboards
marketing-coupons
marketing-overview
navigation-opt-out
navigation
notices
number
onboarding
payment-method-promotions
payment-recommendations
print-shipping-label-banner
profile-wizard
shipping-recommendations
store-alerts
store-performance
task-list
tracks
undefined
wp-admin-scripts
images
includes
languages
license.txtlint-staged.config.jsreadme.txt
src
API
Coupons.phpCustomAttributeTraits.phpCustomers.phpData.phpDataCountries.phpDataDownloadIPs.phpFeatures.phpInit.phpLeaderboards.phpMarketing.phpMarketingOverview.phpNavigationFavorites.phpNoteActions.phpNotes.phpOnboardingFreeExtensions.phpOnboardingPayments.phpOnboardingProductTypes.phpOnboardingProfile.phpOnboardingTasks.phpOnboardingThemes.phpOptions.phpOrders.phpPlugins.phpProductAttributeTerms.phpProductAttributes.phpProductCategories.phpProductReviews.phpProductVariations.phpProducts.phpProductsLowInStock.php
Reports
SettingOptions.phpTaxes.php
Templates
Themes.php
CategoryLookup.php
Composer
DateTimeProvider
DeprecatedClassFacade.phpEvents.phpFeaturePlugin.php
Features
Install.phpLoader.php
Marketing
Notes
Overrides
PageController.phpPaymentPlugins.phpPluginsHelper.phpPluginsInstaller.php
PluginsProvider
RemoteInboxNotifications
ReportCSVEmail.phpReportCSVExporter.phpReportExporter.phpReportsSync.php
Schedulers
Survey.phpWCAdminHelper.phpWCAdminSharedSettings.php
typings
uninstall.phpunminify.js
vendor
autoload.phpautoload_packages.php
automattic
composer
ClassLoader.phpInstalledVersions.phpLICENSEautoload_classmap.phpautoload_namespaces.phpautoload_psr4.phpautoload_real.phpautoload_static.phpinstalled.jsoninstalled.php
installers
LICENSEphpstan.neon.dist
src
Composer
Installers
AglInstaller.phpAimeosInstaller.phpAnnotateCmsInstaller.phpAsgardInstaller.phpAttogramInstaller.phpBaseInstaller.phpBitrixInstaller.phpBonefishInstaller.phpCakePHPInstaller.phpChefInstaller.phpCiviCrmInstaller.phpClanCatsFrameworkInstaller.phpCockpitInstaller.phpCodeIgniterInstaller.phpConcrete5Installer.phpCraftInstaller.phpCroogoInstaller.phpDecibelInstaller.phpDframeInstaller.phpDokuWikiInstaller.phpDolibarrInstaller.phpDrupalInstaller.phpElggInstaller.phpEliasisInstaller.phpExpressionEngineInstaller.phpEzPlatformInstaller.phpFuelInstaller.phpFuelphpInstaller.phpGravInstaller.phpHuradInstaller.phpImageCMSInstaller.phpInstaller.phpItopInstaller.phpJoomlaInstaller.phpKanboardInstaller.phpKirbyInstaller.phpKnownInstaller.phpKodiCMSInstaller.phpKohanaInstaller.phpLanManagementSystemInstaller.phpLaravelInstaller.phpLavaLiteInstaller.phpLithiumInstaller.phpMODULEWorkInstaller.phpMODXEvoInstaller.phpMagentoInstaller.phpMajimaInstaller.phpMakoInstaller.phpMantisBTInstaller.phpMauticInstaller.phpMayaInstaller.phpMediaWikiInstaller.phpMiaoxingInstaller.phpMicroweberInstaller.phpModxInstaller.phpMoodleInstaller.phpOctoberInstaller.phpOntoWikiInstaller.phpOsclassInstaller.phpOxidInstaller.phpPPIInstaller.phpPantheonInstaller.phpPhiftyInstaller.phpPhpBBInstaller.phpPimcoreInstaller.phpPiwikInstaller.phpPlentymarketsInstaller.phpPlugin.phpPortoInstaller.phpPrestashopInstaller.phpProcessWireInstaller.phpPuppetInstaller.phpPxcmsInstaller.phpRadPHPInstaller.phpReIndexInstaller.phpRedaxo5Installer.phpRedaxoInstaller.phpRoundcubeInstaller.phpSMFInstaller.phpShopwareInstaller.phpSilverStripeInstaller.phpSiteDirectInstaller.phpStarbugInstaller.phpSyDESInstaller.phpSyliusInstaller.phpSymfony1Installer.phpTYPO3CmsInstaller.phpTYPO3FlowInstaller.phpTaoInstaller.phpTastyIgniterInstaller.phpTheliaInstaller.phpTuskInstaller.phpUserFrostingInstaller.phpVanillaInstaller.phpVgmcpInstaller.phpWHMCSInstaller.phpWinterInstaller.phpWolfCMSInstaller.phpWordPressInstaller.phpYawikInstaller.phpZendInstaller.phpZikulaInstaller.php
bootstrap.php
jetpack_autoload_classmap.phpjetpack_autoload_psr4.phpplatform_check.php
jetpack-autoloader
woocommerce-admin.php
woocommerce-blocks
LICENSE
assets
css
js
atomic
base
components
block-error-boundary
button
cart-checkout
checkbox-control
checkbox-list
chip
combobox
country-input
drawer
dropdown-selector
filter-element-label
filter-submit-button
form
formatted-monetary-amount
label
load-more-button
loading-mask
pagination
price-slider
product-list
product-name
product-price
quantity-selector
radio-control-accordion
radio-control
read-more
reviews
index.js
review-list-item
review-list
review-sort-select
sidebar-layout
sort-select
spinner
state-input
summary
tabs
text-input
textarea
title
context
event-emit
hooks
index.ts
providers
test
utils.js
hocs
hooks
utils
blocks-registry
blocks
active-filters
attribute-filter
cart-checkout
cart-i2
cart
checkout
attributes.tsblock.tsx
checkout-order-error
columns
context.tsedit.tsxeditor-utils.ts
empty-cart
form-step
frontend.tsxhacks.tsindex.tsx
inner-blocks
order-notes
phone-number
styles
types.tsuse-forced-layout.tsutils.ts
mini-cart
payment-methods
featured-category
featured-product
handpicked-products
price-filter
product-best-sellers
product-categories
product-category
product-new
product-on-sale
product-search
product-tag
product-top-rated
products-by-attribute
products
reviews
single-product
stock-filter
data
editor-components
block-title
compatibility-notices
edit-product-link
error-placeholder
expandable-search-list-item
external-link-card
feedback-prompt
grid-content-control
grid-layout-control
heading-toolbar
page-selector
product-attribute-term-control
product-category-control
product-control
product-orderby-control
product-tag-control
products-control
text-toolbar-button
toggle-button-control
utils
view-switcher
extensions
filters
global.d.ts
hocs
icons
index.js
middleware
payment-method-extensions
previews
settings
shared
types
utils
build
active-filters-frontend.asset.phpactive-filters-frontend.jsactive-filters.asset.phpactive-filters.jsall-products-frontend.asset.phpall-products-frontend.jsall-products.asset.phpall-products.jsall-reviews.asset.phpall-reviews.js
atomic-block-components
attribute-filter-frontend.asset.phpattribute-filter-frontend.jsattribute-filter.asset.phpattribute-filter.jsblocks-checkout.asset.phpblocks-checkout.js
cart-blocks
cart-frontend.asset.phpcart-frontend.jscart-i2-frontend.asset.phpcart-i2-frontend.jscart-i2.asset.phpcart-i2.jscart.asset.phpcart.js
checkout-blocks
checkout-frontend.asset.phpcheckout-frontend.jscheckout.asset.phpcheckout.jsfeatured-category.asset.phpfeatured-category.jsfeatured-product.asset.phpfeatured-product.jshandpicked-products.asset.phphandpicked-products.jsmini-cart-component-frontend.asset.phpmini-cart-component-frontend.jsmini-cart-frontend.asset.phpmini-cart-frontend.jsmini-cart.asset.phpmini-cart.jsprice-filter-frontend.asset.phpprice-filter-frontend.jsprice-filter.asset.phpprice-filter.jsprice-format.asset.phpprice-format.jsproduct-best-sellers.asset.phpproduct-best-sellers.jsproduct-categories.asset.phpproduct-categories.jsproduct-category.asset.phpproduct-category.jsproduct-new.asset.phpproduct-new.jsproduct-on-sale.asset.phpproduct-on-sale.jsproduct-search.asset.phpproduct-search.jsproduct-tag.asset.phpproduct-tag.jsproduct-top-rated.asset.phpproduct-top-rated.jsproducts-by-attribute.asset.phpproducts-by-attribute.jsreviews-by-category.asset.phpreviews-by-category.jsreviews-by-product.asset.phpreviews-by-product.jsreviews-frontend.asset.phpreviews-frontend.jssingle-product-frontend.asset.phpsingle-product-frontend.jssingle-product.asset.phpsingle-product.jsstock-filter-frontend.asset.phpstock-filter-frontend.jsstock-filter.asset.phpstock-filter.js
vendors--atomic-block-components
add-to-cart--cart-blocks
order-summary--checkout-blocks
add-to-cart-frontend.js
price--cart-blocks
vendors--cart-blocks
line-items--checkout-blocks
order-summary--checkout-blocks
billing-address--checkout-blocks
wc-blocks-data.asset.phpwc-blocks-data.jswc-blocks-editor-style-rtl.csswc-blocks-editor-style.csswc-blocks-google-analytics.asset.phpwc-blocks-google-analytics.jswc-blocks-middleware.asset.phpwc-blocks-middleware.jswc-blocks-registry.asset.phpwc-blocks-registry.jswc-blocks-shared-context.asset.phpwc-blocks-shared-context.jswc-blocks-shared-hocs.asset.phpwc-blocks-shared-hocs.jswc-blocks-style-rtl.csswc-blocks-style.csswc-blocks-vendors-style-rtl.csswc-blocks-vendors-style.csswc-blocks-vendors.jswc-blocks.asset.phpwc-blocks.jswc-payment-method-bacs.asset.phpwc-payment-method-bacs.jswc-payment-method-cheque.asset.phpwc-payment-method-cheque.jswc-payment-method-cod.asset.phpwc-payment-method-cod.jswc-payment-method-paypal.asset.phpwc-payment-method-paypal.jswc-payment-method-stripe.asset.phpwc-payment-method-stripe.jswc-settings.asset.phpwc-settings.js
global.d.ts
images
packages
patches
readme.txt
src
Assets.php
Assets
AssetsController.php
BlockTypes
BlockTypesController.php
Domain
InboxNotifications.phpInstaller.php
Integrations
Library.phpPackage.php
Payments
Registry
RestApi.php
StoreApi
Utils
templates
vendor
autoload.phpautoload_packages.php
automattic
composer
ClassLoader.phpInstalledVersions.phpLICENSEautoload_classmap.phpautoload_namespaces.phpautoload_psr4.phpautoload_real.phpautoload_static.phpinstalled.jsoninstalled.php
installers
LICENSEphpstan.neon.dist
src
Composer
Installers
AglInstaller.phpAimeosInstaller.phpAnnotateCmsInstaller.phpAsgardInstaller.phpAttogramInstaller.phpBaseInstaller.phpBitrixInstaller.phpBonefishInstaller.phpCakePHPInstaller.phpChefInstaller.phpCiviCrmInstaller.phpClanCatsFrameworkInstaller.phpCockpitInstaller.phpCodeIgniterInstaller.phpConcrete5Installer.phpCraftInstaller.phpCroogoInstaller.phpDecibelInstaller.phpDframeInstaller.phpDokuWikiInstaller.phpDolibarrInstaller.phpDrupalInstaller.phpElggInstaller.phpEliasisInstaller.phpExpressionEngineInstaller.phpEzPlatformInstaller.phpFuelInstaller.phpFuelphpInstaller.phpGravInstaller.phpHuradInstaller.phpImageCMSInstaller.phpInstaller.phpItopInstaller.phpJoomlaInstaller.phpKanboardInstaller.phpKirbyInstaller.phpKnownInstaller.phpKodiCMSInstaller.phpKohanaInstaller.phpLanManagementSystemInstaller.phpLaravelInstaller.phpLavaLiteInstaller.phpLithiumInstaller.phpMODULEWorkInstaller.phpMODXEvoInstaller.phpMagentoInstaller.phpMajimaInstaller.phpMakoInstaller.phpMantisBTInstaller.phpMauticInstaller.phpMayaInstaller.phpMediaWikiInstaller.phpMiaoxingInstaller.phpMicroweberInstaller.phpModxInstaller.phpMoodleInstaller.phpOctoberInstaller.phpOntoWikiInstaller.phpOsclassInstaller.phpOxidInstaller.phpPPIInstaller.phpPhiftyInstaller.phpPhpBBInstaller.phpPimcoreInstaller.phpPiwikInstaller.phpPlentymarketsInstaller.phpPlugin.phpPortoInstaller.phpPrestashopInstaller.phpProcessWireInstaller.phpPuppetInstaller.phpPxcmsInstaller.phpRadPHPInstaller.phpReIndexInstaller.phpRedaxo5Installer.phpRedaxoInstaller.phpRoundcubeInstaller.phpSMFInstaller.phpShopwareInstaller.phpSilverStripeInstaller.phpSiteDirectInstaller.phpStarbugInstaller.phpSyDESInstaller.phpSyliusInstaller.phpSymfony1Installer.phpTYPO3CmsInstaller.phpTYPO3FlowInstaller.phpTaoInstaller.phpTastyIgniterInstaller.phpTheliaInstaller.phpTuskInstaller.phpUserFrostingInstaller.phpVanillaInstaller.phpVgmcpInstaller.phpWHMCSInstaller.phpWinterInstaller.phpWolfCMSInstaller.phpWordPressInstaller.phpYawikInstaller.phpZendInstaller.phpZikulaInstaller.php
bootstrap.php
jetpack_autoload_classmap.phpjetpack_autoload_psr4.php
jetpack-autoloader
woocommerce-gutenberg-products-block.php
readme.txt
sample-data
src
templates
archive-product.php
auth
cart
checkout
content-product-cat.phpcontent-product.phpcontent-single-product.phpcontent-widget-price-filter.phpcontent-widget-product.phpcontent-widget-reviews.php
emails
global
loop
myaccount
notices
order
product-searchform.phpsingle-product-reviews.phpsingle-product.php
single-product
taxonomy-product-cat.phptaxonomy-product-tag.php
uninstall.php
vendor
autoload.phpautoload_packages.php
automattic
composer
ClassLoader.phpLICENSEautoload_classmap.phpautoload_namespaces.phpautoload_psr4.phpautoload_real.phpautoload_static.phpinstalled.json
installers
LICENSEphpstan.neon.dist
src
Composer
Installers
AglInstaller.phpAimeosInstaller.phpAnnotateCmsInstaller.phpAsgardInstaller.phpAttogramInstaller.phpBaseInstaller.phpBitrixInstaller.phpBonefishInstaller.phpCakePHPInstaller.phpChefInstaller.phpCiviCrmInstaller.phpClanCatsFrameworkInstaller.phpCockpitInstaller.phpCodeIgniterInstaller.phpConcrete5Installer.phpCraftInstaller.phpCroogoInstaller.phpDecibelInstaller.phpDframeInstaller.phpDokuWikiInstaller.phpDolibarrInstaller.phpDrupalInstaller.phpElggInstaller.phpEliasisInstaller.phpExpressionEngineInstaller.phpEzPlatformInstaller.phpFuelInstaller.phpFuelphpInstaller.phpGravInstaller.phpHuradInstaller.phpImageCMSInstaller.phpInstaller.phpItopInstaller.phpJoomlaInstaller.phpKanboardInstaller.phpKirbyInstaller.phpKnownInstaller.phpKodiCMSInstaller.phpKohanaInstaller.phpLanManagementSystemInstaller.phpLaravelInstaller.phpLavaLiteInstaller.phpLithiumInstaller.phpMODULEWorkInstaller.phpMODXEvoInstaller.phpMagentoInstaller.phpMajimaInstaller.phpMakoInstaller.phpMantisBTInstaller.phpMauticInstaller.phpMayaInstaller.phpMediaWikiInstaller.phpMiaoxingInstaller.phpMicroweberInstaller.phpModxInstaller.phpMoodleInstaller.phpOctoberInstaller.phpOntoWikiInstaller.phpOsclassInstaller.phpOxidInstaller.phpPPIInstaller.phpPantheonInstaller.phpPhiftyInstaller.phpPhpBBInstaller.phpPimcoreInstaller.phpPiwikInstaller.phpPlentymarketsInstaller.phpPlugin.phpPortoInstaller.phpPrestashopInstaller.phpProcessWireInstaller.phpPuppetInstaller.phpPxcmsInstaller.phpRadPHPInstaller.phpReIndexInstaller.phpRedaxo5Installer.phpRedaxoInstaller.phpRoundcubeInstaller.phpSMFInstaller.phpShopwareInstaller.phpSilverStripeInstaller.phpSiteDirectInstaller.phpStarbugInstaller.phpSyDESInstaller.phpSyliusInstaller.phpSymfony1Installer.phpTYPO3CmsInstaller.phpTYPO3FlowInstaller.phpTaoInstaller.phpTastyIgniterInstaller.phpTheliaInstaller.phpTuskInstaller.phpUserFrostingInstaller.phpVanillaInstaller.phpVgmcpInstaller.phpWHMCSInstaller.phpWinterInstaller.phpWolfCMSInstaller.phpWordPressInstaller.phpYawikInstaller.phpZendInstaller.phpZikulaInstaller.php
bootstrap.php
jetpack_autoload_classmap.php
jetpack-autoloader
maxmind-db
pelago
psr
symfony
css-selector
CssSelectorConverter.php
Exception
LICENSE
Node
Parser
Tests
XPath
woocommerce.php

@ -0,0 +1,50 @@
/**
* External dependencies
*/
import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
import { registeredBlockComponents } from './registered-block-components-init';
/**
* Get all Registered Block Components.
*
* WooCommerce Blocks allows React Components to be used on the frontend of the store in place of
* Blocks instead of just serving static content.
*
* This gets all registered Block Components so we know which Blocks map to which React Components.
*
* @param {string} context Current context (a named parent Block). If Block Components were only
* registered under a certain context, those Components will be returned,
* as well as any Components registered under all contexts.
* @return {Object} List of React Components registered under the provided context.
*/
export function getRegisteredBlockComponents( context ) {
const parentInnerBlocks =
typeof registeredBlockComponents[ context ] === 'object' &&
Object.keys( registeredBlockComponents[ context ] ).length > 0
? registeredBlockComponents[ context ]
: {};
return {
...parentInnerBlocks,
...registeredBlockComponents.any,
};
}
/**
* Alias of getRegisteredBlockComponents kept for backwards compatibility.
*
* @param {string} main Name of the parent block to retrieve children of.
* @return {Object} List of registered inner blocks.
*/
export function getRegisteredInnerBlocks( main ) {
deprecated( 'getRegisteredInnerBlocks', {
version: '2.8.0',
alternative: 'getRegisteredBlockComponents',
plugin: 'WooCommerce Blocks',
} );
return getRegisteredBlockComponents( main );
}

@ -0,0 +1,2 @@
export * from './get-registered-block-components';
export * from './register-block-component';

@ -0,0 +1,106 @@
/**
* External dependencies
*/
import deprecated from '@wordpress/deprecated';
/**
* Internal dependencies
*/
import { registeredBlockComponents } from './registered-block-components-init';
/**
* Register a Block Component.
*
* WooCommerce Blocks allows React Components to be used on the frontend of the store in place of
* Blocks instead of just serving static content.
*
* Registering a Block Component allows you to define which React Component should be used in place
* of a registered Block. The Component, when rendered, will be passed all Block Attributes.
*
* @param {Object} options Options to use when registering the block.
* @param {Function} options.component React component that will be rendered, or the return value from React.lazy if
* dynamically imported.
* @param {string} options.blockName Name of the block that this component belongs to.
* @param {string} [options.context] To make this component available only under a certain context
* (named parent Block) define it here. If left blank, the
* Component will be available for all contexts.
*/
export function registerBlockComponent( options ) {
if ( ! options.context ) {
options.context = 'any';
}
assertOption( options, 'context', 'string' );
assertOption( options, 'blockName', 'string' );
assertBlockComponent( options, 'component' );
const { context, blockName, component } = options;
if ( ! registeredBlockComponents[ context ] ) {
registeredBlockComponents[ context ] = {};
}
registeredBlockComponents[ context ][ blockName ] = component;
}
/**
* Asserts that an option is a valid react element or lazy callback. Otherwise, throws an error.
*
* @throws Will throw an error if the type of the option doesn't match the expected type.
* @param {Object} options Object containing the option to validate.
* @param {string} optionName Name of the option to validate.
*/
const assertBlockComponent = ( options, optionName ) => {
if ( options[ optionName ] ) {
if ( typeof options[ optionName ] === 'function' ) {
return;
}
if (
options[ optionName ].$$typeof &&
options[ optionName ].$$typeof === Symbol.for( 'react.lazy' )
) {
return;
}
}
throw new Error(
`Incorrect value for the ${ optionName } argument when registering a block component. Component must be a valid React Element or Lazy callback.`
);
};
/**
* Asserts that an option is of the given type. Otherwise, throws an error.
*
* @throws Will throw an error if the type of the option doesn't match the expected type.
* @param {Object} options Object containing the option to validate.
* @param {string} optionName Name of the option to validate.
* @param {string} expectedType Type expected for the option.
*/
const assertOption = ( options, optionName, expectedType ) => {
const actualType = typeof options[ optionName ];
if ( actualType !== expectedType ) {
throw new Error(
`Incorrect value for the ${ optionName } argument when registering a block component. It was a ${ actualType }, but must be a ${ expectedType }.`
);
}
};
/**
* Alias of registerBlockComponent kept for backwards compatibility.
*
* @param {Object} options Options to use when registering the block.
* @param {string} options.main Name of the parent block.
* @param {string} options.blockName Name of the child block being registered.
* @param {Function} options.component React component used to render the child block.
*/
export function registerInnerBlock( options ) {
deprecated( 'registerInnerBlock', {
version: '2.8.0',
alternative: 'registerBlockComponent',
plugin: 'WooCommerce Blocks',
hint: '"main" has been replaced with "context" and is now optional.',
} );
assertOption( options, 'main', 'string' );
registerBlockComponent( {
...options,
context: options.main,
} );
}

@ -0,0 +1,3 @@
const registeredBlockComponents = {};
export { registeredBlockComponents };

@ -0,0 +1,84 @@
/**
* Internal dependencies
*/
import {
getRegisteredBlockComponents,
registerBlockComponent,
registerInnerBlock,
getRegisteredInnerBlocks,
} from '../index';
describe( 'blocks registry', () => {
const context = '@woocommerce/all-products';
const blockName = '@woocommerce-extension/price-level';
const component = () => {
return null;
};
describe( 'registerBlockComponent', () => {
const invokeTest = ( args ) => () => {
return registerBlockComponent( args );
};
it( 'throws an error when registered block is missing `blockName`', () => {
expect( invokeTest( { context, blockName: null } ) ).toThrowError(
/blockName/
);
} );
it( 'throws an error when registered block is missing `component`', () => {
expect(
invokeTest( { context, blockName, component: null } )
).toThrowError( /component/ );
} );
} );
describe( 'getRegisteredBlockComponents', () => {
it( 'gets an empty object when context has no inner blocks', () => {
expect(
getRegisteredBlockComponents( '@woocommerce/all-products' )
).toEqual( {} );
} );
it( 'gets a block that was successfully registered', () => {
registerBlockComponent( { context, blockName, component } );
expect(
getRegisteredBlockComponents( '@woocommerce/all-products' )
).toEqual( { [ blockName ]: component } );
} );
} );
describe( 'registerInnerBlock (deprecated)', () => {
const invokeTest = ( args ) => () => {
registerInnerBlock( args );
};
it( 'throws an error when registered block is missing `main`', () => {
const options = { main: null };
expect( invokeTest( options ) ).toThrowError( /main/ );
expect( console ).toHaveWarned();
} );
it( 'throws an error when registered block is missing `blockName`', () => {
const options = { main: context, blockName: null };
expect( invokeTest( options ) ).toThrowError( /blockName/ );
} );
it( 'throws an error when registered block is missing `component`', () => {
const options = { main: context, blockName, component: null };
expect( invokeTest( options ) ).toThrowError( /component/ );
} );
} );
describe( 'getRegisteredInnerBlocks (deprecated)', () => {
it( 'gets an empty object when parent has no inner blocks', () => {
expect(
getRegisteredInnerBlocks( '@woocommerce/test-parent' )
).toEqual( {} );
expect( console ).toHaveWarned();
} );
it( 'gets a block that was successfully registered', () => {
registerBlockComponent( { context, blockName, component } );
expect(
getRegisteredInnerBlocks( '@woocommerce/all-products' )
).toEqual( {
[ blockName ]: component,
} );
} );
} );
} );

@ -0,0 +1,2 @@
export * from './payment-methods';
export * from './block-components';

@ -0,0 +1,66 @@
/**
* External dependencies
*/
import { isValidElement } from '@wordpress/element';
import type { ReactNode } from 'react';
import type {
PaymentMethodConfiguration,
ExpressPaymentMethodConfiguration,
} from '@woocommerce/type-defs/payments';
export const assertValidPaymentMethodComponent = (
component: () => unknown,
componentName: string
): void => {
if ( typeof component !== 'function' ) {
throw new TypeError(
`The ${ componentName } property for the payment method must be a functional component`
);
}
};
export const assertValidElement = (
element: ReactNode,
elementName: string
): void => {
if ( element !== null && ! isValidElement( element ) ) {
throw new TypeError(
`The ${ elementName } property for the payment method must be a React element or null.`
);
}
};
export const assertValidElementOrString = (
element: ReactNode,
elementName: string
): void => {
if (
element !== null &&
! isValidElement( element ) &&
typeof element !== 'string'
) {
throw new TypeError(
`The ${ elementName } property for the payment method must be a React element, a string, or null.`
);
}
};
export const assertConfigHasProperties = (
config: ExpressPaymentMethodConfiguration | PaymentMethodConfiguration,
expectedProperties: string[] = []
): void => {
const missingProperties = expectedProperties.reduce(
( acc: string[], property: string ) => {
if ( ! config.hasOwnProperty( property ) ) {
acc.push( property );
}
return acc;
},
[]
);
if ( missingProperties.length > 0 ) {
const message =
'The payment method configuration object is missing the following properties:';
throw new TypeError( message + missingProperties.join( ', ' ) );
}
};

@ -0,0 +1,82 @@
/**
* External dependencies
*/
import type { ReactNode } from 'react';
import type {
ExpressPaymentMethodConfiguration,
Supports,
CanMakePaymentCallback,
ExpressPaymentMethodConfigInstance,
} from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import { getCanMakePayment } from './payment-method-config-helper';
import { assertConfigHasProperties, assertValidElement } from './assertions';
export default class ExpressPaymentMethodConfig
implements ExpressPaymentMethodConfigInstance {
public name: string;
public content: ReactNode;
public edit: ReactNode;
public paymentMethodId?: string;
public supports: Supports;
public canMakePaymentFromConfig: CanMakePaymentCallback;
constructor( config: ExpressPaymentMethodConfiguration ) {
// validate config
ExpressPaymentMethodConfig.assertValidConfig( config );
this.name = config.name;
this.content = config.content;
this.edit = config.edit;
this.paymentMethodId = config.paymentMethodId || this.name;
this.supports = {
features: config?.supports?.features || [ 'products' ],
};
this.canMakePaymentFromConfig = config.canMakePayment;
}
// canMakePayment is calculated each time based on data that modifies outside of the class (eg: cart data).
get canMakePayment(): CanMakePaymentCallback {
return getCanMakePayment(
this.canMakePaymentFromConfig,
this.supports.features,
this.name
);
}
static assertValidConfig = (
config: ExpressPaymentMethodConfiguration
): void => {
assertConfigHasProperties( config, [ 'name', 'content', 'edit' ] );
if ( typeof config.name !== 'string' ) {
throw new TypeError(
'The name property for the express payment method must be a string'
);
}
if (
typeof config.paymentMethodId !== 'string' &&
typeof config.paymentMethodId !== 'undefined'
) {
throw new Error(
'The paymentMethodId property for the payment method must be a string or undefined (in which case it will be the value of the name property).'
);
}
if (
typeof config.supports?.features !== 'undefined' &&
! Array.isArray( config.supports?.features )
) {
throw new Error(
'The features property for the payment method must be an array or undefined.'
);
}
assertValidElement( config.content, 'content' );
assertValidElement( config.edit, 'edit' );
if ( typeof config.canMakePayment !== 'function' ) {
throw new TypeError(
'The canMakePayment property for the express payment method must be a function.'
);
}
};
}

@ -0,0 +1,23 @@
/**
* External dependencies
*/
import { CanMakePaymentExtensionCallback } from '@woocommerce/type-defs/payments';
type CanMakePaymentExtensionCallbacks = Record<
string,
CanMakePaymentExtensionCallback
>;
export type NamespacedCanMakePaymentExtensionsCallbacks = Record<
string,
CanMakePaymentExtensionCallbacks
>;
export type ExtensionNamespace = keyof NamespacedCanMakePaymentExtensionsCallbacks;
export type PaymentMethodName = keyof CanMakePaymentExtensionCallbacks;
// Keeps callbacks registered by extensions for different payment methods
// eslint-disable-next-line prefer-const
export const canMakePaymentExtensionsCallbacks: NamespacedCanMakePaymentExtensionsCallbacks = {};
export const extensionsConfig = {
canMakePayment: canMakePaymentExtensionsCallbacks,
};

@ -0,0 +1 @@
export * from './registry';

@ -0,0 +1,90 @@
/**
* External dependencies
*/
import type {
CanMakePaymentCallback,
CanMakePaymentExtensionCallback,
} from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import {
NamespacedCanMakePaymentExtensionsCallbacks,
PaymentMethodName,
ExtensionNamespace,
extensionsConfig,
} from './extensions-config';
// Filter out payment methods by supported features and cart requirement.
export const canMakePaymentWithFeaturesCheck = (
canMakePayment: CanMakePaymentCallback,
features: string[]
): CanMakePaymentCallback => ( canPayArgument ) => {
const requirements = canPayArgument?.paymentRequirements || [];
const featuresSupportRequirements = requirements.every( ( requirement ) =>
features.includes( requirement )
);
return featuresSupportRequirements && canMakePayment( canPayArgument );
};
// Filter out payment methods by callbacks registered by extensions.
export const canMakePaymentWithExtensions = (
canMakePayment: CanMakePaymentCallback,
extensionsCallbacks: NamespacedCanMakePaymentExtensionsCallbacks,
paymentMethodName: PaymentMethodName
): CanMakePaymentCallback => ( canPayArgument ) => {
// Validate whether the payment method is available based on its own criteria first.
let canPay = canMakePayment( canPayArgument );
if ( canPay ) {
// Gather all callbacks for paymentMethodName.
const namespacedCallbacks: Record<
ExtensionNamespace,
CanMakePaymentExtensionCallback
> = {};
Object.entries( extensionsCallbacks ).forEach(
( [ namespace, callbacks ] ) => {
namespacedCallbacks[ namespace ] =
callbacks[ paymentMethodName ];
}
);
canPay = Object.keys( namespacedCallbacks ).every( ( namespace ) => {
try {
return namespacedCallbacks[ namespace ]( canPayArgument );
} catch ( err ) {
// eslint-disable-next-line no-console
console.error(
`Error when executing callback for ${ paymentMethodName } in ${ namespace }`,
err
);
// .every() expects a return value at the end of every arrow function and
// this ensures that the error is ignored when computing the whole result.
return true;
}
} );
}
return canPay;
};
export const getCanMakePayment = (
canMakePayment: CanMakePaymentCallback,
features: string[],
paymentMethodName: string
): CanMakePaymentCallback => {
const canPay = canMakePaymentWithFeaturesCheck( canMakePayment, features );
// Loop through all callbacks to check if there are any registered for this payment method.
return ( Object.values( extensionsConfig.canMakePayment ) as Record<
PaymentMethodName,
CanMakePaymentCallback
>[] ).some( ( callbacks ) => paymentMethodName in callbacks )
? canMakePaymentWithExtensions(
canPay,
extensionsConfig.canMakePayment,
paymentMethodName
)
: canPay;
};

@ -0,0 +1,167 @@
/**
* External dependencies
*/
import deprecated from '@wordpress/deprecated';
import type { ReactNode } from 'react';
import type {
PaymentMethodConfiguration,
Supports,
CanMakePaymentCallback,
PaymentMethodConfigInstance,
PaymentMethodIcons,
} from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import { getCanMakePayment } from './payment-method-config-helper';
import {
assertConfigHasProperties,
assertValidElement,
assertValidElementOrString,
} from './assertions';
const NullComponent = () => {
return null;
};
export default class PaymentMethodConfig
implements PaymentMethodConfigInstance {
public name: string;
public content: ReactNode;
public edit: ReactNode;
public paymentMethodId?: string;
public supports: Supports;
public icons: null | PaymentMethodIcons;
public label: ReactNode;
public ariaLabel: string;
public placeOrderButtonLabel?: string;
public savedTokenComponent?: ReactNode | null;
public canMakePaymentFromConfig: CanMakePaymentCallback;
constructor( config: PaymentMethodConfiguration ) {
// validate config
PaymentMethodConfig.assertValidConfig( config );
this.name = config.name;
this.label = config.label;
this.placeOrderButtonLabel = config.placeOrderButtonLabel;
this.ariaLabel = config.ariaLabel;
this.content = config.content;
this.savedTokenComponent = config.savedTokenComponent;
this.icons = config.icons || null;
this.edit = config.edit;
this.paymentMethodId = config.paymentMethodId || this.name;
this.supports = {
showSavedCards:
config?.supports?.showSavedCards ||
config?.supports?.savePaymentInfo || // Kept for backward compatibility if methods still pass this when registering.
false,
showSaveOption: config?.supports?.showSaveOption || false,
features: config?.supports?.features || [ 'products' ],
};
this.canMakePaymentFromConfig = config.canMakePayment;
}
// canMakePayment is calculated each time based on data that modifies outside of the class (eg: cart data).
get canMakePayment(): CanMakePaymentCallback {
return getCanMakePayment(
this.canMakePaymentFromConfig,
this.supports.features,
this.name
);
}
static assertValidConfig = ( config: PaymentMethodConfiguration ): void => {
// set default for optional
config.savedTokenComponent = config.savedTokenComponent || (
<NullComponent />
);
assertConfigHasProperties( config, [
'name',
'label',
'ariaLabel',
'content',
'edit',
'canMakePayment',
] );
if ( typeof config.name !== 'string' ) {
throw new Error(
'The name property for the payment method must be a string'
);
}
if (
typeof config.icons !== 'undefined' &&
! Array.isArray( config.icons ) &&
config.icons !== null
) {
throw new Error(
'The icons property for the payment method must be an array or null.'
);
}
if (
typeof config.paymentMethodId !== 'string' &&
typeof config.paymentMethodId !== 'undefined'
) {
throw new Error(
'The paymentMethodId property for the payment method must be a string or undefined (in which case it will be the value of the name property).'
);
}
if (
typeof config.placeOrderButtonLabel !== 'string' &&
typeof config.placeOrderButtonLabel !== 'undefined'
) {
throw new TypeError(
'The placeOrderButtonLabel property for the payment method must be a string'
);
}
assertValidElementOrString( config.label, 'label' );
assertValidElement( config.content, 'content' );
assertValidElement( config.edit, 'edit' );
assertValidElement( config.savedTokenComponent, 'savedTokenComponent' );
if ( typeof config.ariaLabel !== 'string' ) {
throw new TypeError(
'The ariaLabel property for the payment method must be a string'
);
}
if ( typeof config.canMakePayment !== 'function' ) {
throw new TypeError(
'The canMakePayment property for the payment method must be a function.'
);
}
if (
typeof config.supports?.showSavedCards !== 'undefined' &&
typeof config.supports?.showSavedCards !== 'boolean'
) {
throw new TypeError(
'If the payment method includes the `supports.showSavedCards` property, it must be a boolean'
);
}
if ( typeof config.supports?.savePaymentInfo !== 'undefined' ) {
deprecated(
'Passing savePaymentInfo when registering a payment method.',
{
alternative: 'Pass showSavedCards and showSaveOption',
plugin: 'woocommerce-gutenberg-products-block',
link:
'https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3686',
}
);
}
if (
typeof config.supports?.features !== 'undefined' &&
! Array.isArray( config.supports?.features )
) {
throw new Error(
'The features property for the payment method must be an array or undefined.'
);
}
if (
typeof config.supports?.showSaveOption !== 'undefined' &&
typeof config.supports?.showSaveOption !== 'boolean'
) {
throw new TypeError(
'If the payment method includes the `supports.showSaveOption` property, it must be a boolean'
);
}
};
}

@ -0,0 +1,130 @@
/**
* External dependencies
*/
import deprecated from '@wordpress/deprecated';
import type {
PaymentMethodConfiguration,
ExpressPaymentMethodConfiguration,
CanMakePaymentExtensionCallback,
PaymentMethodConfigInstance,
PaymentMethods,
ExpressPaymentMethods,
} from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import { default as PaymentMethodConfig } from './payment-method-config';
import { default as ExpressPaymentMethodConfig } from './express-payment-method-config';
import { canMakePaymentExtensionsCallbacks } from './extensions-config';
type LegacyRegisterPaymentMethodFunction = ( config: unknown ) => unknown;
type LegacyRegisterExpessPaymentMethodFunction = ( config: unknown ) => unknown;
const paymentMethods: PaymentMethods = {};
const expressPaymentMethods: ExpressPaymentMethods = {};
/**
* Register a regular payment method.
*/
export const registerPaymentMethod = (
options: PaymentMethodConfiguration | LegacyRegisterPaymentMethodFunction
): void => {
let paymentMethodConfig: PaymentMethodConfigInstance | unknown;
if ( typeof options === 'function' ) {
// Legacy fallback for previous API, where client passes a function:
// registerPaymentMethod( ( Config ) => new Config( options ) );
paymentMethodConfig = options( PaymentMethodConfig );
deprecated( 'Passing a callback to registerPaymentMethod()', {
alternative: 'a config options object',
plugin: 'woocommerce-gutenberg-products-block',
link:
'https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3404',
} );
} else {
paymentMethodConfig = new PaymentMethodConfig( options );
}
if ( paymentMethodConfig instanceof PaymentMethodConfig ) {
paymentMethods[ paymentMethodConfig.name ] = paymentMethodConfig;
}
};
/**
* Register an express payment method.
*/
export const registerExpressPaymentMethod = (
options:
| ExpressPaymentMethodConfiguration
| LegacyRegisterExpessPaymentMethodFunction
): void => {
let paymentMethodConfig;
if ( typeof options === 'function' ) {
// Legacy fallback for previous API, where client passes a function:
// registerExpressPaymentMethod( ( Config ) => new Config( options ) );
paymentMethodConfig = options( ExpressPaymentMethodConfig );
deprecated( 'Passing a callback to registerExpressPaymentMethod()', {
alternative: 'a config options object',
plugin: 'woocommerce-gutenberg-products-block',
link:
'https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3404',
} );
} else {
paymentMethodConfig = new ExpressPaymentMethodConfig( options );
}
if ( paymentMethodConfig instanceof ExpressPaymentMethodConfig ) {
expressPaymentMethods[ paymentMethodConfig.name ] = paymentMethodConfig;
}
};
/**
* Allows extension to register callbacks for specific payment methods to determine if they can make payments
*/
export const registerPaymentMethodExtensionCallbacks = (
namespace: string,
callbacks: Record< string, CanMakePaymentExtensionCallback >
): void => {
if ( canMakePaymentExtensionsCallbacks[ namespace ] ) {
// eslint-disable-next-line no-console
console.error(
`The namespace provided to registerPaymentMethodExtensionCallbacks must be unique. Callbacks have already been registered for the ${ namespace } namespace.`
);
} else {
// Set namespace up as an empty object.
canMakePaymentExtensionsCallbacks[ namespace ] = {};
Object.entries( callbacks ).forEach(
( [ paymentMethodName, callback ] ) => {
if ( typeof callback === 'function' ) {
canMakePaymentExtensionsCallbacks[ namespace ][
paymentMethodName
] = callback;
} else {
// eslint-disable-next-line no-console
console.error(
`All callbacks provided to registerPaymentMethodExtensionCallbacks must be functions. The callback for the ${ paymentMethodName } payment method in the ${ namespace } namespace was not a function.`
);
}
}
);
}
};
export const __experimentalDeRegisterPaymentMethod = (
paymentMethodName: string
): void => {
delete paymentMethods[ paymentMethodName ];
};
export const __experimentalDeRegisterExpressPaymentMethod = (
paymentMethodName: string
): void => {
delete expressPaymentMethods[ paymentMethodName ];
};
export const getPaymentMethods = (): PaymentMethods => {
return paymentMethods;
};
export const getExpressPaymentMethods = (): ExpressPaymentMethods => {
return expressPaymentMethods;
};

@ -0,0 +1,205 @@
/**
* External dependencies
*/
import { registerPaymentMethodExtensionCallbacks } from '@woocommerce/blocks-registry';
/**
* Internal dependencies
*/
import * as helpers from '../payment-method-config-helper';
import { canMakePaymentExtensionsCallbacks } from '../extensions-config';
const canMakePaymentArgument = {
cartTotals: {
total_items: '1488',
total_items_tax: '312',
total_fees: '0',
total_fees_tax: '0',
total_discount: '0',
total_discount_tax: '0',
total_shipping: '0',
total_shipping_tax: '0',
total_price: '1800',
total_tax: '312',
tax_lines: [
{
name: 'BTW',
price: '312',
rate: '21%',
},
],
currency_code: 'EUR',
currency_symbol: '€',
currency_minor_unit: 2,
currency_decimal_separator: ',',
currency_thousand_separator: '.',
currency_prefix: '€',
currency_suffix: '',
},
cartNeedsShipping: true,
billingData: {
first_name: 'name',
last_name: 'Name',
company: '',
address_1: 'fdsfdsfdsf',
address_2: '',
city: 'Berlin',
state: '',
postcode: 'xxxxx',
country: 'DE',
email: 'name.Name@test.com',
phone: '1234',
},
shippingAddress: {
first_name: 'name',
last_name: 'Name',
company: '',
address_1: 'fdsfdsfdsf',
address_2: '',
city: 'Berlin',
state: '',
postcode: 'xxxxx',
country: 'DE',
phone: '1234',
},
selectedShippingMethods: {
'0': 'free_shipping:1',
},
paymentRequirements: [ 'products' ],
};
describe( 'payment-method-config-helper', () => {
const trueCallback = jest.fn().mockReturnValue( true );
const falseCallback = jest.fn().mockReturnValue( false );
const bacsCallback = jest.fn().mockReturnValue( false );
const throwsCallback = jest.fn().mockImplementation( () => {
throw new Error();
} );
beforeAll( () => {
// Register extension callbacks for two payment methods.
registerPaymentMethodExtensionCallbacks(
'woocommerce-marketplace-extension',
{
// cod: one extension returns true, the other returns false.
cod: trueCallback,
// cheque: returns true only if arg.billingData.postcode is 12345.
cheque: ( arg ) => arg.billingData.postcode === '12345',
// bacs: both extensions return false.
bacs: bacsCallback,
// woopay: both extensions return true.
woopay: trueCallback,
// testpay: one callback errors, one returns true
testpay: throwsCallback,
}
);
registerPaymentMethodExtensionCallbacks(
'other-woocommerce-marketplace-extension',
{
cod: falseCallback,
woopay: trueCallback,
testpay: trueCallback,
bacs: bacsCallback,
}
);
} );
beforeEach( () => {
trueCallback.mockClear();
throwsCallback.mockClear();
falseCallback.mockClear();
bacsCallback.mockClear();
} );
describe( 'getCanMakePayment', () => {
it( 'returns callback canMakePaymentWithFeaturesCheck if no extension callback is detected', () => {
// Define arguments from a payment method ('missing-payment-method') with no registered extension callbacks.
const args = {
canMakePayment: jest.fn().mockImplementation( () => true ),
features: [ 'products' ],
paymentMethodName: 'missing-payment-method',
};
const canMakePayment = helpers.getCanMakePayment(
args.canMakePayment,
args.features,
args.paymentMethodName
)( canMakePaymentArgument );
// Expect that the result of getCanMakePayment is the result of
// the payment method's own canMakePayment, as no extension callbacks are called.
expect( canMakePayment ).toEqual( args.canMakePayment() );
} );
it( 'returns callbacks from the extensions when they are defined', () => {
// Define arguments from a payment method (bacs) with registered extension callbacks.
const args = {
canMakePaymentConfiguration: jest
.fn()
.mockImplementation( () => true ),
features: [ 'products' ],
paymentMethodName: 'bacs',
};
const canMakePayment = helpers.getCanMakePayment(
args.canMakePaymentConfiguration,
args.features,
args.paymentMethodName
)( canMakePaymentArgument );
// Expect that the result of getCanMakePayment is not the result of
// the payment method's own canMakePayment (args.canMakePaymentConfiguration),
// but of the registered bacsCallback.
expect( canMakePayment ).toBe( bacsCallback() );
} );
} );
describe( 'canMakePaymentWithExtensions', () => {
it( "Returns false without executing the registered callbacks, if the payment method's canMakePayment callback returns false.", () => {
const canMakePayment = () => false;
const canMakePaymentWithExtensionsResult = helpers.canMakePaymentWithExtensions(
canMakePayment,
canMakePaymentExtensionsCallbacks,
'cod'
)( canMakePaymentArgument );
expect( canMakePaymentWithExtensionsResult ).toBe( false );
expect( trueCallback ).not.toHaveBeenCalled();
} );
it( 'Returns early when a registered callback returns false, without executing all the registered callbacks', () => {
helpers.canMakePaymentWithExtensions(
() => true,
canMakePaymentExtensionsCallbacks,
'bacs'
)( canMakePaymentArgument );
expect( bacsCallback ).toHaveBeenCalledTimes( 1 );
} );
it( 'Returns true if all extension callbacks return true', () => {
const result = helpers.canMakePaymentWithExtensions(
() => true,
canMakePaymentExtensionsCallbacks,
'woopay'
)( canMakePaymentArgument );
expect( result ).toBe( true );
} );
it( 'Passes canPayArg to the callback', () => {
helpers.canMakePaymentWithExtensions(
() => true,
canMakePaymentExtensionsCallbacks,
'woopay'
)( canMakePaymentArgument );
expect( trueCallback ).toHaveBeenCalledWith(
canMakePaymentArgument
);
} );
it( 'Allows all valid callbacks to run, even if one causes an error', () => {
helpers.canMakePaymentWithExtensions(
() => true,
canMakePaymentExtensionsCallbacks,
'testpay'
)( canMakePaymentArgument );
expect( console ).toHaveErrored();
expect( throwsCallback ).toHaveBeenCalledTimes( 1 );
expect( trueCallback ).toHaveBeenCalledTimes( 1 );
} );
} );
} );

@ -0,0 +1,61 @@
/**
* External dependencies
*/
import { registerPaymentMethodExtensionCallbacks } from '@woocommerce/blocks-registry';
import type { PaymentMethodConfigInstance } from '@woocommerce/type-defs/payments';
/**
* Internal dependencies
*/
import PaymentMethodConfig from '../payment-method-config';
import * as paymentMethodConfigHelpers from '../payment-method-config-helper';
describe( 'PaymentMethodConfig', () => {
let paymentMethod: PaymentMethodConfigInstance;
const extensionsCallbackSpy = jest.spyOn(
paymentMethodConfigHelpers,
'canMakePaymentWithExtensions'
);
beforeEach( () => {
paymentMethod = new PaymentMethodConfig( {
name: 'test-payment-method',
label: 'Test payment method',
ariaLabel: 'Test payment method',
content: <div>Test payment content</div>,
edit: <div>Test payment edit</div>,
canMakePayment: () => true,
supports: { features: [ 'products' ] },
} );
} );
it( 'Uses canMakePaymentWithExtensions as the canMakePayment function if an extension registers a callback', () => {
registerPaymentMethodExtensionCallbacks(
'woocommerce-marketplace-extension',
{
'unrelated-payment-method': () => true,
}
);
// At this point, since no extensions have registered a callback for
// test-payment-method we can expect the canMakePayment getter NOT
// to execute canMakePaymentWithExtensions.
// Disable no-unused-expressions because we just want to test the getter
// eslint-disable-next-line no-unused-expressions
paymentMethod.canMakePayment;
expect( extensionsCallbackSpy ).toHaveBeenCalledTimes( 0 );
registerPaymentMethodExtensionCallbacks(
'other-woocommerce-marketplace-extension',
{
'test-payment-method': () => true,
}
);
// Now, because an extension _has_ registered a callback for test-payment-method
// The getter will use canMakePaymentWithExtensions to create the
// canMakePayment function.
// Disable no-unused-expressions because we just want to test the getter
// eslint-disable-next-line no-unused-expressions
paymentMethod.canMakePayment;
expect( extensionsCallbackSpy ).toHaveBeenCalledTimes( 1 );
} );
} );

@ -0,0 +1,97 @@
/**
* External dependencies
*/
import { registerPaymentMethodExtensionCallbacks } from '@woocommerce/blocks-registry';
/**
* Internal dependencies
*/
import { canMakePaymentExtensionsCallbacks } from '../extensions-config';
describe( 'registerPaymentMethodExtensionCallbacks', () => {
it( 'Logs an error to console if namespace is already registered', () => {
registerPaymentMethodExtensionCallbacks(
'woocommerce-marketplace-extension',
{
cod: () => false,
}
);
// eslint-disable-next-line no-console
expect( console ).not.toHaveErrored();
registerPaymentMethodExtensionCallbacks(
'woocommerce-marketplace-extension',
{
cod: () => false,
}
);
expect( console ).toHaveErrored();
// eslint-disable-next-line no-console
expect( console.error ).toHaveBeenCalledTimes( 1 );
} );
it( 'Does not overwrite a namespace if a second extensions tries to register with the same name', () => {
const firstCodCallback = jest.fn().mockReturnValue( false );
registerPaymentMethodExtensionCallbacks(
'overwrite-marketplace-extension',
{
cod: firstCodCallback,
}
);
// eslint-disable-next-line no-console
expect( console ).not.toHaveErrored();
registerPaymentMethodExtensionCallbacks(
'overwrite-marketplace-extension',
{
cod: () => false,
}
);
expect(
canMakePaymentExtensionsCallbacks[
'overwrite-marketplace-extension'
].cod
).toEqual( firstCodCallback );
} );
it( 'Logs an error if a supplied callback is not a function and does not register the callback for that method', () => {
registerPaymentMethodExtensionCallbacks(
'other-woocommerce-marketplace-extension',
{
cod: false,
cheque: () => true,
}
);
// eslint-disable-next-line no-console
expect( console ).toHaveErrored();
expect( canMakePaymentExtensionsCallbacks ).toHaveProperty(
'other-woocommerce-marketplace-extension'
);
expect(
canMakePaymentExtensionsCallbacks[
'other-woocommerce-marketplace-extension'
]
).not.toHaveProperty( 'cod' );
expect(
canMakePaymentExtensionsCallbacks[
'other-woocommerce-marketplace-extension'
]
).toHaveProperty( 'cheque' );
} );
it( 'Adds the namespace and callbacks to the canMakePaymentExtensionCallbacks object', () => {
// We are using a new namespace here because canMakePaymentExtensionsCallbacks cannot be reset between tests.
registerPaymentMethodExtensionCallbacks(
'third-woocommerce-marketplace-extension',
{
cod: () => false,
}
);
expect( canMakePaymentExtensionsCallbacks ).toHaveProperty(
'third-woocommerce-marketplace-extension'
);
} );
} );