WooCommerce Multilingual – run WooCommerce with WPML - Version 5.0.1

Version Description

Fixes * Fixed the upgrade routine for the attribute look-up table * Fixed a fatal error that occurred on sites running a WPML version older than 4.5.2 * Removed an obsolete filter on the woocommerce_create_page_id hook * Fixed an issue with duplication of product terms when using WPMLs Classic Translation Editor on WordPress 6.0

Compatibility * WooCommerce Product Bundles: Added translation support for bundle sales

Download this release

Release Info

Developer strategio
Plugin Icon 128x128 WooCommerce Multilingual – run WooCommerce with WPML
Version 5.0.1
Comparing to
See all releases

Code changes from version 4.12.6 to 5.0.1

Files changed (239) hide show
  1. addons/load-standalone-dependencies.php +48 -0
  2. addons/vendor/autoload.php +7 -0
  3. addons/vendor/composer/ClassLoader.php +445 -0
  4. addons/vendor/composer/LICENSE +21 -0
  5. addons/vendor/composer/autoload_classmap.php +506 -0
  6. addons/vendor/composer/autoload_files.php +14 -0
  7. addons/vendor/composer/autoload_namespaces.php +9 -0
  8. addons/vendor/composer/autoload_psr4.php +11 -0
  9. addons/vendor/composer/autoload_real.php +73 -0
  10. addons/vendor/composer/autoload_static.php +545 -0
  11. addons/vendor/composer/installed.json +799 -0
  12. addons/vendor/otgs/auryn/CONTRIBUTING.md +28 -0
  13. addons/vendor/otgs/auryn/LICENSE +21 -0
  14. addons/vendor/otgs/auryn/README.md +847 -0
  15. addons/vendor/otgs/auryn/lib/CachingReflector.php +108 -0
  16. addons/vendor/otgs/auryn/lib/ConfigException.php +7 -0
  17. addons/vendor/otgs/auryn/lib/Executable.php +82 -0
  18. addons/vendor/otgs/auryn/lib/InjectionException.php +67 -0
  19. addons/vendor/otgs/auryn/lib/Injector.php +757 -0
  20. addons/vendor/otgs/auryn/lib/InjectorException.php +7 -0
  21. addons/vendor/otgs/auryn/lib/ReflectionCache.php +9 -0
  22. addons/vendor/otgs/auryn/lib/ReflectionCacheApc.php +41 -0
  23. addons/vendor/otgs/auryn/lib/ReflectionCacheArray.php +22 -0
  24. addons/vendor/otgs/auryn/lib/Reflector.php +61 -0
  25. addons/vendor/otgs/auryn/lib/StandardReflector.php +53 -0
  26. addons/vendor/otgs/auryn/phpunit.xml +43 -0
  27. addons/vendor/otgs/icons +1 -0
  28. addons/vendor/otgs/ui +1 -0
  29. addons/vendor/wpml/collect/collect-logo.png +0 -0
  30. addons/vendor/wpml/collect/phpunit.xml +20 -0
  31. addons/vendor/wpml/collect/readme.md +19 -0
  32. addons/vendor/wpml/collect/src/Illuminate/Contracts/Support/Arrayable.php +13 -0
  33. addons/vendor/wpml/collect/src/Illuminate/Contracts/Support/Jsonable.php +14 -0
  34. addons/vendor/wpml/collect/src/Illuminate/Support/Arr.php +533 -0
  35. addons/vendor/wpml/collect/src/Illuminate/Support/Collection.php +1500 -0
  36. addons/vendor/wpml/collect/src/Illuminate/Support/Traits/Macroable.php +83 -0
  37. addons/vendor/wpml/collect/src/Illuminate/Support/helpers.php +84 -0
  38. addons/vendor/wpml/collect/tests/Support/SupportCollectionTest.php +1763 -0
  39. addons/vendor/wpml/collect/tests/bootstrap.php +5 -0
  40. addons/vendor/wpml/core-api +1 -0
  41. addons/vendor/wpml/fp +1 -0
  42. addons/vendor/wpml/wp +1 -0
  43. addons/vendor/wpml/wpml-dependencies +1 -0
  44. classes/AdminDashboard/Hooks.php +2 -2
  45. classes/AdminNotices/CachePlugins.php +6 -2
  46. classes/AdminNotices/MultiCurrencyMissing.php +2 -2
  47. classes/AdminNotices/Review.php +6 -5
  48. classes/Attributes/LookupFilters.php +36 -0
  49. classes/Attributes/LookupFiltersFactory.php +31 -0
  50. classes/Attributes/LookupTable.php +108 -0
  51. classes/Attributes/LookupTableFactory.php +30 -0
  52. classes/Block/Convert/Hooks.php +2 -2
  53. classes/Container/Config.php +25 -1
  54. classes/Email/Settings/Hooks.php +2 -2
  55. classes/HomeScreen/Factory.php +18 -0
  56. classes/HomeScreen/Hooks.php +26 -0
  57. classes/Multicurrency/Analytics/Factory.php +3 -1
  58. classes/Multicurrency/Analytics/Hooks.php +9 -5
  59. classes/Multicurrency/Resolver/ComposedResolver.php +32 -0
  60. classes/Multicurrency/Resolver/Factory.php +27 -0
  61. classes/Multicurrency/Resolver/HelperByLanguage.php +49 -0
  62. classes/Multicurrency/Resolver/HelperByLocation.php +33 -0
  63. classes/Multicurrency/Resolver/Resolver.php +11 -0
  64. classes/Multicurrency/Resolver/ResolverForContext.php +123 -0
  65. classes/Multicurrency/Resolver/ResolverForDefault.php +19 -0
  66. classes/Multicurrency/Resolver/ResolverForModeLanguage.php +77 -0
  67. classes/Multicurrency/Resolver/ResolverForModeLocation.php +30 -0
  68. classes/Multicurrency/Settings.php +203 -0
  69. classes/Multicurrency/Shipping/AdminHooks.php +3 -2
  70. classes/Multicurrency/Shipping/FreeShipping.php +4 -0
  71. classes/Multicurrency/Shipping/FrontEndHooks.php +2 -1
  72. classes/Multicurrency/Shipping/ShippingClasses.php +5 -2
  73. classes/Multicurrency/Shipping/ShippingHooksFactory.php +3 -1
  74. classes/Multicurrency/Shipping/VariableCost.php +2 -0
  75. classes/Multicurrency/Transient/Hooks.php +50 -0
  76. classes/Multicurrency/UI/Factory.php +6 -12
  77. classes/Multicurrency/UI/Hooks.php +29 -23
  78. classes/Options/WPML.php +8 -0
  79. classes/PaymentGateways/Hooks.php +3 -2
  80. classes/Reports/Orders/Factory.php +0 -29
  81. classes/Reports/Orders/Hooks.php +1 -3
  82. classes/Reports/Products/Query.php +8 -4
  83. classes/Rest/Exceptions/InvalidCurrency.php +1 -0
  84. classes/Rest/Exceptions/InvalidLanguage.php +1 -0
  85. classes/Rest/Exceptions/InvalidProduct.php +1 -0
  86. classes/Rest/Exceptions/InvalidTerm.php +1 -0
  87. classes/Rest/Functions.php +0 -7
  88. classes/Rest/Generic.php +21 -1
  89. classes/Rest/ProductSaveActions.php +1 -1
  90. classes/Rest/Wrapper/ProductTerms.php +1 -1
  91. classes/Rest/Wrapper/Products/Products.php +1 -1
  92. classes/Rest/Wrapper/Reports/ProductsCount.php +1 -1
  93. classes/Rest/Wrapper/Reports/TopSeller.php +1 -1
  94. classes/Reviews/Translations/Factory.php +1 -1
  95. classes/RewriteRules/Hooks.php +1 -1
  96. classes/StandAlone/ActionFilterLoader.php +47 -0
  97. classes/StandAlone/Container/Config.php +53 -0
  98. classes/StandAlone/DependencyAssets.php +45 -0
  99. classes/StandAlone/IStandAloneAction.php +5 -0
  100. classes/StandAlone/NullSitePress.php +143 -0
  101. classes/StandAlone/UI/AdminMenu.php +103 -0
  102. classes/Utilities/AdminPages.php +103 -0
  103. classes/Utilities/DB.php +38 -0
  104. classes/Utilities/WcAdminPages.php +53 -0
  105. classes/Utilities/WpAdminPages.php +15 -0
  106. classes/class-wcml-tracking-link.php +26 -5
  107. classes/class-woocommerce-wpml.php +77 -26
  108. classes/multi-currency/class-wcml-exchange-rates.php +102 -21
  109. classes/multi-currency/exchange-rate-services/ApiLayerService.php +93 -0
  110. classes/multi-currency/exchange-rate-services/CurrencyLayer.php +20 -45
  111. classes/multi-currency/exchange-rate-services/ExchangeRatesApi.php +6 -7
  112. classes/multi-currency/exchange-rate-services/Fixerio.php +6 -7
  113. classes/multi-currency/exchange-rate-services/Service.php +111 -21
  114. classes/multi-currency/geolocation/Geolocation.php +18 -76
  115. classes/multi-currency/geolocation/GeolocationBackendHooks.php +3 -1
  116. classes/multi-currency/geolocation/GeolocationFrontendHooks.php +3 -1
  117. classes/multi-currency/payment-gateways/class-wcml-currencies-payment-gateways.php +8 -5
  118. classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal-v2.php +95 -0
  119. classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal.php +5 -6
  120. classes/pointers/class-wcml-pointers.php +16 -9
  121. classes/privacy/class-wcml-privacy-content.php +3 -3
  122. classes/shortcodes/class-wcml-wc-shortcode-product-category.php +1 -1
  123. classes/taxonomy-translation/class-wcml-taxonomy-translation-link-filters.php +2 -0
  124. classes/urls/class-wcml-xdomain-data.php +1 -1
  125. classes/wcml-setup/class-wcml-setup.php +3 -3
  126. compatibility/AdventureTours/Factory.php +18 -0
  127. compatibility/{class-wcml-adventure-tours.php → AdventureTours/class-wcml-adventure-tours.php} +1 -1
  128. compatibility/Aurum/Factory.php +25 -0
  129. compatibility/{class-wcml-aurum.php → Aurum/MulticurrencyHooks.php} +8 -4
  130. compatibility/ComponentFactory.php +58 -0
  131. compatibility/Flatsome/Factory.php +16 -0
  132. compatibility/{class-wcml-flatsome.php → Flatsome/class-wcml-flatsome.php} +2 -2
  133. compatibility/GravityForms/Factory.php +34 -0
  134. compatibility/GravityForms/MulticurrencyHooks.php +37 -0
  135. compatibility/{class-wcml-gravityforms.php → GravityForms/class-wcml-gravityforms.php} +4 -22
  136. compatibility/KlarnaPayments/Factory.php +26 -0
  137. compatibility/{class-wcml-klarna-gateway.php → KlarnaPayments/MulticurrencyHooks.php} +3 -4
  138. compatibility/MaxStorePro/Factory.php +16 -0
  139. compatibility/{class-wcml-maxstore.php → MaxStorePro/class-wcml-maxstore.php} +1 -1
  140. compatibility/PerProductShipping/Factory.php +16 -0
  141. compatibility/{class-wcml-per-product-shipping.php → PerProductShipping/class-wcml-per-product-shipping.php} +2 -6
  142. compatibility/Relevanssi/Factory.php +16 -0
  143. compatibility/{class-wcml-relevanssi.php → Relevanssi/class-wcml-relevanssi.php} +1 -1
  144. compatibility/Sensei/Factory.php +18 -0
  145. compatibility/{class-wcml-sensei.php → Sensei/class-wcml-sensei.php} +1 -1
  146. compatibility/StripePayments/Factory.php +27 -0
  147. compatibility/StripePayments/MulticurrencyHooks.php +33 -0
  148. compatibility/TableRateShipping/Factory.php +36 -0
  149. compatibility/TableRateShipping/MulticurrencyHooks.php +64 -0
  150. compatibility/{class-wcml-table-rate-shipping.php → TableRateShipping/class-wcml-table-rate-shipping.php} +3 -46
  151. compatibility/TheEventsCalendar/Factory.php +34 -0
  152. compatibility/TheEventsCalendar/MulticurrencyHooks.php +22 -0
  153. compatibility/{class-wcml-the-events-calendar.php → TheEventsCalendar/class-wcml-the-events-calendar.php} +4 -8
  154. compatibility/TmExtraProductOptions/Factory.php +16 -0
  155. compatibility/{class-wcml-extra-product-options.php → TmExtraProductOptions/class-wcml-extra-product-options.php} +3 -3
  156. compatibility/WcAjaxLayeredNav/Factory.php +16 -0
  157. compatibility/{class-wcml-ajax-layered-nav-widget.php → WcAjaxLayeredNav/class-wcml-ajax-layered-nav-widget.php} +3 -2
  158. compatibility/WcBookings/Factory.php +42 -0
  159. compatibility/WcBookings/MulticurrencyHooks.php +936 -0
  160. compatibility/WcBookings/SharedHooks.php +86 -0
  161. compatibility/{class-wcml-accommodation-bookings.php → WcBookings/class-wcml-accommodation-bookings.php} +11 -28
  162. compatibility/{class-wcml-bookings.php → WcBookings/class-wcml-bookings.php} +109 -1045
  163. compatibility/WcBulkStockManagement/Factory.php +19 -0
  164. compatibility/{class-wcml-bulk-stock-management.php → WcBulkStockManagement/class-wcml-bulk-stock-management.php} +3 -2
  165. compatibility/WcCheckoutAddons/Factory.php +31 -0
  166. compatibility/WcCheckoutAddons/MulticurrencyHooks.php +30 -0
  167. compatibility/WcCheckoutAddons/OptionIterator.php +31 -0
  168. compatibility/WcCheckoutAddons/class-wcml-checkout-addons.php +47 -0
  169. compatibility/WcCheckoutFieldEditor/Factory.php +16 -0
  170. compatibility/{class-wcml-checkout-field-editor.php → WcCheckoutFieldEditor/class-wcml-checkout-field-editor.php} +1 -1
  171. compatibility/WcCompositeProducts/Factory.php +33 -0
  172. compatibility/WcCompositeProducts/MulticurrencyHooks.php +117 -0
  173. compatibility/{class-wcml-composite-products.php → WcCompositeProducts/class-wcml-composite-products.php} +139 -197
  174. compatibility/WcDynamicPricing/Factory.php +31 -0
  175. compatibility/WcDynamicPricing/MulticurrencyHooks.php +78 -0
  176. compatibility/{class-wcml-dynamic-pricing.php → WcDynamicPricing/class-wcml-dynamic-pricing.php} +2 -76
  177. compatibility/WcExporter/Factory.php +21 -0
  178. compatibility/{class-wcml-wcexporter.php → WcExporter/class-wcml-wcexporter.php} +1 -1
  179. compatibility/WcMemberships/Factory.php +15 -0
  180. compatibility/{class-wcml-wc-memberships.php → WcMemberships/class-wcml-wc-memberships.php} +1 -1
  181. compatibility/WcMixAndMatch/Factory.php +30 -0
  182. compatibility/WcMixAndMatch/MulticurrencyHooks.php +74 -0
  183. compatibility/WcMixAndMatch/class-wcml-mix-and-match-products.php +235 -0
  184. compatibility/WcNameYourPrice/Factory.php +26 -0
  185. compatibility/WcNameYourPrice/MulticurrencyHooks.php +110 -0
  186. compatibility/WcOrderStatusManager/Factory.php +17 -0
  187. compatibility/{class-wcml-order-status-manager.php → WcOrderStatusManager/class-wcml-order-status-manager.php} +1 -1
  188. compatibility/WcPip/Factory.php +31 -0
  189. compatibility/WcPip/Helper.php +28 -0
  190. compatibility/WcPip/MulticurrencyHooks.php +69 -0
  191. compatibility/WcPip/class-wcml-pip.php +29 -0
  192. compatibility/WcProductAddons/Factory.php +34 -0
  193. compatibility/WcProductAddons/MulticurrencyHooks.php +341 -0
  194. compatibility/WcProductAddons/SharedHooks.php +75 -0
  195. compatibility/WcProductAddons/class-wcml-product-addons.php +397 -0
  196. compatibility/WcProductBundles/Factory.php +31 -0
  197. compatibility/WcProductBundles/MulticurrencyHooks.php +65 -0
  198. compatibility/{class-wcml-product-bundles.php → WcProductBundles/class-wcml-product-bundles.php} +224 -93
  199. compatibility/{includes → WcProductBundles}/class-wcml-wc-product-bundles-items.php +0 -0
  200. compatibility/WcProductTypeColumn/Factory.php +16 -0
  201. compatibility/{class-wcml-wc-product-type-column.php → WcProductTypeColumn/class-wcml-wc-product-type-column.php} +1 -1
  202. compatibility/WcShowSingleVariations/Factory.php +19 -0
  203. compatibility/{class-wcml-jck-wssv.php → WcShowSingleVariations/class-wcml-jck-wssv.php} +2 -3
  204. compatibility/WcSubscriptions/Factory.php +34 -0
  205. compatibility/WcSubscriptions/MulticurrencyHooks.php +265 -0
  206. compatibility/WcSubscriptions/SharedHooks.php +41 -0
  207. compatibility/WcSubscriptions/class-wcml-wc-subscriptions.php +198 -0
  208. compatibility/WcSwatches/Factory.php +17 -0
  209. compatibility/{class-wcml-variation-swatches-and-photos.php → WcSwatches/class-wcml-variation-swatches-and-photos.php} +1 -1
  210. compatibility/WcTabManager/Factory.php +18 -0
  211. compatibility/{class-wcml-tab-manager.php → WcTabManager/class-wcml-tab-manager.php} +2 -1
  212. compatibility/WooVariationsTable/Factory.php +16 -0
  213. compatibility/{class-wcml-woo-var-table.php → WooVariationsTable/class-wcml-woo-var-table.php} +1 -1
  214. compatibility/WoobeBulkEditor/Factory.php +17 -0
  215. compatibility/{class-wcml-woobe.php → WoobeBulkEditor/class-wcml-woobe.php} +1 -1
  216. compatibility/WoofWcProductFilter/Factory.php +26 -0
  217. compatibility/{class-wcml-woof-woocommerce-product-filter.php → WoofWcProductFilter/MulticurrencyHooks.php} +9 -12
  218. compatibility/WpBakery/Factory.php +16 -0
  219. compatibility/{class-wcml-wpb-vc.php → WpBakery/class-wcml-wpb-vc.php} +1 -1
  220. compatibility/WpFastestCache/Factory.php +25 -0
  221. compatibility/{class-wcml-wpfastest-cache.php → WpFastestCache/MulticurrencyHooks.php} +3 -1
  222. compatibility/WpSeo/Factory.php +16 -0
  223. compatibility/{class-wcml-wpseo.php → WpSeo/class-wcml-wpseo.php} +2 -2
  224. compatibility/YikesCustomProductTabs/Factory.php +17 -0
  225. compatibility/{class-wcml-yikes-custom-product-tabs.php → YikesCustomProductTabs/class-wcml-yikes-custom-product-tabs.php} +2 -1
  226. compatibility/YithWcQuickView/Factory.php +25 -0
  227. compatibility/{class-wcml-yith-wcqv.php → YithWcQuickView/MulticurrencyHooks.php} +8 -5
  228. compatibility/class-wcml-checkout-addons.php +0 -61
  229. compatibility/class-wcml-compatibility-helper.php +1 -1
  230. compatibility/class-wcml-litespeed-cache.php +0 -26
  231. compatibility/class-wcml-mix-and-match-products.php +0 -53
  232. compatibility/class-wcml-pip.php +0 -104
  233. compatibility/class-wcml-product-addons.php +0 -664
  234. compatibility/class-wcml-wc-name-your-price.php +0 -29
  235. compatibility/class-wcml-wc-subscriptions.php +0 -460
  236. dist/css/homeScreen/styles.css +1 -0
  237. dist/css/multicurrencyOptions/styles.css +3 -1
  238. dist/js/homeScreen/app.js +1 -0
  239. dist/js/multicurrencyOptions/app.js +2 -2
addons/load-standalone-dependencies.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This bootstrap file is loaded only when WCML is running in the Standalone mode.
4
+ * It's executed on `plugins_loaded` priority 10000.
5
+ *
6
+ * @see load_wcml_without_wpml
7
+ */
8
+
9
+ /**
10
+ * This constant `WCML_WPML_DEPENDENCY_URL` is used in several places inside
11
+ * the dependency files (it replaces hard-coded URL base).
12
+ */
13
+ define( 'WCML_WPML_DEPENDENCY_URL', WCML_PLUGIN_URL . '/addons/vendor/wpml/wpml-dependencies/lib' );
14
+
15
+ require_once WCML_PLUGIN_PATH . '/addons/vendor/autoload.php';
16
+ require_once WCML_PLUGIN_PATH . '/addons/vendor/wpml/wpml-dependencies/lib/missing-functions.php';
17
+
18
+ $setPartialDicConfigFromCore = function() {
19
+ \WPML\Container\share( \WCML\StandAlone\Container\Config::getSharedInstances() );
20
+ \WPML\Container\share( \WCML\StandAlone\Container\Config::getSharedClasses() );
21
+ \WPML\Container\alias( \WCML\StandAlone\Container\Config::getAliases() );
22
+ \WPML\Container\delegate( \WCML\StandAlone\Container\Config::getDelegated() );
23
+ };
24
+
25
+ $setPartialDicConfigFromCore();
26
+
27
+ if ( is_admin() ) {
28
+ require_once WCML_PLUGIN_PATH . '/addons/vendor/wpml/wpml-dependencies/lib/inc/icl-admin-notifier.php';
29
+
30
+ $loadOtgsIconsStyles = function() {
31
+ $vendor_root_url = WCML_PLUGIN_URL . '/addons/vendor';
32
+ require_once WCML_PLUGIN_PATH . '/addons/vendor/otgs/icons/loader.php';
33
+
34
+ add_action( 'admin_init', function() {
35
+ wp_enqueue_style( OTGS_ASSETS_ICONS_STYLES );
36
+ }, PHP_INT_MAX );
37
+ };
38
+
39
+ $loadOtgsIconsStyles();
40
+
41
+ ( new \WCML\StandAlone\DependencyAssets( WCML_WPML_DEPENDENCY_URL ) )->add_hooks();
42
+
43
+ wcml_wpml_get_admin_notices(); // Initialize the notices hooks
44
+
45
+ ( new WPML_Action_Filter_Loader() )->load( [
46
+ \WPML\Notices\DismissNotices::class,
47
+ ] );
48
+ }
addons/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit4821ed1a7ed1caf1298338b695908544::getLoader();
addons/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath . '\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
addons/vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
addons/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,506 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'ICL_AdminNotifier' => $vendorDir . '/wpml/wpml-dependencies/lib/inc/icl-admin-notifier.php',
10
+ 'IWPML_AJAX_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-ajax-action.php',
11
+ 'IWPML_AJAX_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-ajax-action-loader.php',
12
+ 'IWPML_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-action.php',
13
+ 'IWPML_Action_Loader_Factory' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-action-loader-factory.php',
14
+ 'IWPML_Backend_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-backend-action.php',
15
+ 'IWPML_Backend_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-backend-action-loader.php',
16
+ 'IWPML_CLI_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-cli-action.php',
17
+ 'IWPML_CLI_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-cli-action-loader.php',
18
+ 'IWPML_Current_Language' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/languages/interface-iwpml-current-language.php',
19
+ 'IWPML_DIC_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-dic-action.php',
20
+ 'IWPML_Deferred_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-deferred-action-loader.php',
21
+ 'IWPML_Frontend_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-frontend-action.php',
22
+ 'IWPML_Frontend_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-frontend-action-loader.php',
23
+ 'IWPML_REST_Action' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-rest-action.php',
24
+ 'IWPML_REST_Action_Loader' => $vendorDir . '/wpml/core-api/core/interfaces/actions/interface-iwpml-rest-action-loader.php',
25
+ 'IWPML_Template_Service' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/templates/interface-iwpml-template-service.php',
26
+ 'IWPML_WP_Element_Type' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/iwpml-wp-element-type.php',
27
+ 'OTGS_Assets_Handles' => $vendorDir . '/otgs/ui/src/php/OTGS_Assets_Handles.php',
28
+ 'OTGS_Assets_Store' => $vendorDir . '/otgs/ui/src/php/OTGS_Assets_Store.php',
29
+ 'OTGS_UI_Assets' => $vendorDir . '/otgs/ui/src/php/OTGS_UI_Assets.php',
30
+ 'OTGS_UI_Loader' => $vendorDir . '/otgs/ui/src/php/OTGS_UI_Loader.php',
31
+ 'WPML\\API\\PostTypes' => $vendorDir . '/wpml/core-api/core/PostTypes.php',
32
+ 'WPML\\API\\Settings' => $vendorDir . '/wpml/core-api/core/Settings.php',
33
+ 'WPML\\API\\Version' => $vendorDir . '/wpml/core-api/core/Version.php',
34
+ 'WPML\\Action\\Type' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-action-type.php',
35
+ 'WPML\\Ajax\\IHandler' => $vendorDir . '/wpml/core-api/core/interfaces/ajax/Handler.php',
36
+ 'WPML\\Container\\Config' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/container/class-config.php',
37
+ 'WPML\\Container\\Container' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/container/class-wpml-container.php',
38
+ 'WPML\\Core\\BackgroundTask' => $vendorDir . '/wpml/core-api/core/utility/BackgroundTask.php',
39
+ 'WPML\\Core\\ISitePress' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/ISitePress.php',
40
+ 'WPML\\Core\\Twig\\Cache\\CacheInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/CacheInterface.php',
41
+ 'WPML\\Core\\Twig\\Cache\\FilesystemCache' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/FilesystemCache.php',
42
+ 'WPML\\Core\\Twig\\Cache\\NullCache' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/NullCache.php',
43
+ 'WPML\\Core\\Twig\\Compiler' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Compiler.php',
44
+ 'WPML\\Core\\Twig\\Environment' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Environment.php',
45
+ 'WPML\\Core\\Twig\\Error\\Error' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/Error.php',
46
+ 'WPML\\Core\\Twig\\Error\\LoaderError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/LoaderError.php',
47
+ 'WPML\\Core\\Twig\\Error\\RuntimeError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/RuntimeError.php',
48
+ 'WPML\\Core\\Twig\\Error\\SyntaxError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/SyntaxError.php',
49
+ 'WPML\\Core\\Twig\\ExpressionParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/ExpressionParser.php',
50
+ 'WPML\\Core\\Twig\\Extension\\AbstractExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/AbstractExtension.php',
51
+ 'WPML\\Core\\Twig\\Extension\\CoreExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/CoreExtension.php',
52
+ 'WPML\\Core\\Twig\\Extension\\DebugExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/DebugExtension.php',
53
+ 'WPML\\Core\\Twig\\Extension\\EscaperExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/EscaperExtension.php',
54
+ 'WPML\\Core\\Twig\\Extension\\ExtensionInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/ExtensionInterface.php',
55
+ 'WPML\\Core\\Twig\\Extension\\GlobalsInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/GlobalsInterface.php',
56
+ 'WPML\\Core\\Twig\\Extension\\InitRuntimeInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/InitRuntimeInterface.php',
57
+ 'WPML\\Core\\Twig\\Extension\\OptimizerExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/OptimizerExtension.php',
58
+ 'WPML\\Core\\Twig\\Extension\\ProfilerExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/ProfilerExtension.php',
59
+ 'WPML\\Core\\Twig\\Extension\\RuntimeExtensionInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/RuntimeExtensionInterface.php',
60
+ 'WPML\\Core\\Twig\\Extension\\SandboxExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/SandboxExtension.php',
61
+ 'WPML\\Core\\Twig\\Extension\\StagingExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/StagingExtension.php',
62
+ 'WPML\\Core\\Twig\\Extension\\StringLoaderExtension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/StringLoaderExtension.php',
63
+ 'WPML\\Core\\Twig\\FileExtensionEscapingStrategy' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/FileExtensionEscapingStrategy.php',
64
+ 'WPML\\Core\\Twig\\Lexer' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Lexer.php',
65
+ 'WPML\\Core\\Twig\\Loader\\ArrayLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ArrayLoader.php',
66
+ 'WPML\\Core\\Twig\\Loader\\ChainLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ChainLoader.php',
67
+ 'WPML\\Core\\Twig\\Loader\\ExistsLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ExistsLoaderInterface.php',
68
+ 'WPML\\Core\\Twig\\Loader\\FilesystemLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/FilesystemLoader.php',
69
+ 'WPML\\Core\\Twig\\Loader\\LoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/LoaderInterface.php',
70
+ 'WPML\\Core\\Twig\\Loader\\SourceContextLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/SourceContextLoaderInterface.php',
71
+ 'WPML\\Core\\Twig\\Markup' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Markup.php',
72
+ 'WPML\\Core\\Twig\\NodeTraverser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeTraverser.php',
73
+ 'WPML\\Core\\Twig\\NodeVisitor\\AbstractNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/AbstractNodeVisitor.php',
74
+ 'WPML\\Core\\Twig\\NodeVisitor\\EscaperNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/EscaperNodeVisitor.php',
75
+ 'WPML\\Core\\Twig\\NodeVisitor\\NodeVisitorInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/NodeVisitorInterface.php',
76
+ 'WPML\\Core\\Twig\\NodeVisitor\\OptimizerNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/OptimizerNodeVisitor.php',
77
+ 'WPML\\Core\\Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php',
78
+ 'WPML\\Core\\Twig\\NodeVisitor\\SandboxNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/SandboxNodeVisitor.php',
79
+ 'WPML\\Core\\Twig\\Node\\AutoEscapeNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/AutoEscapeNode.php',
80
+ 'WPML\\Core\\Twig\\Node\\BlockNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BlockNode.php',
81
+ 'WPML\\Core\\Twig\\Node\\BlockReferenceNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BlockReferenceNode.php',
82
+ 'WPML\\Core\\Twig\\Node\\BodyNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BodyNode.php',
83
+ 'WPML\\Core\\Twig\\Node\\CheckSecurityNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/CheckSecurityNode.php',
84
+ 'WPML\\Core\\Twig\\Node\\CheckToStringNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/CheckToStringNode.php',
85
+ 'WPML\\Core\\Twig\\Node\\DeprecatedNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/DeprecatedNode.php',
86
+ 'WPML\\Core\\Twig\\Node\\DoNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/DoNode.php',
87
+ 'WPML\\Core\\Twig\\Node\\EmbedNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/EmbedNode.php',
88
+ 'WPML\\Core\\Twig\\Node\\Expression\\AbstractExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/AbstractExpression.php',
89
+ 'WPML\\Core\\Twig\\Node\\Expression\\ArrayExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ArrayExpression.php',
90
+ 'WPML\\Core\\Twig\\Node\\Expression\\ArrowFunctionExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ArrowFunctionExpression.php',
91
+ 'WPML\\Core\\Twig\\Node\\Expression\\AssignNameExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/AssignNameExpression.php',
92
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AbstractBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AbstractBinary.php',
93
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AddBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AddBinary.php',
94
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AndBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AndBinary.php',
95
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseAndBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseAndBinary.php',
96
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseOrBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseOrBinary.php',
97
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseXorBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseXorBinary.php',
98
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\ConcatBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/ConcatBinary.php',
99
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\DivBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/DivBinary.php',
100
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\EndsWithBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/EndsWithBinary.php',
101
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\EqualBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/EqualBinary.php',
102
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\FloorDivBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/FloorDivBinary.php',
103
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\GreaterBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/GreaterBinary.php',
104
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/GreaterEqualBinary.php',
105
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\InBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/InBinary.php',
106
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\LessBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/LessBinary.php',
107
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\LessEqualBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/LessEqualBinary.php',
108
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\MatchesBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/MatchesBinary.php',
109
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\ModBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/ModBinary.php',
110
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\MulBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/MulBinary.php',
111
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\NotEqualBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/NotEqualBinary.php',
112
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\NotInBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/NotInBinary.php',
113
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\OrBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/OrBinary.php',
114
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\PowerBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/PowerBinary.php',
115
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\RangeBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/RangeBinary.php',
116
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\StartsWithBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/StartsWithBinary.php',
117
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\SubBinary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/SubBinary.php',
118
+ 'WPML\\Core\\Twig\\Node\\Expression\\BlockReferenceExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/BlockReferenceExpression.php',
119
+ 'WPML\\Core\\Twig\\Node\\Expression\\CallExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/CallExpression.php',
120
+ 'WPML\\Core\\Twig\\Node\\Expression\\ConditionalExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ConditionalExpression.php',
121
+ 'WPML\\Core\\Twig\\Node\\Expression\\ConstantExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ConstantExpression.php',
122
+ 'WPML\\Core\\Twig\\Node\\Expression\\FilterExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/FilterExpression.php',
123
+ 'WPML\\Core\\Twig\\Node\\Expression\\Filter\\DefaultFilter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Filter/DefaultFilter.php',
124
+ 'WPML\\Core\\Twig\\Node\\Expression\\FunctionExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/FunctionExpression.php',
125
+ 'WPML\\Core\\Twig\\Node\\Expression\\GetAttrExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/GetAttrExpression.php',
126
+ 'WPML\\Core\\Twig\\Node\\Expression\\InlinePrint' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/InlinePrint.php',
127
+ 'WPML\\Core\\Twig\\Node\\Expression\\MethodCallExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/MethodCallExpression.php',
128
+ 'WPML\\Core\\Twig\\Node\\Expression\\NameExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/NameExpression.php',
129
+ 'WPML\\Core\\Twig\\Node\\Expression\\NullCoalesceExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/NullCoalesceExpression.php',
130
+ 'WPML\\Core\\Twig\\Node\\Expression\\ParentExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ParentExpression.php',
131
+ 'WPML\\Core\\Twig\\Node\\Expression\\TempNameExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/TempNameExpression.php',
132
+ 'WPML\\Core\\Twig\\Node\\Expression\\TestExpression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/TestExpression.php',
133
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\ConstantTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/ConstantTest.php',
134
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\DefinedTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/DefinedTest.php',
135
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\DivisiblebyTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/DivisiblebyTest.php',
136
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\EvenTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/EvenTest.php',
137
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\NullTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/NullTest.php',
138
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\OddTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/OddTest.php',
139
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\SameasTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/SameasTest.php',
140
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\AbstractUnary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/AbstractUnary.php',
141
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\NegUnary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/NegUnary.php',
142
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\NotUnary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/NotUnary.php',
143
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\PosUnary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/PosUnary.php',
144
+ 'WPML\\Core\\Twig\\Node\\FlushNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/FlushNode.php',
145
+ 'WPML\\Core\\Twig\\Node\\ForLoopNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ForLoopNode.php',
146
+ 'WPML\\Core\\Twig\\Node\\ForNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ForNode.php',
147
+ 'WPML\\Core\\Twig\\Node\\IfNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/IfNode.php',
148
+ 'WPML\\Core\\Twig\\Node\\ImportNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ImportNode.php',
149
+ 'WPML\\Core\\Twig\\Node\\IncludeNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/IncludeNode.php',
150
+ 'WPML\\Core\\Twig\\Node\\MacroNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/MacroNode.php',
151
+ 'WPML\\Core\\Twig\\Node\\ModuleNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ModuleNode.php',
152
+ 'WPML\\Core\\Twig\\Node\\Node' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Node.php',
153
+ 'WPML\\Core\\Twig\\Node\\NodeCaptureInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/NodeCaptureInterface.php',
154
+ 'WPML\\Core\\Twig\\Node\\NodeOutputInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/NodeOutputInterface.php',
155
+ 'WPML\\Core\\Twig\\Node\\PrintNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/PrintNode.php',
156
+ 'WPML\\Core\\Twig\\Node\\SandboxNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SandboxNode.php',
157
+ 'WPML\\Core\\Twig\\Node\\SandboxedPrintNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SandboxedPrintNode.php',
158
+ 'WPML\\Core\\Twig\\Node\\SetNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SetNode.php',
159
+ 'WPML\\Core\\Twig\\Node\\SetTempNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SetTempNode.php',
160
+ 'WPML\\Core\\Twig\\Node\\SpacelessNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SpacelessNode.php',
161
+ 'WPML\\Core\\Twig\\Node\\TextNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/TextNode.php',
162
+ 'WPML\\Core\\Twig\\Node\\WithNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/WithNode.php',
163
+ 'WPML\\Core\\Twig\\Parser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Parser.php',
164
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\BaseDumper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/BaseDumper.php',
165
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\BlackfireDumper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/BlackfireDumper.php',
166
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\HtmlDumper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/HtmlDumper.php',
167
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\TextDumper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/TextDumper.php',
168
+ 'WPML\\Core\\Twig\\Profiler\\NodeVisitor\\ProfilerNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php',
169
+ 'WPML\\Core\\Twig\\Profiler\\Node\\EnterProfileNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Node/EnterProfileNode.php',
170
+ 'WPML\\Core\\Twig\\Profiler\\Node\\LeaveProfileNode' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Node/LeaveProfileNode.php',
171
+ 'WPML\\Core\\Twig\\Profiler\\Profile' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Profile.php',
172
+ 'WPML\\Core\\Twig\\RuntimeLoader\\ContainerRuntimeLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/ContainerRuntimeLoader.php',
173
+ 'WPML\\Core\\Twig\\RuntimeLoader\\FactoryRuntimeLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/FactoryRuntimeLoader.php',
174
+ 'WPML\\Core\\Twig\\RuntimeLoader\\RuntimeLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/RuntimeLoaderInterface.php',
175
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityError.php',
176
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedFilterError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedFilterError.php',
177
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedFunctionError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedFunctionError.php',
178
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedMethodError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedMethodError.php',
179
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedPropertyError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedPropertyError.php',
180
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedTagError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedTagError.php',
181
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityPolicy' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityPolicy.php',
182
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityPolicyInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityPolicyInterface.php',
183
+ 'WPML\\Core\\Twig\\Source' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Source.php',
184
+ 'WPML\\Core\\Twig\\Template' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Template.php',
185
+ 'WPML\\Core\\Twig\\TemplateWrapper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TemplateWrapper.php',
186
+ 'WPML\\Core\\Twig\\Test\\IntegrationTestCase' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Test/IntegrationTestCase.php',
187
+ 'WPML\\Core\\Twig\\Test\\NodeTestCase' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Test/NodeTestCase.php',
188
+ 'WPML\\Core\\Twig\\Token' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Token.php',
189
+ 'WPML\\Core\\Twig\\TokenParser\\AbstractTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/AbstractTokenParser.php',
190
+ 'WPML\\Core\\Twig\\TokenParser\\ApplyTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ApplyTokenParser.php',
191
+ 'WPML\\Core\\Twig\\TokenParser\\AutoEscapeTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/AutoEscapeTokenParser.php',
192
+ 'WPML\\Core\\Twig\\TokenParser\\BlockTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/BlockTokenParser.php',
193
+ 'WPML\\Core\\Twig\\TokenParser\\DeprecatedTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/DeprecatedTokenParser.php',
194
+ 'WPML\\Core\\Twig\\TokenParser\\DoTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/DoTokenParser.php',
195
+ 'WPML\\Core\\Twig\\TokenParser\\EmbedTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/EmbedTokenParser.php',
196
+ 'WPML\\Core\\Twig\\TokenParser\\ExtendsTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ExtendsTokenParser.php',
197
+ 'WPML\\Core\\Twig\\TokenParser\\FilterTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FilterTokenParser.php',
198
+ 'WPML\\Core\\Twig\\TokenParser\\FlushTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FlushTokenParser.php',
199
+ 'WPML\\Core\\Twig\\TokenParser\\ForTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ForTokenParser.php',
200
+ 'WPML\\Core\\Twig\\TokenParser\\FromTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FromTokenParser.php',
201
+ 'WPML\\Core\\Twig\\TokenParser\\IfTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/IfTokenParser.php',
202
+ 'WPML\\Core\\Twig\\TokenParser\\ImportTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ImportTokenParser.php',
203
+ 'WPML\\Core\\Twig\\TokenParser\\IncludeTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/IncludeTokenParser.php',
204
+ 'WPML\\Core\\Twig\\TokenParser\\MacroTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/MacroTokenParser.php',
205
+ 'WPML\\Core\\Twig\\TokenParser\\SandboxTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SandboxTokenParser.php',
206
+ 'WPML\\Core\\Twig\\TokenParser\\SetTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SetTokenParser.php',
207
+ 'WPML\\Core\\Twig\\TokenParser\\SpacelessTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SpacelessTokenParser.php',
208
+ 'WPML\\Core\\Twig\\TokenParser\\TokenParserInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/TokenParserInterface.php',
209
+ 'WPML\\Core\\Twig\\TokenParser\\UseTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/UseTokenParser.php',
210
+ 'WPML\\Core\\Twig\\TokenParser\\WithTokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/WithTokenParser.php',
211
+ 'WPML\\Core\\Twig\\TokenStream' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenStream.php',
212
+ 'WPML\\Core\\Twig\\TwigFilter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigFilter.php',
213
+ 'WPML\\Core\\Twig\\TwigFunction' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigFunction.php',
214
+ 'WPML\\Core\\Twig\\TwigTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigTest.php',
215
+ 'WPML\\Core\\Twig\\Util\\DeprecationCollector' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Util/DeprecationCollector.php',
216
+ 'WPML\\Core\\Twig\\Util\\TemplateDirIterator' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/src/Util/TemplateDirIterator.php',
217
+ 'WPML\\Core\\Twig_Autoloader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Autoloader.php',
218
+ 'WPML\\Core\\Twig_BaseNodeVisitor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/BaseNodeVisitor.php',
219
+ 'WPML\\Core\\Twig_CacheInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/CacheInterface.php',
220
+ 'WPML\\Core\\Twig_Cache_Filesystem' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Cache/Filesystem.php',
221
+ 'WPML\\Core\\Twig_Cache_Null' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Cache/Null.php',
222
+ 'WPML\\Core\\Twig_Compiler' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Compiler.php',
223
+ 'WPML\\Core\\Twig_CompilerInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/CompilerInterface.php',
224
+ 'WPML\\Core\\Twig_ContainerRuntimeLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ContainerRuntimeLoader.php',
225
+ 'WPML\\Core\\Twig_Environment' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Environment.php',
226
+ 'WPML\\Core\\Twig_Error' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error.php',
227
+ 'WPML\\Core\\Twig_Error_Loader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Loader.php',
228
+ 'WPML\\Core\\Twig_Error_Runtime' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Runtime.php',
229
+ 'WPML\\Core\\Twig_Error_Syntax' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Syntax.php',
230
+ 'WPML\\Core\\Twig_ExistsLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExistsLoaderInterface.php',
231
+ 'WPML\\Core\\Twig_ExpressionParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExpressionParser.php',
232
+ 'WPML\\Core\\Twig_Extension' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension.php',
233
+ 'WPML\\Core\\Twig_ExtensionInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExtensionInterface.php',
234
+ 'WPML\\Core\\Twig_Extension_Core' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Core.php',
235
+ 'WPML\\Core\\Twig_Extension_Debug' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Debug.php',
236
+ 'WPML\\Core\\Twig_Extension_Escaper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Escaper.php',
237
+ 'WPML\\Core\\Twig_Extension_GlobalsInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/GlobalsInterface.php',
238
+ 'WPML\\Core\\Twig_Extension_InitRuntimeInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/InitRuntimeInterface.php',
239
+ 'WPML\\Core\\Twig_Extension_Optimizer' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Optimizer.php',
240
+ 'WPML\\Core\\Twig_Extension_Profiler' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Profiler.php',
241
+ 'WPML\\Core\\Twig_Extension_Sandbox' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Sandbox.php',
242
+ 'WPML\\Core\\Twig_Extension_Staging' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Staging.php',
243
+ 'WPML\\Core\\Twig_Extension_StringLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/StringLoader.php',
244
+ 'WPML\\Core\\Twig_FactoryRuntimeLoader' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FactoryRuntimeLoader.php',
245
+ 'WPML\\Core\\Twig_FileExtensionEscapingStrategy' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FileExtensionEscapingStrategy.php',
246
+ 'WPML\\Core\\Twig_Filter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter.php',
247
+ 'WPML\\Core\\Twig_FilterCallableInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FilterCallableInterface.php',
248
+ 'WPML\\Core\\Twig_FilterInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FilterInterface.php',
249
+ 'WPML\\Core\\Twig_Filter_Function' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Function.php',
250
+ 'WPML\\Core\\Twig_Filter_Method' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Method.php',
251
+ 'WPML\\Core\\Twig_Filter_Node' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Node.php',
252
+ 'WPML\\Core\\Twig_Function' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function.php',
253
+ 'WPML\\Core\\Twig_FunctionCallableInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FunctionCallableInterface.php',
254
+ 'WPML\\Core\\Twig_FunctionInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FunctionInterface.php',
255
+ 'WPML\\Core\\Twig_Function_Function' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Function.php',
256
+ 'WPML\\Core\\Twig_Function_Method' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Method.php',
257
+ 'WPML\\Core\\Twig_Function_Node' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Node.php',
258
+ 'WPML\\Core\\Twig_Lexer' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Lexer.php',
259
+ 'WPML\\Core\\Twig_LexerInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/LexerInterface.php',
260
+ 'WPML\\Core\\Twig_LoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/LoaderInterface.php',
261
+ 'WPML\\Core\\Twig_Loader_Array' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Array.php',
262
+ 'WPML\\Core\\Twig_Loader_Chain' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Chain.php',
263
+ 'WPML\\Core\\Twig_Loader_Filesystem' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Filesystem.php',
264
+ 'WPML\\Core\\Twig_Loader_String' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/String.php',
265
+ 'WPML\\Core\\Twig_Markup' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Markup.php',
266
+ 'WPML\\Core\\Twig_Node' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node.php',
267
+ 'WPML\\Core\\Twig_NodeCaptureInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeCaptureInterface.php',
268
+ 'WPML\\Core\\Twig_NodeInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeInterface.php',
269
+ 'WPML\\Core\\Twig_NodeOutputInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeOutputInterface.php',
270
+ 'WPML\\Core\\Twig_NodeTraverser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeTraverser.php',
271
+ 'WPML\\Core\\Twig_NodeVisitorInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitorInterface.php',
272
+ 'WPML\\Core\\Twig_NodeVisitor_Escaper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Escaper.php',
273
+ 'WPML\\Core\\Twig_NodeVisitor_Optimizer' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Optimizer.php',
274
+ 'WPML\\Core\\Twig_NodeVisitor_SafeAnalysis' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/SafeAnalysis.php',
275
+ 'WPML\\Core\\Twig_NodeVisitor_Sandbox' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Sandbox.php',
276
+ 'WPML\\Core\\Twig_Node_AutoEscape' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/AutoEscape.php',
277
+ 'WPML\\Core\\Twig_Node_Block' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Block.php',
278
+ 'WPML\\Core\\Twig_Node_BlockReference' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/BlockReference.php',
279
+ 'WPML\\Core\\Twig_Node_Body' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Body.php',
280
+ 'WPML\\Core\\Twig_Node_CheckSecurity' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/CheckSecurity.php',
281
+ 'WPML\\Core\\Twig_Node_Deprecated' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Deprecated.php',
282
+ 'WPML\\Core\\Twig_Node_Do' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Do.php',
283
+ 'WPML\\Core\\Twig_Node_Embed' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Embed.php',
284
+ 'WPML\\Core\\Twig_Node_Expression' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression.php',
285
+ 'WPML\\Core\\Twig_Node_Expression_Array' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Array.php',
286
+ 'WPML\\Core\\Twig_Node_Expression_AssignName' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/AssignName.php',
287
+ 'WPML\\Core\\Twig_Node_Expression_Binary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary.php',
288
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Add' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Add.php',
289
+ 'WPML\\Core\\Twig_Node_Expression_Binary_And' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/And.php',
290
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseAnd' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php',
291
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseOr' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php',
292
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseXor' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php',
293
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Concat' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Concat.php',
294
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Div' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Div.php',
295
+ 'WPML\\Core\\Twig_Node_Expression_Binary_EndsWith' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/EndsWith.php',
296
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Equal' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Equal.php',
297
+ 'WPML\\Core\\Twig_Node_Expression_Binary_FloorDiv' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php',
298
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Greater' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Greater.php',
299
+ 'WPML\\Core\\Twig_Node_Expression_Binary_GreaterEqual' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php',
300
+ 'WPML\\Core\\Twig_Node_Expression_Binary_In' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/In.php',
301
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Less' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Less.php',
302
+ 'WPML\\Core\\Twig_Node_Expression_Binary_LessEqual' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/LessEqual.php',
303
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Matches' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Matches.php',
304
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Mod' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Mod.php',
305
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Mul' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Mul.php',
306
+ 'WPML\\Core\\Twig_Node_Expression_Binary_NotEqual' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/NotEqual.php',
307
+ 'WPML\\Core\\Twig_Node_Expression_Binary_NotIn' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/NotIn.php',
308
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Or' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Or.php',
309
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Power' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Power.php',
310
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Range' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Range.php',
311
+ 'WPML\\Core\\Twig_Node_Expression_Binary_StartsWith' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/StartsWith.php',
312
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Sub' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Sub.php',
313
+ 'WPML\\Core\\Twig_Node_Expression_BlockReference' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/BlockReference.php',
314
+ 'WPML\\Core\\Twig_Node_Expression_Call' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Call.php',
315
+ 'WPML\\Core\\Twig_Node_Expression_Conditional' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Conditional.php',
316
+ 'WPML\\Core\\Twig_Node_Expression_Constant' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Constant.php',
317
+ 'WPML\\Core\\Twig_Node_Expression_ExtensionReference' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/ExtensionReference.php',
318
+ 'WPML\\Core\\Twig_Node_Expression_Filter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Filter.php',
319
+ 'WPML\\Core\\Twig_Node_Expression_Filter_Default' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Filter/Default.php',
320
+ 'WPML\\Core\\Twig_Node_Expression_Function' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Function.php',
321
+ 'WPML\\Core\\Twig_Node_Expression_GetAttr' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/GetAttr.php',
322
+ 'WPML\\Core\\Twig_Node_Expression_MethodCall' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/MethodCall.php',
323
+ 'WPML\\Core\\Twig_Node_Expression_Name' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Name.php',
324
+ 'WPML\\Core\\Twig_Node_Expression_NullCoalesce' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/NullCoalesce.php',
325
+ 'WPML\\Core\\Twig_Node_Expression_Parent' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Parent.php',
326
+ 'WPML\\Core\\Twig_Node_Expression_TempName' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/TempName.php',
327
+ 'WPML\\Core\\Twig_Node_Expression_Test' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test.php',
328
+ 'WPML\\Core\\Twig_Node_Expression_Test_Constant' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Constant.php',
329
+ 'WPML\\Core\\Twig_Node_Expression_Test_Defined' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Defined.php',
330
+ 'WPML\\Core\\Twig_Node_Expression_Test_Divisibleby' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Divisibleby.php',
331
+ 'WPML\\Core\\Twig_Node_Expression_Test_Even' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Even.php',
332
+ 'WPML\\Core\\Twig_Node_Expression_Test_Null' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Null.php',
333
+ 'WPML\\Core\\Twig_Node_Expression_Test_Odd' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Odd.php',
334
+ 'WPML\\Core\\Twig_Node_Expression_Test_Sameas' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Sameas.php',
335
+ 'WPML\\Core\\Twig_Node_Expression_Unary' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary.php',
336
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Neg' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Neg.php',
337
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Not' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Not.php',
338
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Pos' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Pos.php',
339
+ 'WPML\\Core\\Twig_Node_Flush' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Flush.php',
340
+ 'WPML\\Core\\Twig_Node_For' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/For.php',
341
+ 'WPML\\Core\\Twig_Node_ForLoop' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/ForLoop.php',
342
+ 'WPML\\Core\\Twig_Node_If' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/If.php',
343
+ 'WPML\\Core\\Twig_Node_Import' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Import.php',
344
+ 'WPML\\Core\\Twig_Node_Include' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Include.php',
345
+ 'WPML\\Core\\Twig_Node_Macro' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Macro.php',
346
+ 'WPML\\Core\\Twig_Node_Module' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Module.php',
347
+ 'WPML\\Core\\Twig_Node_Print' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Print.php',
348
+ 'WPML\\Core\\Twig_Node_Sandbox' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Sandbox.php',
349
+ 'WPML\\Core\\Twig_Node_SandboxedPrint' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/SandboxedPrint.php',
350
+ 'WPML\\Core\\Twig_Node_Set' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Set.php',
351
+ 'WPML\\Core\\Twig_Node_SetTemp' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/SetTemp.php',
352
+ 'WPML\\Core\\Twig_Node_Spaceless' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Spaceless.php',
353
+ 'WPML\\Core\\Twig_Node_Text' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Text.php',
354
+ 'WPML\\Core\\Twig_Node_With' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/With.php',
355
+ 'WPML\\Core\\Twig_Parser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Parser.php',
356
+ 'WPML\\Core\\Twig_ParserInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ParserInterface.php',
357
+ 'WPML\\Core\\Twig_Profiler_Dumper_Base' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Base.php',
358
+ 'WPML\\Core\\Twig_Profiler_Dumper_Blackfire' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Blackfire.php',
359
+ 'WPML\\Core\\Twig_Profiler_Dumper_Html' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Html.php',
360
+ 'WPML\\Core\\Twig_Profiler_Dumper_Text' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Text.php',
361
+ 'WPML\\Core\\Twig_Profiler_NodeVisitor_Profiler' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php',
362
+ 'WPML\\Core\\Twig_Profiler_Node_EnterProfile' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Node/EnterProfile.php',
363
+ 'WPML\\Core\\Twig_Profiler_Node_LeaveProfile' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Node/LeaveProfile.php',
364
+ 'WPML\\Core\\Twig_Profiler_Profile' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Profile.php',
365
+ 'WPML\\Core\\Twig_RuntimeLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/RuntimeLoaderInterface.php',
366
+ 'WPML\\Core\\Twig_Sandbox_SecurityError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityError.php',
367
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedFilterError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php',
368
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedFunctionError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php',
369
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedMethodError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php',
370
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedPropertyError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php',
371
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedTagError' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php',
372
+ 'WPML\\Core\\Twig_Sandbox_SecurityPolicy' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityPolicy.php',
373
+ 'WPML\\Core\\Twig_Sandbox_SecurityPolicyInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php',
374
+ 'WPML\\Core\\Twig_SimpleFilter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleFilter.php',
375
+ 'WPML\\Core\\Twig_SimpleFunction' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleFunction.php',
376
+ 'WPML\\Core\\Twig_SimpleTest' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleTest.php',
377
+ 'WPML\\Core\\Twig_Source' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Source.php',
378
+ 'WPML\\Core\\Twig_SourceContextLoaderInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SourceContextLoaderInterface.php',
379
+ 'WPML\\Core\\Twig_Template' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Template.php',
380
+ 'WPML\\Core\\Twig_TemplateInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TemplateInterface.php',
381
+ 'WPML\\Core\\Twig_TemplateWrapper' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TemplateWrapper.php',
382
+ 'WPML\\Core\\Twig_Test' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test.php',
383
+ 'WPML\\Core\\Twig_TestCallableInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TestCallableInterface.php',
384
+ 'WPML\\Core\\Twig_TestInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TestInterface.php',
385
+ 'WPML\\Core\\Twig_Test_Function' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Function.php',
386
+ 'WPML\\Core\\Twig_Test_IntegrationTestCase' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/IntegrationTestCase.php',
387
+ 'WPML\\Core\\Twig_Test_Method' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Method.php',
388
+ 'WPML\\Core\\Twig_Test_Node' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Node.php',
389
+ 'WPML\\Core\\Twig_Test_NodeTestCase' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/NodeTestCase.php',
390
+ 'WPML\\Core\\Twig_Token' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Token.php',
391
+ 'WPML\\Core\\Twig_TokenParser' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser.php',
392
+ 'WPML\\Core\\Twig_TokenParserBroker' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserBroker.php',
393
+ 'WPML\\Core\\Twig_TokenParserBrokerInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserBrokerInterface.php',
394
+ 'WPML\\Core\\Twig_TokenParserInterface' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserInterface.php',
395
+ 'WPML\\Core\\Twig_TokenParser_AutoEscape' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/AutoEscape.php',
396
+ 'WPML\\Core\\Twig_TokenParser_Block' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Block.php',
397
+ 'WPML\\Core\\Twig_TokenParser_Deprecated' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Deprecated.php',
398
+ 'WPML\\Core\\Twig_TokenParser_Do' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Do.php',
399
+ 'WPML\\Core\\Twig_TokenParser_Embed' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Embed.php',
400
+ 'WPML\\Core\\Twig_TokenParser_Extends' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Extends.php',
401
+ 'WPML\\Core\\Twig_TokenParser_Filter' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Filter.php',
402
+ 'WPML\\Core\\Twig_TokenParser_Flush' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Flush.php',
403
+ 'WPML\\Core\\Twig_TokenParser_For' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/For.php',
404
+ 'WPML\\Core\\Twig_TokenParser_From' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/From.php',
405
+ 'WPML\\Core\\Twig_TokenParser_If' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/If.php',
406
+ 'WPML\\Core\\Twig_TokenParser_Import' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Import.php',
407
+ 'WPML\\Core\\Twig_TokenParser_Include' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Include.php',
408
+ 'WPML\\Core\\Twig_TokenParser_Macro' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Macro.php',
409
+ 'WPML\\Core\\Twig_TokenParser_Sandbox' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Sandbox.php',
410
+ 'WPML\\Core\\Twig_TokenParser_Set' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Set.php',
411
+ 'WPML\\Core\\Twig_TokenParser_Spaceless' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Spaceless.php',
412
+ 'WPML\\Core\\Twig_TokenParser_Use' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Use.php',
413
+ 'WPML\\Core\\Twig_TokenParser_With' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/With.php',
414
+ 'WPML\\Core\\Twig_TokenStream' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenStream.php',
415
+ 'WPML\\Core\\Twig_Util_DeprecationCollector' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Util/DeprecationCollector.php',
416
+ 'WPML\\Core\\Twig_Util_TemplateDirIterator' => $vendorDir . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Util/TemplateDirIterator.php',
417
+ 'WPML\\DocPage' => $vendorDir . '/wpml/core-api/core/DocPage.php',
418
+ 'WPML\\Element\\API\\Entity\\LanguageMapping' => $vendorDir . '/wpml/core-api/core/Entity/LanguageMapping.php',
419
+ 'WPML\\Element\\API\\IfOriginalPost' => $vendorDir . '/wpml/core-api/core/IfOriginalPost.php',
420
+ 'WPML\\Element\\API\\Languages' => $vendorDir . '/wpml/core-api/core/Languages.php',
421
+ 'WPML\\Element\\API\\Post' => $vendorDir . '/wpml/core-api/core/Post.php',
422
+ 'WPML\\Element\\API\\PostTranslations' => $vendorDir . '/wpml/core-api/core/PostTranslations.php',
423
+ 'WPML\\Element\\API\\Translations' => $vendorDir . '/wpml/core-api/core/Translations.php',
424
+ 'WPML\\Element\\API\\TranslationsRepository' => $vendorDir . '/wpml/core-api/core/TranslationsRepository.php',
425
+ 'WPML\\FP\\Applicative' => $vendorDir . '/wpml/fp/core/Functor/Applicative.php',
426
+ 'WPML\\FP\\Cast' => $vendorDir . '/wpml/fp/core/Cast.php',
427
+ 'WPML\\FP\\ConstApplicative' => $vendorDir . '/wpml/fp/core/Functor/ConstApplicative.php',
428
+ 'WPML\\FP\\Curryable' => $vendorDir . '/wpml/fp/core/traits/Curryable.php',
429
+ 'WPML\\FP\\Debug' => $vendorDir . '/wpml/fp/core/Debug.php',
430
+ 'WPML\\FP\\Either' => $vendorDir . '/wpml/fp/core/Either.php',
431
+ 'WPML\\FP\\FP' => $vendorDir . '/wpml/fp/core/FP.php',
432
+ 'WPML\\FP\\Fns' => $vendorDir . '/wpml/fp/core/Fns.php',
433
+ 'WPML\\FP\\Functor\\ConstFunctor' => $vendorDir . '/wpml/fp/core/Functor/ConstFunctor.php',
434
+ 'WPML\\FP\\Functor\\Functor' => $vendorDir . '/wpml/fp/core/Functor/Functor.php',
435
+ 'WPML\\FP\\Functor\\IdentityFunctor' => $vendorDir . '/wpml/fp/core/Functor/IdentityFunctor.php',
436
+ 'WPML\\FP\\Functor\\Pointed' => $vendorDir . '/wpml/fp/core/Functor/Pointed.php',
437
+ 'WPML\\FP\\Json' => $vendorDir . '/wpml/fp/core/Json.php',
438
+ 'WPML\\FP\\Just' => $vendorDir . '/wpml/fp/core/Maybe.php',
439
+ 'WPML\\FP\\Left' => $vendorDir . '/wpml/fp/core/Either.php',
440
+ 'WPML\\FP\\Logic' => $vendorDir . '/wpml/fp/core/Logic.php',
441
+ 'WPML\\FP\\Lst' => $vendorDir . '/wpml/fp/core/Lst.php',
442
+ 'WPML\\FP\\Math' => $vendorDir . '/wpml/fp/core/Math.php',
443
+ 'WPML\\FP\\Maybe' => $vendorDir . '/wpml/fp/core/Maybe.php',
444
+ 'WPML\\FP\\Nothing' => $vendorDir . '/wpml/fp/core/Maybe.php',
445
+ 'WPML\\FP\\Obj' => $vendorDir . '/wpml/fp/core/Obj.php',
446
+ 'WPML\\FP\\Promise' => $vendorDir . '/wpml/fp/core/Promise.php',
447
+ 'WPML\\FP\\Relation' => $vendorDir . '/wpml/fp/core/Relation.php',
448
+ 'WPML\\FP\\Right' => $vendorDir . '/wpml/fp/core/Either.php',
449
+ 'WPML\\FP\\Str' => $vendorDir . '/wpml/fp/core/Strings.php',
450
+ 'WPML\\FP\\System\\System' => $vendorDir . '/wpml/fp/core/SystemClass.php',
451
+ 'WPML\\FP\\System\\_Filter' => $vendorDir . '/wpml/fp/core/Filter.php',
452
+ 'WPML\\FP\\System\\_Validator' => $vendorDir . '/wpml/fp/core/Validator.php',
453
+ 'WPML\\FP\\Undefined' => $vendorDir . '/wpml/fp/core/Undefined.php',
454
+ 'WPML\\FP\\Wrapper' => $vendorDir . '/wpml/fp/core/Wrapper.php',
455
+ 'WPML\\FP\\_Invoker' => $vendorDir . '/wpml/fp/core/Invoker.php',
456
+ 'WPML\\LIB\\WP\\App\\Resources' => $vendorDir . '/wpml/wp/classes/Resources.php',
457
+ 'WPML\\LIB\\WP\\Attachment' => $vendorDir . '/wpml/wp/classes/Attachment.php',
458
+ 'WPML\\LIB\\WP\\Cache' => $vendorDir . '/wpml/wp/classes/Cache.php',
459
+ 'WPML\\LIB\\WP\\Gutenberg' => $vendorDir . '/wpml/wp/classes/Gutenberg.php',
460
+ 'WPML\\LIB\\WP\\Hooks' => $vendorDir . '/wpml/wp/classes/Hooks.php',
461
+ 'WPML\\LIB\\WP\\Http' => $vendorDir . '/wpml/wp/classes/Http.php',
462
+ 'WPML\\LIB\\WP\\Nonce' => $vendorDir . '/wpml/wp/classes/Nonce.php',
463
+ 'WPML\\LIB\\WP\\Option' => $vendorDir . '/wpml/wp/classes/Option.php',
464
+ 'WPML\\LIB\\WP\\Post' => $vendorDir . '/wpml/wp/classes/Post.php',
465
+ 'WPML\\LIB\\WP\\PostType' => $vendorDir . '/wpml/wp/classes/PostType.php',
466
+ 'WPML\\LIB\\WP\\Roles' => $vendorDir . '/wpml/wp/classes/Roles.php',
467
+ 'WPML\\LIB\\WP\\Transient' => $vendorDir . '/wpml/wp/classes/Transient.php',
468
+ 'WPML\\LIB\\WP\\User' => $vendorDir . '/wpml/wp/classes/User.php',
469
+ 'WPML\\LIB\\WP\\WPDB' => $vendorDir . '/wpml/wp/classes/WPDB.php',
470
+ 'WPML\\LIB\\WP\\WordPress' => $vendorDir . '/wpml/wp/classes/WP.php',
471
+ 'WPML\\Media\\Option' => $vendorDir . '/wpml/core-api/core/media/Option.php',
472
+ 'WPML\\Notices\\DismissNotices' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/DismissNotices.php',
473
+ 'WPML\\Records\\Translations' => $vendorDir . '/wpml/core-api/core/Records/Translations.php',
474
+ 'WPML\\Settings\\PostType\\Automatic' => $vendorDir . '/wpml/core-api/core/settings/Automatic.php',
475
+ 'WPML\\Setup\\Option' => $vendorDir . '/wpml/core-api/core/setup/Option.php',
476
+ 'WPML\\Timer' => $vendorDir . '/wpml/core-api/core/Timer.php',
477
+ 'WPML\\UIPage' => $vendorDir . '/wpml/core-api/core/UIPage.php',
478
+ 'WPML\\Utilities\\ILock' => $vendorDir . '/wpml/core-api/core/utility/ILock.php',
479
+ 'WPML\\Utilities\\Lock' => $vendorDir . '/wpml/core-api/core/utility/Lock.php',
480
+ 'WPML\\WP\\OptionManager' => $vendorDir . '/wpml/core-api/core/OptionManager.php',
481
+ 'WPML_AJAX_Action_Validation' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-ajax-action-validation.php',
482
+ 'WPML_AJAX_Base_Factory' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-ajax-action-base-factory.php',
483
+ 'WPML_Action_Filter_Loader' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-action-filter-loader.php',
484
+ 'WPML_Block_Editor_Helper' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/block-editor/class-wpml-block-editor-helper.php',
485
+ 'WPML_Cookie' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/cookie/class-wpml-cookie.php',
486
+ 'WPML_Core_Privacy_Content' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-core-privacy-content.php',
487
+ 'WPML_Current_Screen_Loader_Factory' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-current-screen-loader-factory.php',
488
+ 'WPML_File' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/class-wpml-file.php',
489
+ 'WPML_Notice' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice.php',
490
+ 'WPML_Notice_Action' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice-action.php',
491
+ 'WPML_Notice_Render' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice-render.php',
492
+ 'WPML_Notice_Show_On_Dashboard_And_WPML_Pages' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/pages/class-wpml-notice-show-on-dashboard-and-wpml-pages.php',
493
+ 'WPML_Notices' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notices.php',
494
+ 'WPML_PHP_Functions' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/wpml-php-functions.php',
495
+ 'WPML_Privacy_Content' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-privacy-content.php',
496
+ 'WPML_Privacy_Content_Factory' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-privacy-content-factory.php',
497
+ 'WPML_Templates_Factory' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/templating/class-wpml-templates-factory.php',
498
+ 'WPML_Twig_Template' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/templates/class-wpml-twig-template.php',
499
+ 'WPML_Twig_Template_Loader' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/templates/wpml-twig-template-loader.php',
500
+ 'WPML_Twig_WP_Plugin_Extension' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/twig-extensions/wpml-twig-wp-plugin-extension.php',
501
+ 'WPML_WP_API' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-api.php',
502
+ 'WPML_WP_Cache' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/utilities/class-wpml-wp-cache.php',
503
+ 'WPML_WP_Post_Type' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/wpml-wp-post-type.php',
504
+ 'WPML_WP_Roles' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-roles.php',
505
+ 'WPML_WP_Taxonomy' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-taxonomy.php',
506
+ );
addons/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ '5f5b8f7c1db2e892006e8805f0ed573c' => $vendorDir . '/wpml/collect/src/Illuminate/Support/helpers.php',
10
+ '914c4a8cb7e06f7d6e1ddf6997c1785f' => $vendorDir . '/wpml/fp/core/functions.php',
11
+ '348332d63f916da7598941d18c24311d' => $vendorDir . '/wpml/fp/core/strings_functions.php',
12
+ '766b758ee51e52c53cf3312a1dba9e34' => $vendorDir . '/wpml/fp/core/system.php',
13
+ '4f861be014c38ae526415a9a3c62913a' => $vendorDir . '/wpml/wpml-dependencies/lib/classes/container/functions.php',
14
+ );
addons/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
addons/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'WPML\\Collect\\' => array($vendorDir . '/wpml/collect/src/Illuminate'),
10
+ 'WPML\\Auryn\\' => array($vendorDir . '/otgs/auryn/lib'),
11
+ );
addons/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit4821ed1a7ed1caf1298338b695908544
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ spl_autoload_register(array('ComposerAutoloaderInit4821ed1a7ed1caf1298338b695908544', 'loadClassLoader'), true, true);
26
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit4821ed1a7ed1caf1298338b695908544', 'loadClassLoader'));
28
+
29
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
+ if ($useStaticLoader) {
31
+ require_once __DIR__ . '/autoload_static.php';
32
+
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit4821ed1a7ed1caf1298338b695908544::getInitializer($loader));
34
+ } else {
35
+ $map = require __DIR__ . '/autoload_namespaces.php';
36
+ foreach ($map as $namespace => $path) {
37
+ $loader->set($namespace, $path);
38
+ }
39
+
40
+ $map = require __DIR__ . '/autoload_psr4.php';
41
+ foreach ($map as $namespace => $path) {
42
+ $loader->setPsr4($namespace, $path);
43
+ }
44
+
45
+ $classMap = require __DIR__ . '/autoload_classmap.php';
46
+ if ($classMap) {
47
+ $loader->addClassMap($classMap);
48
+ }
49
+ }
50
+
51
+ $loader->register(true);
52
+
53
+ if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInit4821ed1a7ed1caf1298338b695908544::$files;
55
+ } else {
56
+ $includeFiles = require __DIR__ . '/autoload_files.php';
57
+ }
58
+ foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequire4821ed1a7ed1caf1298338b695908544($fileIdentifier, $file);
60
+ }
61
+
62
+ return $loader;
63
+ }
64
+ }
65
+
66
+ function composerRequire4821ed1a7ed1caf1298338b695908544($fileIdentifier, $file)
67
+ {
68
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
+ require $file;
70
+
71
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
72
+ }
73
+ }
addons/vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit4821ed1a7ed1caf1298338b695908544
8
+ {
9
+ public static $files = array (
10
+ '5f5b8f7c1db2e892006e8805f0ed573c' => __DIR__ . '/..' . '/wpml/collect/src/Illuminate/Support/helpers.php',
11
+ '914c4a8cb7e06f7d6e1ddf6997c1785f' => __DIR__ . '/..' . '/wpml/fp/core/functions.php',
12
+ '348332d63f916da7598941d18c24311d' => __DIR__ . '/..' . '/wpml/fp/core/strings_functions.php',
13
+ '766b758ee51e52c53cf3312a1dba9e34' => __DIR__ . '/..' . '/wpml/fp/core/system.php',
14
+ '4f861be014c38ae526415a9a3c62913a' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/container/functions.php',
15
+ );
16
+
17
+ public static $prefixLengthsPsr4 = array (
18
+ 'W' =>
19
+ array (
20
+ 'WPML\\Collect\\' => 13,
21
+ 'WPML\\Auryn\\' => 11,
22
+ ),
23
+ );
24
+
25
+ public static $prefixDirsPsr4 = array (
26
+ 'WPML\\Collect\\' =>
27
+ array (
28
+ 0 => __DIR__ . '/..' . '/wpml/collect/src/Illuminate',
29
+ ),
30
+ 'WPML\\Auryn\\' =>
31
+ array (
32
+ 0 => __DIR__ . '/..' . '/otgs/auryn/lib',
33
+ ),
34
+ );
35
+
36
+ public static $classMap = array (
37
+ 'ICL_AdminNotifier' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/inc/icl-admin-notifier.php',
38
+ 'IWPML_AJAX_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-ajax-action.php',
39
+ 'IWPML_AJAX_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-ajax-action-loader.php',
40
+ 'IWPML_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-action.php',
41
+ 'IWPML_Action_Loader_Factory' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-action-loader-factory.php',
42
+ 'IWPML_Backend_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-backend-action.php',
43
+ 'IWPML_Backend_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-backend-action-loader.php',
44
+ 'IWPML_CLI_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-cli-action.php',
45
+ 'IWPML_CLI_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-cli-action-loader.php',
46
+ 'IWPML_Current_Language' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/languages/interface-iwpml-current-language.php',
47
+ 'IWPML_DIC_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-dic-action.php',
48
+ 'IWPML_Deferred_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-deferred-action-loader.php',
49
+ 'IWPML_Frontend_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-frontend-action.php',
50
+ 'IWPML_Frontend_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-frontend-action-loader.php',
51
+ 'IWPML_REST_Action' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-rest-action.php',
52
+ 'IWPML_REST_Action_Loader' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/actions/interface-iwpml-rest-action-loader.php',
53
+ 'IWPML_Template_Service' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/templates/interface-iwpml-template-service.php',
54
+ 'IWPML_WP_Element_Type' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/iwpml-wp-element-type.php',
55
+ 'OTGS_Assets_Handles' => __DIR__ . '/..' . '/otgs/ui/src/php/OTGS_Assets_Handles.php',
56
+ 'OTGS_Assets_Store' => __DIR__ . '/..' . '/otgs/ui/src/php/OTGS_Assets_Store.php',
57
+ 'OTGS_UI_Assets' => __DIR__ . '/..' . '/otgs/ui/src/php/OTGS_UI_Assets.php',
58
+ 'OTGS_UI_Loader' => __DIR__ . '/..' . '/otgs/ui/src/php/OTGS_UI_Loader.php',
59
+ 'WPML\\API\\PostTypes' => __DIR__ . '/..' . '/wpml/core-api/core/PostTypes.php',
60
+ 'WPML\\API\\Settings' => __DIR__ . '/..' . '/wpml/core-api/core/Settings.php',
61
+ 'WPML\\API\\Version' => __DIR__ . '/..' . '/wpml/core-api/core/Version.php',
62
+ 'WPML\\Action\\Type' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-action-type.php',
63
+ 'WPML\\Ajax\\IHandler' => __DIR__ . '/..' . '/wpml/core-api/core/interfaces/ajax/Handler.php',
64
+ 'WPML\\Container\\Config' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/container/class-config.php',
65
+ 'WPML\\Container\\Container' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/container/class-wpml-container.php',
66
+ 'WPML\\Core\\BackgroundTask' => __DIR__ . '/..' . '/wpml/core-api/core/utility/BackgroundTask.php',
67
+ 'WPML\\Core\\ISitePress' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/ISitePress.php',
68
+ 'WPML\\Core\\Twig\\Cache\\CacheInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/CacheInterface.php',
69
+ 'WPML\\Core\\Twig\\Cache\\FilesystemCache' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/FilesystemCache.php',
70
+ 'WPML\\Core\\Twig\\Cache\\NullCache' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Cache/NullCache.php',
71
+ 'WPML\\Core\\Twig\\Compiler' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Compiler.php',
72
+ 'WPML\\Core\\Twig\\Environment' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Environment.php',
73
+ 'WPML\\Core\\Twig\\Error\\Error' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/Error.php',
74
+ 'WPML\\Core\\Twig\\Error\\LoaderError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/LoaderError.php',
75
+ 'WPML\\Core\\Twig\\Error\\RuntimeError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/RuntimeError.php',
76
+ 'WPML\\Core\\Twig\\Error\\SyntaxError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Error/SyntaxError.php',
77
+ 'WPML\\Core\\Twig\\ExpressionParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/ExpressionParser.php',
78
+ 'WPML\\Core\\Twig\\Extension\\AbstractExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/AbstractExtension.php',
79
+ 'WPML\\Core\\Twig\\Extension\\CoreExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/CoreExtension.php',
80
+ 'WPML\\Core\\Twig\\Extension\\DebugExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/DebugExtension.php',
81
+ 'WPML\\Core\\Twig\\Extension\\EscaperExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/EscaperExtension.php',
82
+ 'WPML\\Core\\Twig\\Extension\\ExtensionInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/ExtensionInterface.php',
83
+ 'WPML\\Core\\Twig\\Extension\\GlobalsInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/GlobalsInterface.php',
84
+ 'WPML\\Core\\Twig\\Extension\\InitRuntimeInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/InitRuntimeInterface.php',
85
+ 'WPML\\Core\\Twig\\Extension\\OptimizerExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/OptimizerExtension.php',
86
+ 'WPML\\Core\\Twig\\Extension\\ProfilerExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/ProfilerExtension.php',
87
+ 'WPML\\Core\\Twig\\Extension\\RuntimeExtensionInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/RuntimeExtensionInterface.php',
88
+ 'WPML\\Core\\Twig\\Extension\\SandboxExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/SandboxExtension.php',
89
+ 'WPML\\Core\\Twig\\Extension\\StagingExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/StagingExtension.php',
90
+ 'WPML\\Core\\Twig\\Extension\\StringLoaderExtension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Extension/StringLoaderExtension.php',
91
+ 'WPML\\Core\\Twig\\FileExtensionEscapingStrategy' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/FileExtensionEscapingStrategy.php',
92
+ 'WPML\\Core\\Twig\\Lexer' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Lexer.php',
93
+ 'WPML\\Core\\Twig\\Loader\\ArrayLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ArrayLoader.php',
94
+ 'WPML\\Core\\Twig\\Loader\\ChainLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ChainLoader.php',
95
+ 'WPML\\Core\\Twig\\Loader\\ExistsLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/ExistsLoaderInterface.php',
96
+ 'WPML\\Core\\Twig\\Loader\\FilesystemLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/FilesystemLoader.php',
97
+ 'WPML\\Core\\Twig\\Loader\\LoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/LoaderInterface.php',
98
+ 'WPML\\Core\\Twig\\Loader\\SourceContextLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Loader/SourceContextLoaderInterface.php',
99
+ 'WPML\\Core\\Twig\\Markup' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Markup.php',
100
+ 'WPML\\Core\\Twig\\NodeTraverser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeTraverser.php',
101
+ 'WPML\\Core\\Twig\\NodeVisitor\\AbstractNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/AbstractNodeVisitor.php',
102
+ 'WPML\\Core\\Twig\\NodeVisitor\\EscaperNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/EscaperNodeVisitor.php',
103
+ 'WPML\\Core\\Twig\\NodeVisitor\\NodeVisitorInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/NodeVisitorInterface.php',
104
+ 'WPML\\Core\\Twig\\NodeVisitor\\OptimizerNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/OptimizerNodeVisitor.php',
105
+ 'WPML\\Core\\Twig\\NodeVisitor\\SafeAnalysisNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php',
106
+ 'WPML\\Core\\Twig\\NodeVisitor\\SandboxNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/NodeVisitor/SandboxNodeVisitor.php',
107
+ 'WPML\\Core\\Twig\\Node\\AutoEscapeNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/AutoEscapeNode.php',
108
+ 'WPML\\Core\\Twig\\Node\\BlockNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BlockNode.php',
109
+ 'WPML\\Core\\Twig\\Node\\BlockReferenceNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BlockReferenceNode.php',
110
+ 'WPML\\Core\\Twig\\Node\\BodyNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/BodyNode.php',
111
+ 'WPML\\Core\\Twig\\Node\\CheckSecurityNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/CheckSecurityNode.php',
112
+ 'WPML\\Core\\Twig\\Node\\CheckToStringNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/CheckToStringNode.php',
113
+ 'WPML\\Core\\Twig\\Node\\DeprecatedNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/DeprecatedNode.php',
114
+ 'WPML\\Core\\Twig\\Node\\DoNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/DoNode.php',
115
+ 'WPML\\Core\\Twig\\Node\\EmbedNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/EmbedNode.php',
116
+ 'WPML\\Core\\Twig\\Node\\Expression\\AbstractExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/AbstractExpression.php',
117
+ 'WPML\\Core\\Twig\\Node\\Expression\\ArrayExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ArrayExpression.php',
118
+ 'WPML\\Core\\Twig\\Node\\Expression\\ArrowFunctionExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ArrowFunctionExpression.php',
119
+ 'WPML\\Core\\Twig\\Node\\Expression\\AssignNameExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/AssignNameExpression.php',
120
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AbstractBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AbstractBinary.php',
121
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AddBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AddBinary.php',
122
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\AndBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/AndBinary.php',
123
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseAndBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseAndBinary.php',
124
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseOrBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseOrBinary.php',
125
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\BitwiseXorBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/BitwiseXorBinary.php',
126
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\ConcatBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/ConcatBinary.php',
127
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\DivBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/DivBinary.php',
128
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\EndsWithBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/EndsWithBinary.php',
129
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\EqualBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/EqualBinary.php',
130
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\FloorDivBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/FloorDivBinary.php',
131
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\GreaterBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/GreaterBinary.php',
132
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\GreaterEqualBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/GreaterEqualBinary.php',
133
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\InBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/InBinary.php',
134
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\LessBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/LessBinary.php',
135
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\LessEqualBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/LessEqualBinary.php',
136
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\MatchesBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/MatchesBinary.php',
137
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\ModBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/ModBinary.php',
138
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\MulBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/MulBinary.php',
139
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\NotEqualBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/NotEqualBinary.php',
140
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\NotInBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/NotInBinary.php',
141
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\OrBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/OrBinary.php',
142
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\PowerBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/PowerBinary.php',
143
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\RangeBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/RangeBinary.php',
144
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\StartsWithBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/StartsWithBinary.php',
145
+ 'WPML\\Core\\Twig\\Node\\Expression\\Binary\\SubBinary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Binary/SubBinary.php',
146
+ 'WPML\\Core\\Twig\\Node\\Expression\\BlockReferenceExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/BlockReferenceExpression.php',
147
+ 'WPML\\Core\\Twig\\Node\\Expression\\CallExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/CallExpression.php',
148
+ 'WPML\\Core\\Twig\\Node\\Expression\\ConditionalExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ConditionalExpression.php',
149
+ 'WPML\\Core\\Twig\\Node\\Expression\\ConstantExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ConstantExpression.php',
150
+ 'WPML\\Core\\Twig\\Node\\Expression\\FilterExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/FilterExpression.php',
151
+ 'WPML\\Core\\Twig\\Node\\Expression\\Filter\\DefaultFilter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Filter/DefaultFilter.php',
152
+ 'WPML\\Core\\Twig\\Node\\Expression\\FunctionExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/FunctionExpression.php',
153
+ 'WPML\\Core\\Twig\\Node\\Expression\\GetAttrExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/GetAttrExpression.php',
154
+ 'WPML\\Core\\Twig\\Node\\Expression\\InlinePrint' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/InlinePrint.php',
155
+ 'WPML\\Core\\Twig\\Node\\Expression\\MethodCallExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/MethodCallExpression.php',
156
+ 'WPML\\Core\\Twig\\Node\\Expression\\NameExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/NameExpression.php',
157
+ 'WPML\\Core\\Twig\\Node\\Expression\\NullCoalesceExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/NullCoalesceExpression.php',
158
+ 'WPML\\Core\\Twig\\Node\\Expression\\ParentExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/ParentExpression.php',
159
+ 'WPML\\Core\\Twig\\Node\\Expression\\TempNameExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/TempNameExpression.php',
160
+ 'WPML\\Core\\Twig\\Node\\Expression\\TestExpression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/TestExpression.php',
161
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\ConstantTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/ConstantTest.php',
162
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\DefinedTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/DefinedTest.php',
163
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\DivisiblebyTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/DivisiblebyTest.php',
164
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\EvenTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/EvenTest.php',
165
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\NullTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/NullTest.php',
166
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\OddTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/OddTest.php',
167
+ 'WPML\\Core\\Twig\\Node\\Expression\\Test\\SameasTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Test/SameasTest.php',
168
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\AbstractUnary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/AbstractUnary.php',
169
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\NegUnary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/NegUnary.php',
170
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\NotUnary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/NotUnary.php',
171
+ 'WPML\\Core\\Twig\\Node\\Expression\\Unary\\PosUnary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Expression/Unary/PosUnary.php',
172
+ 'WPML\\Core\\Twig\\Node\\FlushNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/FlushNode.php',
173
+ 'WPML\\Core\\Twig\\Node\\ForLoopNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ForLoopNode.php',
174
+ 'WPML\\Core\\Twig\\Node\\ForNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ForNode.php',
175
+ 'WPML\\Core\\Twig\\Node\\IfNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/IfNode.php',
176
+ 'WPML\\Core\\Twig\\Node\\ImportNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ImportNode.php',
177
+ 'WPML\\Core\\Twig\\Node\\IncludeNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/IncludeNode.php',
178
+ 'WPML\\Core\\Twig\\Node\\MacroNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/MacroNode.php',
179
+ 'WPML\\Core\\Twig\\Node\\ModuleNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/ModuleNode.php',
180
+ 'WPML\\Core\\Twig\\Node\\Node' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/Node.php',
181
+ 'WPML\\Core\\Twig\\Node\\NodeCaptureInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/NodeCaptureInterface.php',
182
+ 'WPML\\Core\\Twig\\Node\\NodeOutputInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/NodeOutputInterface.php',
183
+ 'WPML\\Core\\Twig\\Node\\PrintNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/PrintNode.php',
184
+ 'WPML\\Core\\Twig\\Node\\SandboxNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SandboxNode.php',
185
+ 'WPML\\Core\\Twig\\Node\\SandboxedPrintNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SandboxedPrintNode.php',
186
+ 'WPML\\Core\\Twig\\Node\\SetNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SetNode.php',
187
+ 'WPML\\Core\\Twig\\Node\\SetTempNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SetTempNode.php',
188
+ 'WPML\\Core\\Twig\\Node\\SpacelessNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/SpacelessNode.php',
189
+ 'WPML\\Core\\Twig\\Node\\TextNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/TextNode.php',
190
+ 'WPML\\Core\\Twig\\Node\\WithNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Node/WithNode.php',
191
+ 'WPML\\Core\\Twig\\Parser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Parser.php',
192
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\BaseDumper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/BaseDumper.php',
193
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\BlackfireDumper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/BlackfireDumper.php',
194
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\HtmlDumper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/HtmlDumper.php',
195
+ 'WPML\\Core\\Twig\\Profiler\\Dumper\\TextDumper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Dumper/TextDumper.php',
196
+ 'WPML\\Core\\Twig\\Profiler\\NodeVisitor\\ProfilerNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php',
197
+ 'WPML\\Core\\Twig\\Profiler\\Node\\EnterProfileNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Node/EnterProfileNode.php',
198
+ 'WPML\\Core\\Twig\\Profiler\\Node\\LeaveProfileNode' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Node/LeaveProfileNode.php',
199
+ 'WPML\\Core\\Twig\\Profiler\\Profile' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Profiler/Profile.php',
200
+ 'WPML\\Core\\Twig\\RuntimeLoader\\ContainerRuntimeLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/ContainerRuntimeLoader.php',
201
+ 'WPML\\Core\\Twig\\RuntimeLoader\\FactoryRuntimeLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/FactoryRuntimeLoader.php',
202
+ 'WPML\\Core\\Twig\\RuntimeLoader\\RuntimeLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/RuntimeLoader/RuntimeLoaderInterface.php',
203
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityError.php',
204
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedFilterError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedFilterError.php',
205
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedFunctionError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedFunctionError.php',
206
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedMethodError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedMethodError.php',
207
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedPropertyError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedPropertyError.php',
208
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityNotAllowedTagError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityNotAllowedTagError.php',
209
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityPolicy' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityPolicy.php',
210
+ 'WPML\\Core\\Twig\\Sandbox\\SecurityPolicyInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Sandbox/SecurityPolicyInterface.php',
211
+ 'WPML\\Core\\Twig\\Source' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Source.php',
212
+ 'WPML\\Core\\Twig\\Template' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Template.php',
213
+ 'WPML\\Core\\Twig\\TemplateWrapper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TemplateWrapper.php',
214
+ 'WPML\\Core\\Twig\\Test\\IntegrationTestCase' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Test/IntegrationTestCase.php',
215
+ 'WPML\\Core\\Twig\\Test\\NodeTestCase' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Test/NodeTestCase.php',
216
+ 'WPML\\Core\\Twig\\Token' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Token.php',
217
+ 'WPML\\Core\\Twig\\TokenParser\\AbstractTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/AbstractTokenParser.php',
218
+ 'WPML\\Core\\Twig\\TokenParser\\ApplyTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ApplyTokenParser.php',
219
+ 'WPML\\Core\\Twig\\TokenParser\\AutoEscapeTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/AutoEscapeTokenParser.php',
220
+ 'WPML\\Core\\Twig\\TokenParser\\BlockTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/BlockTokenParser.php',
221
+ 'WPML\\Core\\Twig\\TokenParser\\DeprecatedTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/DeprecatedTokenParser.php',
222
+ 'WPML\\Core\\Twig\\TokenParser\\DoTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/DoTokenParser.php',
223
+ 'WPML\\Core\\Twig\\TokenParser\\EmbedTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/EmbedTokenParser.php',
224
+ 'WPML\\Core\\Twig\\TokenParser\\ExtendsTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ExtendsTokenParser.php',
225
+ 'WPML\\Core\\Twig\\TokenParser\\FilterTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FilterTokenParser.php',
226
+ 'WPML\\Core\\Twig\\TokenParser\\FlushTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FlushTokenParser.php',
227
+ 'WPML\\Core\\Twig\\TokenParser\\ForTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ForTokenParser.php',
228
+ 'WPML\\Core\\Twig\\TokenParser\\FromTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/FromTokenParser.php',
229
+ 'WPML\\Core\\Twig\\TokenParser\\IfTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/IfTokenParser.php',
230
+ 'WPML\\Core\\Twig\\TokenParser\\ImportTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/ImportTokenParser.php',
231
+ 'WPML\\Core\\Twig\\TokenParser\\IncludeTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/IncludeTokenParser.php',
232
+ 'WPML\\Core\\Twig\\TokenParser\\MacroTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/MacroTokenParser.php',
233
+ 'WPML\\Core\\Twig\\TokenParser\\SandboxTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SandboxTokenParser.php',
234
+ 'WPML\\Core\\Twig\\TokenParser\\SetTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SetTokenParser.php',
235
+ 'WPML\\Core\\Twig\\TokenParser\\SpacelessTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/SpacelessTokenParser.php',
236
+ 'WPML\\Core\\Twig\\TokenParser\\TokenParserInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/TokenParserInterface.php',
237
+ 'WPML\\Core\\Twig\\TokenParser\\UseTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/UseTokenParser.php',
238
+ 'WPML\\Core\\Twig\\TokenParser\\WithTokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenParser/WithTokenParser.php',
239
+ 'WPML\\Core\\Twig\\TokenStream' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TokenStream.php',
240
+ 'WPML\\Core\\Twig\\TwigFilter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigFilter.php',
241
+ 'WPML\\Core\\Twig\\TwigFunction' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigFunction.php',
242
+ 'WPML\\Core\\Twig\\TwigTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/TwigTest.php',
243
+ 'WPML\\Core\\Twig\\Util\\DeprecationCollector' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Util/DeprecationCollector.php',
244
+ 'WPML\\Core\\Twig\\Util\\TemplateDirIterator' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/src/Util/TemplateDirIterator.php',
245
+ 'WPML\\Core\\Twig_Autoloader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Autoloader.php',
246
+ 'WPML\\Core\\Twig_BaseNodeVisitor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/BaseNodeVisitor.php',
247
+ 'WPML\\Core\\Twig_CacheInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/CacheInterface.php',
248
+ 'WPML\\Core\\Twig_Cache_Filesystem' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Cache/Filesystem.php',
249
+ 'WPML\\Core\\Twig_Cache_Null' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Cache/Null.php',
250
+ 'WPML\\Core\\Twig_Compiler' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Compiler.php',
251
+ 'WPML\\Core\\Twig_CompilerInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/CompilerInterface.php',
252
+ 'WPML\\Core\\Twig_ContainerRuntimeLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ContainerRuntimeLoader.php',
253
+ 'WPML\\Core\\Twig_Environment' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Environment.php',
254
+ 'WPML\\Core\\Twig_Error' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error.php',
255
+ 'WPML\\Core\\Twig_Error_Loader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Loader.php',
256
+ 'WPML\\Core\\Twig_Error_Runtime' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Runtime.php',
257
+ 'WPML\\Core\\Twig_Error_Syntax' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Error/Syntax.php',
258
+ 'WPML\\Core\\Twig_ExistsLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExistsLoaderInterface.php',
259
+ 'WPML\\Core\\Twig_ExpressionParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExpressionParser.php',
260
+ 'WPML\\Core\\Twig_Extension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension.php',
261
+ 'WPML\\Core\\Twig_ExtensionInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ExtensionInterface.php',
262
+ 'WPML\\Core\\Twig_Extension_Core' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Core.php',
263
+ 'WPML\\Core\\Twig_Extension_Debug' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Debug.php',
264
+ 'WPML\\Core\\Twig_Extension_Escaper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Escaper.php',
265
+ 'WPML\\Core\\Twig_Extension_GlobalsInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/GlobalsInterface.php',
266
+ 'WPML\\Core\\Twig_Extension_InitRuntimeInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/InitRuntimeInterface.php',
267
+ 'WPML\\Core\\Twig_Extension_Optimizer' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Optimizer.php',
268
+ 'WPML\\Core\\Twig_Extension_Profiler' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Profiler.php',
269
+ 'WPML\\Core\\Twig_Extension_Sandbox' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Sandbox.php',
270
+ 'WPML\\Core\\Twig_Extension_Staging' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/Staging.php',
271
+ 'WPML\\Core\\Twig_Extension_StringLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Extension/StringLoader.php',
272
+ 'WPML\\Core\\Twig_FactoryRuntimeLoader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FactoryRuntimeLoader.php',
273
+ 'WPML\\Core\\Twig_FileExtensionEscapingStrategy' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FileExtensionEscapingStrategy.php',
274
+ 'WPML\\Core\\Twig_Filter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter.php',
275
+ 'WPML\\Core\\Twig_FilterCallableInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FilterCallableInterface.php',
276
+ 'WPML\\Core\\Twig_FilterInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FilterInterface.php',
277
+ 'WPML\\Core\\Twig_Filter_Function' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Function.php',
278
+ 'WPML\\Core\\Twig_Filter_Method' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Method.php',
279
+ 'WPML\\Core\\Twig_Filter_Node' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Filter/Node.php',
280
+ 'WPML\\Core\\Twig_Function' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function.php',
281
+ 'WPML\\Core\\Twig_FunctionCallableInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FunctionCallableInterface.php',
282
+ 'WPML\\Core\\Twig_FunctionInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/FunctionInterface.php',
283
+ 'WPML\\Core\\Twig_Function_Function' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Function.php',
284
+ 'WPML\\Core\\Twig_Function_Method' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Method.php',
285
+ 'WPML\\Core\\Twig_Function_Node' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Function/Node.php',
286
+ 'WPML\\Core\\Twig_Lexer' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Lexer.php',
287
+ 'WPML\\Core\\Twig_LexerInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/LexerInterface.php',
288
+ 'WPML\\Core\\Twig_LoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/LoaderInterface.php',
289
+ 'WPML\\Core\\Twig_Loader_Array' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Array.php',
290
+ 'WPML\\Core\\Twig_Loader_Chain' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Chain.php',
291
+ 'WPML\\Core\\Twig_Loader_Filesystem' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/Filesystem.php',
292
+ 'WPML\\Core\\Twig_Loader_String' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Loader/String.php',
293
+ 'WPML\\Core\\Twig_Markup' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Markup.php',
294
+ 'WPML\\Core\\Twig_Node' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node.php',
295
+ 'WPML\\Core\\Twig_NodeCaptureInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeCaptureInterface.php',
296
+ 'WPML\\Core\\Twig_NodeInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeInterface.php',
297
+ 'WPML\\Core\\Twig_NodeOutputInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeOutputInterface.php',
298
+ 'WPML\\Core\\Twig_NodeTraverser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeTraverser.php',
299
+ 'WPML\\Core\\Twig_NodeVisitorInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitorInterface.php',
300
+ 'WPML\\Core\\Twig_NodeVisitor_Escaper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Escaper.php',
301
+ 'WPML\\Core\\Twig_NodeVisitor_Optimizer' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Optimizer.php',
302
+ 'WPML\\Core\\Twig_NodeVisitor_SafeAnalysis' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/SafeAnalysis.php',
303
+ 'WPML\\Core\\Twig_NodeVisitor_Sandbox' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/NodeVisitor/Sandbox.php',
304
+ 'WPML\\Core\\Twig_Node_AutoEscape' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/AutoEscape.php',
305
+ 'WPML\\Core\\Twig_Node_Block' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Block.php',
306
+ 'WPML\\Core\\Twig_Node_BlockReference' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/BlockReference.php',
307
+ 'WPML\\Core\\Twig_Node_Body' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Body.php',
308
+ 'WPML\\Core\\Twig_Node_CheckSecurity' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/CheckSecurity.php',
309
+ 'WPML\\Core\\Twig_Node_Deprecated' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Deprecated.php',
310
+ 'WPML\\Core\\Twig_Node_Do' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Do.php',
311
+ 'WPML\\Core\\Twig_Node_Embed' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Embed.php',
312
+ 'WPML\\Core\\Twig_Node_Expression' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression.php',
313
+ 'WPML\\Core\\Twig_Node_Expression_Array' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Array.php',
314
+ 'WPML\\Core\\Twig_Node_Expression_AssignName' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/AssignName.php',
315
+ 'WPML\\Core\\Twig_Node_Expression_Binary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary.php',
316
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Add' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Add.php',
317
+ 'WPML\\Core\\Twig_Node_Expression_Binary_And' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/And.php',
318
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseAnd' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php',
319
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseOr' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php',
320
+ 'WPML\\Core\\Twig_Node_Expression_Binary_BitwiseXor' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php',
321
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Concat' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Concat.php',
322
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Div' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Div.php',
323
+ 'WPML\\Core\\Twig_Node_Expression_Binary_EndsWith' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/EndsWith.php',
324
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Equal' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Equal.php',
325
+ 'WPML\\Core\\Twig_Node_Expression_Binary_FloorDiv' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php',
326
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Greater' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Greater.php',
327
+ 'WPML\\Core\\Twig_Node_Expression_Binary_GreaterEqual' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php',
328
+ 'WPML\\Core\\Twig_Node_Expression_Binary_In' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/In.php',
329
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Less' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Less.php',
330
+ 'WPML\\Core\\Twig_Node_Expression_Binary_LessEqual' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/LessEqual.php',
331
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Matches' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Matches.php',
332
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Mod' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Mod.php',
333
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Mul' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Mul.php',
334
+ 'WPML\\Core\\Twig_Node_Expression_Binary_NotEqual' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/NotEqual.php',
335
+ 'WPML\\Core\\Twig_Node_Expression_Binary_NotIn' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/NotIn.php',
336
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Or' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Or.php',
337
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Power' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Power.php',
338
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Range' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Range.php',
339
+ 'WPML\\Core\\Twig_Node_Expression_Binary_StartsWith' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/StartsWith.php',
340
+ 'WPML\\Core\\Twig_Node_Expression_Binary_Sub' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Binary/Sub.php',
341
+ 'WPML\\Core\\Twig_Node_Expression_BlockReference' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/BlockReference.php',
342
+ 'WPML\\Core\\Twig_Node_Expression_Call' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Call.php',
343
+ 'WPML\\Core\\Twig_Node_Expression_Conditional' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Conditional.php',
344
+ 'WPML\\Core\\Twig_Node_Expression_Constant' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Constant.php',
345
+ 'WPML\\Core\\Twig_Node_Expression_ExtensionReference' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/ExtensionReference.php',
346
+ 'WPML\\Core\\Twig_Node_Expression_Filter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Filter.php',
347
+ 'WPML\\Core\\Twig_Node_Expression_Filter_Default' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Filter/Default.php',
348
+ 'WPML\\Core\\Twig_Node_Expression_Function' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Function.php',
349
+ 'WPML\\Core\\Twig_Node_Expression_GetAttr' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/GetAttr.php',
350
+ 'WPML\\Core\\Twig_Node_Expression_MethodCall' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/MethodCall.php',
351
+ 'WPML\\Core\\Twig_Node_Expression_Name' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Name.php',
352
+ 'WPML\\Core\\Twig_Node_Expression_NullCoalesce' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/NullCoalesce.php',
353
+ 'WPML\\Core\\Twig_Node_Expression_Parent' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Parent.php',
354
+ 'WPML\\Core\\Twig_Node_Expression_TempName' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/TempName.php',
355
+ 'WPML\\Core\\Twig_Node_Expression_Test' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test.php',
356
+ 'WPML\\Core\\Twig_Node_Expression_Test_Constant' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Constant.php',
357
+ 'WPML\\Core\\Twig_Node_Expression_Test_Defined' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Defined.php',
358
+ 'WPML\\Core\\Twig_Node_Expression_Test_Divisibleby' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Divisibleby.php',
359
+ 'WPML\\Core\\Twig_Node_Expression_Test_Even' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Even.php',
360
+ 'WPML\\Core\\Twig_Node_Expression_Test_Null' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Null.php',
361
+ 'WPML\\Core\\Twig_Node_Expression_Test_Odd' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Odd.php',
362
+ 'WPML\\Core\\Twig_Node_Expression_Test_Sameas' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Test/Sameas.php',
363
+ 'WPML\\Core\\Twig_Node_Expression_Unary' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary.php',
364
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Neg' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Neg.php',
365
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Not' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Not.php',
366
+ 'WPML\\Core\\Twig_Node_Expression_Unary_Pos' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Expression/Unary/Pos.php',
367
+ 'WPML\\Core\\Twig_Node_Flush' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Flush.php',
368
+ 'WPML\\Core\\Twig_Node_For' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/For.php',
369
+ 'WPML\\Core\\Twig_Node_ForLoop' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/ForLoop.php',
370
+ 'WPML\\Core\\Twig_Node_If' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/If.php',
371
+ 'WPML\\Core\\Twig_Node_Import' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Import.php',
372
+ 'WPML\\Core\\Twig_Node_Include' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Include.php',
373
+ 'WPML\\Core\\Twig_Node_Macro' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Macro.php',
374
+ 'WPML\\Core\\Twig_Node_Module' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Module.php',
375
+ 'WPML\\Core\\Twig_Node_Print' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Print.php',
376
+ 'WPML\\Core\\Twig_Node_Sandbox' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Sandbox.php',
377
+ 'WPML\\Core\\Twig_Node_SandboxedPrint' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/SandboxedPrint.php',
378
+ 'WPML\\Core\\Twig_Node_Set' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Set.php',
379
+ 'WPML\\Core\\Twig_Node_SetTemp' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/SetTemp.php',
380
+ 'WPML\\Core\\Twig_Node_Spaceless' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Spaceless.php',
381
+ 'WPML\\Core\\Twig_Node_Text' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/Text.php',
382
+ 'WPML\\Core\\Twig_Node_With' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Node/With.php',
383
+ 'WPML\\Core\\Twig_Parser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Parser.php',
384
+ 'WPML\\Core\\Twig_ParserInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/ParserInterface.php',
385
+ 'WPML\\Core\\Twig_Profiler_Dumper_Base' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Base.php',
386
+ 'WPML\\Core\\Twig_Profiler_Dumper_Blackfire' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Blackfire.php',
387
+ 'WPML\\Core\\Twig_Profiler_Dumper_Html' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Html.php',
388
+ 'WPML\\Core\\Twig_Profiler_Dumper_Text' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Dumper/Text.php',
389
+ 'WPML\\Core\\Twig_Profiler_NodeVisitor_Profiler' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php',
390
+ 'WPML\\Core\\Twig_Profiler_Node_EnterProfile' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Node/EnterProfile.php',
391
+ 'WPML\\Core\\Twig_Profiler_Node_LeaveProfile' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Node/LeaveProfile.php',
392
+ 'WPML\\Core\\Twig_Profiler_Profile' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Profiler/Profile.php',
393
+ 'WPML\\Core\\Twig_RuntimeLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/RuntimeLoaderInterface.php',
394
+ 'WPML\\Core\\Twig_Sandbox_SecurityError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityError.php',
395
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedFilterError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php',
396
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedFunctionError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php',
397
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedMethodError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php',
398
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedPropertyError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php',
399
+ 'WPML\\Core\\Twig_Sandbox_SecurityNotAllowedTagError' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php',
400
+ 'WPML\\Core\\Twig_Sandbox_SecurityPolicy' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityPolicy.php',
401
+ 'WPML\\Core\\Twig_Sandbox_SecurityPolicyInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php',
402
+ 'WPML\\Core\\Twig_SimpleFilter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleFilter.php',
403
+ 'WPML\\Core\\Twig_SimpleFunction' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleFunction.php',
404
+ 'WPML\\Core\\Twig_SimpleTest' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SimpleTest.php',
405
+ 'WPML\\Core\\Twig_Source' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Source.php',
406
+ 'WPML\\Core\\Twig_SourceContextLoaderInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/SourceContextLoaderInterface.php',
407
+ 'WPML\\Core\\Twig_Template' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Template.php',
408
+ 'WPML\\Core\\Twig_TemplateInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TemplateInterface.php',
409
+ 'WPML\\Core\\Twig_TemplateWrapper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TemplateWrapper.php',
410
+ 'WPML\\Core\\Twig_Test' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test.php',
411
+ 'WPML\\Core\\Twig_TestCallableInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TestCallableInterface.php',
412
+ 'WPML\\Core\\Twig_TestInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TestInterface.php',
413
+ 'WPML\\Core\\Twig_Test_Function' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Function.php',
414
+ 'WPML\\Core\\Twig_Test_IntegrationTestCase' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/IntegrationTestCase.php',
415
+ 'WPML\\Core\\Twig_Test_Method' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Method.php',
416
+ 'WPML\\Core\\Twig_Test_Node' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/Node.php',
417
+ 'WPML\\Core\\Twig_Test_NodeTestCase' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Test/NodeTestCase.php',
418
+ 'WPML\\Core\\Twig_Token' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Token.php',
419
+ 'WPML\\Core\\Twig_TokenParser' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser.php',
420
+ 'WPML\\Core\\Twig_TokenParserBroker' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserBroker.php',
421
+ 'WPML\\Core\\Twig_TokenParserBrokerInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserBrokerInterface.php',
422
+ 'WPML\\Core\\Twig_TokenParserInterface' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParserInterface.php',
423
+ 'WPML\\Core\\Twig_TokenParser_AutoEscape' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/AutoEscape.php',
424
+ 'WPML\\Core\\Twig_TokenParser_Block' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Block.php',
425
+ 'WPML\\Core\\Twig_TokenParser_Deprecated' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Deprecated.php',
426
+ 'WPML\\Core\\Twig_TokenParser_Do' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Do.php',
427
+ 'WPML\\Core\\Twig_TokenParser_Embed' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Embed.php',
428
+ 'WPML\\Core\\Twig_TokenParser_Extends' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Extends.php',
429
+ 'WPML\\Core\\Twig_TokenParser_Filter' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Filter.php',
430
+ 'WPML\\Core\\Twig_TokenParser_Flush' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Flush.php',
431
+ 'WPML\\Core\\Twig_TokenParser_For' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/For.php',
432
+ 'WPML\\Core\\Twig_TokenParser_From' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/From.php',
433
+ 'WPML\\Core\\Twig_TokenParser_If' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/If.php',
434
+ 'WPML\\Core\\Twig_TokenParser_Import' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Import.php',
435
+ 'WPML\\Core\\Twig_TokenParser_Include' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Include.php',
436
+ 'WPML\\Core\\Twig_TokenParser_Macro' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Macro.php',
437
+ 'WPML\\Core\\Twig_TokenParser_Sandbox' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Sandbox.php',
438
+ 'WPML\\Core\\Twig_TokenParser_Set' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Set.php',
439
+ 'WPML\\Core\\Twig_TokenParser_Spaceless' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Spaceless.php',
440
+ 'WPML\\Core\\Twig_TokenParser_Use' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/Use.php',
441
+ 'WPML\\Core\\Twig_TokenParser_With' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenParser/With.php',
442
+ 'WPML\\Core\\Twig_TokenStream' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/TokenStream.php',
443
+ 'WPML\\Core\\Twig_Util_DeprecationCollector' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Util/DeprecationCollector.php',
444
+ 'WPML\\Core\\Twig_Util_TemplateDirIterator' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/lib/twig/lib/Twig/Util/TemplateDirIterator.php',
445
+ 'WPML\\DocPage' => __DIR__ . '/..' . '/wpml/core-api/core/DocPage.php',
446
+ 'WPML\\Element\\API\\Entity\\LanguageMapping' => __DIR__ . '/..' . '/wpml/core-api/core/Entity/LanguageMapping.php',
447
+ 'WPML\\Element\\API\\IfOriginalPost' => __DIR__ . '/..' . '/wpml/core-api/core/IfOriginalPost.php',
448
+ 'WPML\\Element\\API\\Languages' => __DIR__ . '/..' . '/wpml/core-api/core/Languages.php',
449
+ 'WPML\\Element\\API\\Post' => __DIR__ . '/..' . '/wpml/core-api/core/Post.php',
450
+ 'WPML\\Element\\API\\PostTranslations' => __DIR__ . '/..' . '/wpml/core-api/core/PostTranslations.php',
451
+ 'WPML\\Element\\API\\Translations' => __DIR__ . '/..' . '/wpml/core-api/core/Translations.php',
452
+ 'WPML\\Element\\API\\TranslationsRepository' => __DIR__ . '/..' . '/wpml/core-api/core/TranslationsRepository.php',
453
+ 'WPML\\FP\\Applicative' => __DIR__ . '/..' . '/wpml/fp/core/Functor/Applicative.php',
454
+ 'WPML\\FP\\Cast' => __DIR__ . '/..' . '/wpml/fp/core/Cast.php',
455
+ 'WPML\\FP\\ConstApplicative' => __DIR__ . '/..' . '/wpml/fp/core/Functor/ConstApplicative.php',
456
+ 'WPML\\FP\\Curryable' => __DIR__ . '/..' . '/wpml/fp/core/traits/Curryable.php',
457
+ 'WPML\\FP\\Debug' => __DIR__ . '/..' . '/wpml/fp/core/Debug.php',
458
+ 'WPML\\FP\\Either' => __DIR__ . '/..' . '/wpml/fp/core/Either.php',
459
+ 'WPML\\FP\\FP' => __DIR__ . '/..' . '/wpml/fp/core/FP.php',
460
+ 'WPML\\FP\\Fns' => __DIR__ . '/..' . '/wpml/fp/core/Fns.php',
461
+ 'WPML\\FP\\Functor\\ConstFunctor' => __DIR__ . '/..' . '/wpml/fp/core/Functor/ConstFunctor.php',
462
+ 'WPML\\FP\\Functor\\Functor' => __DIR__ . '/..' . '/wpml/fp/core/Functor/Functor.php',
463
+ 'WPML\\FP\\Functor\\IdentityFunctor' => __DIR__ . '/..' . '/wpml/fp/core/Functor/IdentityFunctor.php',
464
+ 'WPML\\FP\\Functor\\Pointed' => __DIR__ . '/..' . '/wpml/fp/core/Functor/Pointed.php',
465
+ 'WPML\\FP\\Json' => __DIR__ . '/..' . '/wpml/fp/core/Json.php',
466
+ 'WPML\\FP\\Just' => __DIR__ . '/..' . '/wpml/fp/core/Maybe.php',
467
+ 'WPML\\FP\\Left' => __DIR__ . '/..' . '/wpml/fp/core/Either.php',
468
+ 'WPML\\FP\\Logic' => __DIR__ . '/..' . '/wpml/fp/core/Logic.php',
469
+ 'WPML\\FP\\Lst' => __DIR__ . '/..' . '/wpml/fp/core/Lst.php',
470
+ 'WPML\\FP\\Math' => __DIR__ . '/..' . '/wpml/fp/core/Math.php',
471
+ 'WPML\\FP\\Maybe' => __DIR__ . '/..' . '/wpml/fp/core/Maybe.php',
472
+ 'WPML\\FP\\Nothing' => __DIR__ . '/..' . '/wpml/fp/core/Maybe.php',
473
+ 'WPML\\FP\\Obj' => __DIR__ . '/..' . '/wpml/fp/core/Obj.php',
474
+ 'WPML\\FP\\Promise' => __DIR__ . '/..' . '/wpml/fp/core/Promise.php',
475
+ 'WPML\\FP\\Relation' => __DIR__ . '/..' . '/wpml/fp/core/Relation.php',
476
+ 'WPML\\FP\\Right' => __DIR__ . '/..' . '/wpml/fp/core/Either.php',
477
+ 'WPML\\FP\\Str' => __DIR__ . '/..' . '/wpml/fp/core/Strings.php',
478
+ 'WPML\\FP\\System\\System' => __DIR__ . '/..' . '/wpml/fp/core/SystemClass.php',
479
+ 'WPML\\FP\\System\\_Filter' => __DIR__ . '/..' . '/wpml/fp/core/Filter.php',
480
+ 'WPML\\FP\\System\\_Validator' => __DIR__ . '/..' . '/wpml/fp/core/Validator.php',
481
+ 'WPML\\FP\\Undefined' => __DIR__ . '/..' . '/wpml/fp/core/Undefined.php',
482
+ 'WPML\\FP\\Wrapper' => __DIR__ . '/..' . '/wpml/fp/core/Wrapper.php',
483
+ 'WPML\\FP\\_Invoker' => __DIR__ . '/..' . '/wpml/fp/core/Invoker.php',
484
+ 'WPML\\LIB\\WP\\App\\Resources' => __DIR__ . '/..' . '/wpml/wp/classes/Resources.php',
485
+ 'WPML\\LIB\\WP\\Attachment' => __DIR__ . '/..' . '/wpml/wp/classes/Attachment.php',
486
+ 'WPML\\LIB\\WP\\Cache' => __DIR__ . '/..' . '/wpml/wp/classes/Cache.php',
487
+ 'WPML\\LIB\\WP\\Gutenberg' => __DIR__ . '/..' . '/wpml/wp/classes/Gutenberg.php',
488
+ 'WPML\\LIB\\WP\\Hooks' => __DIR__ . '/..' . '/wpml/wp/classes/Hooks.php',
489
+ 'WPML\\LIB\\WP\\Http' => __DIR__ . '/..' . '/wpml/wp/classes/Http.php',
490
+ 'WPML\\LIB\\WP\\Nonce' => __DIR__ . '/..' . '/wpml/wp/classes/Nonce.php',
491
+ 'WPML\\LIB\\WP\\Option' => __DIR__ . '/..' . '/wpml/wp/classes/Option.php',
492
+ 'WPML\\LIB\\WP\\Post' => __DIR__ . '/..' . '/wpml/wp/classes/Post.php',
493
+ 'WPML\\LIB\\WP\\PostType' => __DIR__ . '/..' . '/wpml/wp/classes/PostType.php',
494
+ 'WPML\\LIB\\WP\\Roles' => __DIR__ . '/..' . '/wpml/wp/classes/Roles.php',
495
+ 'WPML\\LIB\\WP\\Transient' => __DIR__ . '/..' . '/wpml/wp/classes/Transient.php',
496
+ 'WPML\\LIB\\WP\\User' => __DIR__ . '/..' . '/wpml/wp/classes/User.php',
497
+ 'WPML\\LIB\\WP\\WPDB' => __DIR__ . '/..' . '/wpml/wp/classes/WPDB.php',
498
+ 'WPML\\LIB\\WP\\WordPress' => __DIR__ . '/..' . '/wpml/wp/classes/WP.php',
499
+ 'WPML\\Media\\Option' => __DIR__ . '/..' . '/wpml/core-api/core/media/Option.php',
500
+ 'WPML\\Notices\\DismissNotices' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/DismissNotices.php',
501
+ 'WPML\\Records\\Translations' => __DIR__ . '/..' . '/wpml/core-api/core/Records/Translations.php',
502
+ 'WPML\\Settings\\PostType\\Automatic' => __DIR__ . '/..' . '/wpml/core-api/core/settings/Automatic.php',
503
+ 'WPML\\Setup\\Option' => __DIR__ . '/..' . '/wpml/core-api/core/setup/Option.php',
504
+ 'WPML\\Timer' => __DIR__ . '/..' . '/wpml/core-api/core/Timer.php',
505
+ 'WPML\\UIPage' => __DIR__ . '/..' . '/wpml/core-api/core/UIPage.php',
506
+ 'WPML\\Utilities\\ILock' => __DIR__ . '/..' . '/wpml/core-api/core/utility/ILock.php',
507
+ 'WPML\\Utilities\\Lock' => __DIR__ . '/..' . '/wpml/core-api/core/utility/Lock.php',
508
+ 'WPML\\WP\\OptionManager' => __DIR__ . '/..' . '/wpml/core-api/core/OptionManager.php',
509
+ 'WPML_AJAX_Action_Validation' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-ajax-action-validation.php',
510
+ 'WPML_AJAX_Base_Factory' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-ajax-action-base-factory.php',
511
+ 'WPML_Action_Filter_Loader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-action-filter-loader.php',
512
+ 'WPML_Block_Editor_Helper' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/block-editor/class-wpml-block-editor-helper.php',
513
+ 'WPML_Cookie' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/cookie/class-wpml-cookie.php',
514
+ 'WPML_Core_Privacy_Content' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-core-privacy-content.php',
515
+ 'WPML_Current_Screen_Loader_Factory' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/action-filter-loader/class-wpml-current-screen-loader-factory.php',
516
+ 'WPML_File' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/class-wpml-file.php',
517
+ 'WPML_Notice' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice.php',
518
+ 'WPML_Notice_Action' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice-action.php',
519
+ 'WPML_Notice_Render' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notice-render.php',
520
+ 'WPML_Notice_Show_On_Dashboard_And_WPML_Pages' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/pages/class-wpml-notice-show-on-dashboard-and-wpml-pages.php',
521
+ 'WPML_Notices' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/notices/class-wpml-notices.php',
522
+ 'WPML_PHP_Functions' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/wpml-php-functions.php',
523
+ 'WPML_Privacy_Content' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-privacy-content.php',
524
+ 'WPML_Privacy_Content_Factory' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/privacy/class-wpml-privacy-content-factory.php',
525
+ 'WPML_Templates_Factory' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/templating/class-wpml-templates-factory.php',
526
+ 'WPML_Twig_Template' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/templates/class-wpml-twig-template.php',
527
+ 'WPML_Twig_Template_Loader' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/templates/wpml-twig-template-loader.php',
528
+ 'WPML_Twig_WP_Plugin_Extension' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/twig-extensions/wpml-twig-wp-plugin-extension.php',
529
+ 'WPML_WP_API' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-api.php',
530
+ 'WPML_WP_Cache' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/utilities/class-wpml-wp-cache.php',
531
+ 'WPML_WP_Post_Type' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/wpml-wp-post-type.php',
532
+ 'WPML_WP_Roles' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-roles.php',
533
+ 'WPML_WP_Taxonomy' => __DIR__ . '/..' . '/wpml/wpml-dependencies/lib/classes/wpml-wp/class-wpml-wp-taxonomy.php',
534
+ );
535
+
536
+ public static function getInitializer(ClassLoader $loader)
537
+ {
538
+ return \Closure::bind(function () use ($loader) {
539
+ $loader->prefixLengthsPsr4 = ComposerStaticInit4821ed1a7ed1caf1298338b695908544::$prefixLengthsPsr4;
540
+ $loader->prefixDirsPsr4 = ComposerStaticInit4821ed1a7ed1caf1298338b695908544::$prefixDirsPsr4;
541
+ $loader->classMap = ComposerStaticInit4821ed1a7ed1caf1298338b695908544::$classMap;
542
+
543
+ }, null, ClassLoader::class);
544
+ }
545
+ }
addons/vendor/composer/installed.json ADDED
@@ -0,0 +1,799 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "otgs/auryn",
4
+ "version": "dev-master",
5
+ "version_normalized": "9999999-dev",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/OnTheGoSystems/auryn.git",
9
+ "reference": "82dca7f4674d5a283947620892597c1f4325bb76"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/OnTheGoSystems/auryn/zipball/82dca7f4674d5a283947620892597c1f4325bb76",
14
+ "reference": "82dca7f4674d5a283947620892597c1f4325bb76",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.3.0"
19
+ },
20
+ "require-dev": {
21
+ "athletic/athletic": "~0.1",
22
+ "fabpot/php-cs-fixer": "~1.9",
23
+ "phpunit/phpunit": "^4.8"
24
+ },
25
+ "time": "2020-10-29T12:28:42+00:00",
26
+ "type": "library",
27
+ "installation-source": "dist",
28
+ "autoload": {
29
+ "psr-4": {
30
+ "WPML\\Auryn\\": "lib/"
31
+ }
32
+ },
33
+ "notification-url": "https://packagist.org/downloads/",
34
+ "license": [
35
+ "MIT"
36
+ ],
37
+ "authors": [
38
+ {
39
+ "name": "Daniel Lowrey",
40
+ "email": "rdlowrey@gmail.com",
41
+ "homepage": "https://github.com/rdlowrey",
42
+ "role": "Creator / Main Developer"
43
+ },
44
+ {
45
+ "name": "Levi Morrison",
46
+ "email": "levim@php.net",
47
+ "homepage": "http://morrisonlevi.github.com/",
48
+ "role": "Developer"
49
+ },
50
+ {
51
+ "name": "Dan Ackroyd",
52
+ "email": "Danack@basereality.com",
53
+ "homepage": "http://www.basereality.com",
54
+ "role": "Developer"
55
+ }
56
+ ],
57
+ "description": "Auryn is a dependency injector for bootstrapping object-oriented PHP applications.",
58
+ "homepage": "https://github.com/rdlowrey/auryn",
59
+ "keywords": [
60
+ "dependency injection",
61
+ "dic",
62
+ "ioc"
63
+ ],
64
+ "support": {
65
+ "source": "https://github.com/OnTheGoSystems/auryn/tree/master"
66
+ }
67
+ },
68
+ {
69
+ "name": "otgs/icons",
70
+ "version": "1.0.2",
71
+ "version_normalized": "1.0.2.0",
72
+ "source": {
73
+ "type": "git",
74
+ "url": "https://git.onthegosystems.com/otgs-public/otgs-icons.git",
75
+ "reference": "4dbce75c1ba493c7d4d2c86f318d2ad10fa4f24b"
76
+ },
77
+ "time": "2020-03-20T16:45:00+00:00",
78
+ "type": "library",
79
+ "installation-source": "source",
80
+ "notification-url": "https://packagist.org/downloads/",
81
+ "license": [
82
+ "GPL-2.0"
83
+ ],
84
+ "description": "Toolset and WPML icons"
85
+ },
86
+ {
87
+ "name": "otgs/ui",
88
+ "version": "dev-master",
89
+ "version_normalized": "9999999-dev",
90
+ "source": {
91
+ "type": "git",
92
+ "url": "https://git.onthegosystems.com/otgs-public/otgs-ui.git",
93
+ "reference": "d8b11b073ba3247f25108b0dd88742ca3b0d4628"
94
+ },
95
+ "require": {
96
+ "roave/security-advisories": "dev-master"
97
+ },
98
+ "require-dev": {
99
+ "dealerdirect/phpcodesniffer-composer-installer": "*",
100
+ "otgs/unit-tests-framework": "~1.2.0",
101
+ "phpcompatibility/php-compatibility": "*",
102
+ "phpunit/phpunit": "~5.7",
103
+ "sebastian/phpcpd": "^3.0",
104
+ "squizlabs/php_codesniffer": "~3",
105
+ "wp-coding-standards/wpcs": "^0"
106
+ },
107
+ "suggest": {
108
+ "otgs/icons": "Needed for displaying Company's glyphs and icons,"
109
+ },
110
+ "time": "2020-11-26T14:58:07+00:00",
111
+ "type": "library",
112
+ "installation-source": "source",
113
+ "autoload": {
114
+ "classmap": [
115
+ "src/php/"
116
+ ]
117
+ },
118
+ "notification-url": "https://packagist.org/downloads/",
119
+ "license": [
120
+ "GPL-2.0-or-later"
121
+ ],
122
+ "authors": [
123
+ {
124
+ "name": "Andrea Sciamanna",
125
+ "email": "andrea.s@onthegosystems.com",
126
+ "homepage": "https://onthegosystems.com"
127
+ },
128
+ {
129
+ "name": "Kasia Janoska",
130
+ "email": "kasia.j@onthegosystems.com",
131
+ "homepage": "https://onthegosystems.com"
132
+ }
133
+ ],
134
+ "description": "UI library from OnTheGoSystems",
135
+ "homepage": "https://git.onthegosystems.com/otgs-public/otgs-ui",
136
+ "keywords": [
137
+ "ui"
138
+ ]
139
+ },
140
+ {
141
+ "name": "roave/security-advisories",
142
+ "version": "dev-master",
143
+ "version_normalized": "9999999-dev",
144
+ "source": {
145
+ "type": "git",
146
+ "url": "https://github.com/Roave/SecurityAdvisories.git",
147
+ "reference": "fa60732bcafd446e9ff858eefa06cdcbae8d9823"
148
+ },
149
+ "dist": {
150
+ "type": "zip",
151
+ "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/fa60732bcafd446e9ff858eefa06cdcbae8d9823",
152
+ "reference": "fa60732bcafd446e9ff858eefa06cdcbae8d9823",
153
+ "shasum": ""
154
+ },
155
+ "conflict": {
156
+ "3f/pygmentize": "<1.2",
157
+ "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3",
158
+ "akaunting/akaunting": "<2.1.13",
159
+ "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1",
160
+ "amazing/media2click": ">=1,<1.3.3",
161
+ "amphp/artax": "<1.0.6|>=2,<2.0.6",
162
+ "amphp/http": "<1.0.1",
163
+ "amphp/http-client": ">=4,<4.4",
164
+ "anchorcms/anchor-cms": "<=0.12.7",
165
+ "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6",
166
+ "area17/twill": "<1.2.5|>=2,<2.5.3",
167
+ "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99",
168
+ "aws/aws-sdk-php": ">=3,<3.2.1",
169
+ "bagisto/bagisto": "<0.1.5",
170
+ "barrelstrength/sprout-base-email": "<1.2.7",
171
+ "barrelstrength/sprout-forms": "<3.9",
172
+ "baserproject/basercms": "<4.5.4",
173
+ "billz/raspap-webgui": "<=2.6.6",
174
+ "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3",
175
+ "bolt/bolt": "<3.7.2",
176
+ "bolt/core": "<4.1.13",
177
+ "bottelet/flarepoint": "<2.2.1",
178
+ "brightlocal/phpwhois": "<=4.2.5",
179
+ "buddypress/buddypress": "<7.2.1",
180
+ "bugsnag/bugsnag-laravel": ">=2,<2.0.2",
181
+ "bytefury/crater": "<6",
182
+ "cachethq/cachet": "<2.5.1",
183
+ "cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7",
184
+ "cardgate/magento2": "<2.0.33",
185
+ "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4",
186
+ "cartalyst/sentry": "<=2.1.6",
187
+ "catfan/medoo": "<1.7.5",
188
+ "centreon/centreon": "<20.10.7",
189
+ "cesnet/simplesamlphp-module-proxystatistics": "<3.1",
190
+ "codeception/codeception": "<3.1.3|>=4,<4.1.22",
191
+ "codeigniter/framework": "<=3.0.6",
192
+ "codeigniter4/framework": "<4.1.8",
193
+ "codiad/codiad": "<=2.8.4",
194
+ "composer/composer": "<1.10.23|>=2-alpha.1,<2.1.9",
195
+ "concrete5/concrete5": "<8.5.5",
196
+ "concrete5/core": "<8.5.7",
197
+ "contao-components/mediaelement": ">=2.14.2,<2.21.1",
198
+ "contao/core": ">=2,<3.5.39",
199
+ "contao/core-bundle": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|= 4.10.0",
200
+ "contao/listing-bundle": ">=4,<4.4.8",
201
+ "craftcms/cms": "<3.7.14",
202
+ "croogo/croogo": "<3.0.7",
203
+ "datadog/dd-trace": ">=0.30,<0.30.2",
204
+ "david-garcia/phpwhois": "<=4.3.1",
205
+ "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1",
206
+ "directmailteam/direct-mail": "<5.2.4",
207
+ "doctrine/annotations": ">=1,<1.2.7",
208
+ "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2",
209
+ "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1",
210
+ "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4",
211
+ "doctrine/doctrine-bundle": "<1.5.2",
212
+ "doctrine/doctrine-module": "<=0.7.1",
213
+ "doctrine/mongodb-odm": ">=1,<1.0.2",
214
+ "doctrine/mongodb-odm-bundle": ">=2,<3.0.1",
215
+ "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4",
216
+ "dolibarr/dolibarr": "<=14.0.5|>= 3.3.beta1, < 13.0.2",
217
+ "dompdf/dompdf": ">=0.6,<0.6.2",
218
+ "drupal/core": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4",
219
+ "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4",
220
+ "dweeves/magmi": "<=0.7.24",
221
+ "ecodev/newsletter": "<=4",
222
+ "elgg/elgg": "<3.3.24|>=4,<4.0.5",
223
+ "endroid/qr-code-bundle": "<3.4.2",
224
+ "enshrined/svg-sanitize": "<0.13.1",
225
+ "erusev/parsedown": "<1.7.2",
226
+ "ether/logs": "<3.0.4",
227
+ "ezsystems/demobundle": ">=5.4,<5.4.6.1",
228
+ "ezsystems/ez-support-tools": ">=2.2,<2.2.3",
229
+ "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1",
230
+ "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1",
231
+ "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24",
232
+ "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<=1.5.25",
233
+ "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1",
234
+ "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1",
235
+ "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8",
236
+ "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7",
237
+ "ezsystems/ezplatform-user": ">=1,<1.0.1",
238
+ "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.26",
239
+ "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1",
240
+ "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3",
241
+ "ezsystems/repository-forms": ">=2.3,<2.3.2.1",
242
+ "ezyang/htmlpurifier": "<4.1.1",
243
+ "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2",
244
+ "feehi/cms": "<=2.1.1",
245
+ "feehi/feehicms": "<=0.1.3",
246
+ "firebase/php-jwt": "<2",
247
+ "flarum/core": ">=1,<=1.0.1",
248
+ "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15",
249
+ "flarum/tags": "<=0.1-beta.13",
250
+ "fluidtypo3/vhs": "<5.1.1",
251
+ "fooman/tcpdf": "<6.2.22",
252
+ "forkcms/forkcms": "<=5.9.2",
253
+ "fossar/tcpdf-parser": "<6.2.22",
254
+ "francoisjacquet/rosariosis": "<8.1.1",
255
+ "friendsofsymfony/oauth2-php": "<1.3",
256
+ "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2",
257
+ "friendsofsymfony/user-bundle": ">=1.2,<1.3.5",
258
+ "friendsoftypo3/mediace": ">=7.6.2,<7.6.5",
259
+ "froala/wysiwyg-editor": "<3.2.7",
260
+ "fuel/core": "<1.8.1",
261
+ "gaoming13/wechat-php-sdk": "<=1.10.2",
262
+ "getgrav/grav": "<1.7.28",
263
+ "getkirby/cms": "<3.5.8",
264
+ "getkirby/panel": "<2.5.14",
265
+ "gilacms/gila": "<=1.11.4",
266
+ "globalpayments/php-sdk": "<2",
267
+ "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3",
268
+ "gree/jose": "<=2.2",
269
+ "gregwar/rst": "<1.0.3",
270
+ "grumpydictator/firefly-iii": "<5.6.5",
271
+ "guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1",
272
+ "helloxz/imgurl": "<=2.31",
273
+ "hillelcoren/invoice-ninja": "<5.3.35",
274
+ "hjue/justwriting": "<=1",
275
+ "hov/jobfair": "<1.0.13|>=2,<2.0.2",
276
+ "ibexa/post-install": "<=1.0.4",
277
+ "icecoder/icecoder": "<=8.1",
278
+ "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10",
279
+ "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4",
280
+ "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40",
281
+ "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15",
282
+ "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75",
283
+ "impresscms/impresscms": "<=1.4.2",
284
+ "in2code/femanager": "<5.5.1|>=6,<6.3.1",
285
+ "intelliants/subrion": "<=4.2.1",
286
+ "ivankristianto/phpwhois": "<=4.3",
287
+ "jackalope/jackalope-doctrine-dbal": "<1.7.4",
288
+ "james-heinrich/getid3": "<1.9.21",
289
+ "joomla/archive": "<1.1.10",
290
+ "joomla/session": "<1.3.1",
291
+ "jsmitty12/phpwhois": "<5.1",
292
+ "kazist/phpwhois": "<=4.2.6",
293
+ "kevinpapst/kimai2": "<1.16.7",
294
+ "kitodo/presentation": "<3.1.2",
295
+ "klaviyo/magento2-extension": ">=1,<3",
296
+ "kreait/firebase-php": ">=3.2,<3.8.1",
297
+ "la-haute-societe/tcpdf": "<6.2.22",
298
+ "laminas/laminas-form": "<2.17.2|>=3,<3.0.2|>=3.1,<3.1.1",
299
+ "laminas/laminas-http": "<2.14.2",
300
+ "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75",
301
+ "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
302
+ "latte/latte": "<2.10.8",
303
+ "lavalite/cms": "<=5.8",
304
+ "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5",
305
+ "league/commonmark": "<0.18.3",
306
+ "league/flysystem": "<1.1.4|>=2,<2.1.1",
307
+ "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3",
308
+ "librenms/librenms": "<=21.11",
309
+ "limesurvey/limesurvey": "<3.27.19",
310
+ "livehelperchat/livehelperchat": "<=3.91",
311
+ "livewire/livewire": ">2.2.4,<2.2.6",
312
+ "lms/routes": "<2.1.1",
313
+ "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2",
314
+ "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3",
315
+ "magento/magento1ce": "<1.9.4.3",
316
+ "magento/magento1ee": ">=1,<1.14.4.3",
317
+ "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2",
318
+ "marcwillmann/turn": "<0.3.3",
319
+ "mautic/core": "<4|= 2.13.1",
320
+ "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35",
321
+ "microweber/microweber": "<1.2.11",
322
+ "miniorange/miniorange-saml": "<1.4.3",
323
+ "mittwald/typo3_forum": "<1.2.1",
324
+ "modx/revolution": "<2.8",
325
+ "monolog/monolog": ">=1.8,<1.12",
326
+ "moodle/moodle": "<3.9.11|>=3.10-beta,<3.10.8|>=3.11,<3.11.5",
327
+ "mustache/mustache": ">=2,<2.14.1",
328
+ "namshi/jose": "<2.2",
329
+ "neoan3-apps/template": "<1.1.1",
330
+ "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6",
331
+ "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3",
332
+ "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3",
333
+ "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5",
334
+ "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15",
335
+ "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6",
336
+ "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13",
337
+ "nilsteampassnet/teampass": "<=2.1.27.36",
338
+ "nukeviet/nukeviet": "<4.3.4",
339
+ "nystudio107/craft-seomatic": "<3.3",
340
+ "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1",
341
+ "october/backend": "<1.1.2",
342
+ "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469",
343
+ "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12",
344
+ "october/rain": "<1.0.472|>=1.1,<1.1.2",
345
+ "october/system": "<1.0.473|>=1.1,<1.1.6|>=2.1,<2.1.12",
346
+ "onelogin/php-saml": "<2.10.4",
347
+ "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5",
348
+ "opencart/opencart": "<=3.0.3.2",
349
+ "openid/php-openid": "<2.3",
350
+ "openmage/magento-lts": "<19.4.15|>=20,<20.0.13",
351
+ "orchid/platform": ">=9,<9.4.4",
352
+ "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7",
353
+ "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8",
354
+ "padraic/humbug_get_contents": "<1.1.2",
355
+ "pagarme/pagarme-php": ">=0,<3",
356
+ "pagekit/pagekit": "<=1.0.18",
357
+ "paragonie/random_compat": "<2",
358
+ "passbolt/passbolt_api": "<2.11",
359
+ "paypal/merchant-sdk-php": "<3.12",
360
+ "pear/archive_tar": "<1.4.14",
361
+ "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1",
362
+ "personnummer/personnummer": "<3.0.2",
363
+ "phanan/koel": "<5.1.4",
364
+ "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7",
365
+ "phpmailer/phpmailer": "<6.5",
366
+ "phpmussel/phpmussel": ">=1,<1.6",
367
+ "phpmyadmin/phpmyadmin": "<4.9.8|>=5,<5.0.3|>=5.1,<5.1.2",
368
+ "phpoffice/phpexcel": "<1.8.2",
369
+ "phpoffice/phpspreadsheet": "<1.16",
370
+ "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7",
371
+ "phpservermon/phpservermon": "<=3.5.2",
372
+ "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3",
373
+ "phpwhois/phpwhois": "<=4.2.5",
374
+ "phpxmlrpc/extras": "<0.6.1",
375
+ "pimcore/pimcore": "<=10.2.9",
376
+ "pocketmine/pocketmine-mp": "<4.0.7",
377
+ "pressbooks/pressbooks": "<5.18",
378
+ "prestashop/autoupgrade": ">=4,<4.10.1",
379
+ "prestashop/contactform": ">1.0.1,<4.3",
380
+ "prestashop/gamification": "<2.3.2",
381
+ "prestashop/prestashop": ">=1.7,<=1.7.8.2",
382
+ "prestashop/productcomments": ">=4,<4.2.1",
383
+ "prestashop/ps_emailsubscription": "<2.6.1",
384
+ "prestashop/ps_facetedsearch": "<3.4.1",
385
+ "prestashop/ps_linklist": "<3.1",
386
+ "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2",
387
+ "propel/propel": ">=2-alpha.1,<=2-alpha.7",
388
+ "propel/propel1": ">=1,<=1.7.1",
389
+ "pterodactyl/panel": "<1.7",
390
+ "pusher/pusher-php-server": "<2.2.1",
391
+ "pwweb/laravel-core": "<=0.3.6-beta",
392
+ "rainlab/debugbar-plugin": "<3.1",
393
+ "remdex/livehelperchat": "<3.93",
394
+ "rmccue/requests": ">=1.6,<1.8",
395
+ "robrichards/xmlseclibs": "<3.0.4",
396
+ "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1",
397
+ "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9",
398
+ "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11",
399
+ "sensiolabs/connect": "<4.2.3",
400
+ "serluck/phpwhois": "<=4.2.6",
401
+ "shopware/core": "<=6.4.6",
402
+ "shopware/platform": "<=6.4.6",
403
+ "shopware/production": "<=6.3.5.2",
404
+ "shopware/shopware": "<5.7.7",
405
+ "showdoc/showdoc": "<2.10.2",
406
+ "silverstripe/admin": ">=1,<1.8.1",
407
+ "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2",
408
+ "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4",
409
+ "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1",
410
+ "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3",
411
+ "silverstripe/framework": "<4.7.4",
412
+ "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2",
413
+ "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
414
+ "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4",
415
+ "silverstripe/subsites": ">=2,<2.1.1",
416
+ "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1",
417
+ "silverstripe/userforms": "<3",
418
+ "simple-updates/phpwhois": "<=1",
419
+ "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4",
420
+ "simplesamlphp/simplesamlphp": "<1.18.6",
421
+ "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1",
422
+ "simplito/elliptic-php": "<1.0.6",
423
+ "slim/slim": "<2.6",
424
+ "smarty/smarty": "<3.1.43|>=4,<4.0.3",
425
+ "snipe/snipe-it": "<=5.3.7",
426
+ "socalnick/scn-social-auth": "<1.15.2",
427
+ "socialiteproviders/steam": "<1.1",
428
+ "spipu/html2pdf": "<5.2.4",
429
+ "spoonity/tcpdf": "<6.2.22",
430
+ "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1",
431
+ "ssddanbrown/bookstack": "<21.12.1",
432
+ "stormpath/sdk": ">=0,<9.9.99",
433
+ "studio-42/elfinder": "<2.1.59",
434
+ "subrion/cms": "<=4.2.1",
435
+ "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8",
436
+ "swiftmailer/swiftmailer": ">=4,<5.4.5",
437
+ "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2",
438
+ "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1",
439
+ "sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1",
440
+ "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1",
441
+ "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4",
442
+ "sylius/sylius": "<1.6.9|>=1.7,<1.7.9|>=1.8,<1.8.3|>=1.9,<1.9.5",
443
+ "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99",
444
+ "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4",
445
+ "symbiote/silverstripe-versionedfiles": "<=2.0.3",
446
+ "symfont/process": ">=0,<4",
447
+ "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8",
448
+ "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
449
+ "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4",
450
+ "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1",
451
+ "symfony/framework-bundle": "<5.3.15|>=5.4,<5.4.4|>=6,<6.0.4",
452
+ "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7",
453
+ "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12",
454
+ "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
455
+ "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1",
456
+ "symfony/mime": ">=4.3,<4.3.8",
457
+ "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
458
+ "symfony/polyfill": ">=1,<1.10",
459
+ "symfony/polyfill-php55": ">=1,<1.10",
460
+ "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
461
+ "symfony/routing": ">=2,<2.0.19",
462
+ "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8",
463
+ "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12",
464
+ "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9",
465
+ "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11",
466
+ "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8",
467
+ "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8|>=5.3,<5.3.2",
468
+ "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12",
469
+ "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3",
470
+ "symfony/translation": ">=2,<2.0.17",
471
+ "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3",
472
+ "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8",
473
+ "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4",
474
+ "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7",
475
+ "t3/dce": ">=2.2,<2.6.2",
476
+ "t3g/svg-sanitizer": "<1.0.3",
477
+ "tecnickcom/tcpdf": "<6.2.22",
478
+ "thelia/backoffice-default-template": ">=2.1,<2.1.2",
479
+ "thelia/thelia": ">=2.1-beta.1,<2.1.3",
480
+ "theonedemon/phpwhois": "<=4.2.5",
481
+ "tinymce/tinymce": "<5.10",
482
+ "titon/framework": ">=0,<9.9.99",
483
+ "topthink/framework": "<6.0.9",
484
+ "topthink/think": "<=6.0.9",
485
+ "topthink/thinkphp": "<=3.2.3",
486
+ "tribalsystems/zenario": "<8.8.53370",
487
+ "truckersmp/phpwhois": "<=4.3.1",
488
+ "twig/twig": "<1.38|>=2,<2.7",
489
+ "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5",
490
+ "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1",
491
+ "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<=7.6.52|>=8,<=8.7.41|>=9,<9.5.29|>=10,<10.4.19|>=11,<11.5",
492
+ "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1",
493
+ "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6",
494
+ "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3",
495
+ "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1",
496
+ "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5",
497
+ "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10",
498
+ "ua-parser/uap-php": "<3.8",
499
+ "unisharp/laravel-filemanager": "<=2.3",
500
+ "userfrosting/userfrosting": ">=0.3.1,<4.6.3",
501
+ "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2",
502
+ "vanilla/safecurl": "<0.9.2",
503
+ "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4",
504
+ "vrana/adminer": "<4.7.9",
505
+ "wallabag/tcpdf": "<6.2.22",
506
+ "wanglelecc/laracms": "<=1.0.3",
507
+ "web-auth/webauthn-framework": ">=3.3,<3.3.4",
508
+ "webcoast/deferred-image-processing": "<1.0.2",
509
+ "wikimedia/parsoid": "<0.12.2",
510
+ "willdurand/js-translation-bundle": "<2.1.1",
511
+ "wp-cli/wp-cli": "<2.5",
512
+ "yetiforce/yetiforce-crm": "<=6.3",
513
+ "yidashi/yii2cmf": "<=2",
514
+ "yii2mod/yii2-cms": "<1.9.2",
515
+ "yiisoft/yii": ">=1.1.14,<1.1.15",
516
+ "yiisoft/yii2": "<2.0.38",
517
+ "yiisoft/yii2-bootstrap": "<2.0.4",
518
+ "yiisoft/yii2-dev": "<2.0.43",
519
+ "yiisoft/yii2-elasticsearch": "<2.0.5",
520
+ "yiisoft/yii2-gii": "<2.0.4",
521
+ "yiisoft/yii2-jui": "<2.0.4",
522
+ "yiisoft/yii2-redis": "<2.0.8",
523
+ "yoast-seo-for-typo3/yoast_seo": "<7.2.3",
524
+ "yourls/yourls": "<=1.8.2",
525
+ "zendesk/zendesk_api_client_php": "<2.2.11",
526
+ "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3",
527
+ "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2",
528
+ "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2",
529
+ "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5",
530
+ "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3",
531
+ "zendframework/zend-diactoros": ">=1,<1.8.4",
532
+ "zendframework/zend-feed": ">=1,<2.10.3",
533
+ "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1",
534
+ "zendframework/zend-http": ">=1,<2.8.1",
535
+ "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6",
536
+ "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3",
537
+ "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2",
538
+ "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1",
539
+ "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4",
540
+ "zendframework/zend-validator": ">=2.3,<2.3.6",
541
+ "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1",
542
+ "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6",
543
+ "zendframework/zendframework": "<=3",
544
+ "zendframework/zendframework1": "<1.12.20",
545
+ "zendframework/zendopenid": ">=2,<2.0.2",
546
+ "zendframework/zendxml": ">=1,<1.0.1",
547
+ "zetacomponents/mail": "<1.8.2",
548
+ "zf-commons/zfc-user": "<1.2.2",
549
+ "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3",
550
+ "zfr/zfr-oauth2-server-module": "<0.1.2",
551
+ "zoujingli/thinkadmin": "<6.0.22"
552
+ },
553
+ "time": "2022-02-01T15:19:50+00:00",
554
+ "type": "metapackage",
555
+ "notification-url": "https://packagist.org/downloads/",
556
+ "license": [
557
+ "MIT"
558
+ ],
559
+ "authors": [
560
+ {
561
+ "name": "Marco Pivetta",
562
+ "email": "ocramius@gmail.com",
563
+ "role": "maintainer"
564
+ },
565
+ {
566
+ "name": "Ilya Tribusean",
567
+ "email": "slash3b@gmail.com",
568
+ "role": "maintainer"
569
+ }
570
+ ],
571
+ "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it",
572
+ "support": {
573
+ "issues": "https://github.com/Roave/SecurityAdvisories/issues",
574
+ "source": "https://github.com/Roave/SecurityAdvisories/tree/latest"
575
+ },
576
+ "funding": [
577
+ {
578
+ "url": "https://github.com/Ocramius",
579
+ "type": "github"
580
+ },
581
+ {
582
+ "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories",
583
+ "type": "tidelift"
584
+ }
585
+ ]
586
+ },
587
+ {
588
+ "name": "wpml/collect",
589
+ "version": "dev-wpml-collect-rename",
590
+ "version_normalized": "dev-wpml-collect-rename",
591
+ "source": {
592
+ "type": "git",
593
+ "url": "https://github.com/OnTheGoSystems/collect.git",
594
+ "reference": "c822762bb9dcc581b26e16cc19226d7a6087c23c"
595
+ },
596
+ "dist": {
597
+ "type": "zip",
598
+ "url": "https://api.github.com/repos/OnTheGoSystems/collect/zipball/c822762bb9dcc581b26e16cc19226d7a6087c23c",
599
+ "reference": "c822762bb9dcc581b26e16cc19226d7a6087c23c",
600
+ "shasum": ""
601
+ },
602
+ "require": {
603
+ "php": ">=5.5.9"
604
+ },
605
+ "require-dev": {
606
+ "mockery/mockery": "~0.9.4",
607
+ "phpunit/phpunit": "~4.1"
608
+ },
609
+ "time": "2020-10-28T08:07:38+00:00",
610
+ "type": "library",
611
+ "installation-source": "dist",
612
+ "autoload": {
613
+ "files": [
614
+ "src/Illuminate/Support/helpers.php"
615
+ ],
616
+ "psr-4": {
617
+ "WPML\\Collect\\": "src/Illuminate"
618
+ }
619
+ },
620
+ "notification-url": "https://packagist.org/downloads/",
621
+ "license": [
622
+ "MIT"
623
+ ],
624
+ "authors": [
625
+ {
626
+ "name": "Taylor Otwell",
627
+ "email": "taylorotwell@gmail.com"
628
+ }
629
+ ],
630
+ "description": "Collect - Illuminate Collections as a separate package.",
631
+ "keywords": [
632
+ "collection",
633
+ "laravel"
634
+ ],
635
+ "support": {
636
+ "source": "https://github.com/OnTheGoSystems/collect/tree/wpml-collect-rename"
637
+ }
638
+ },
639
+ {
640
+ "name": "wpml/core-api",
641
+ "version": "0.1.5",
642
+ "version_normalized": "0.1.5.0",
643
+ "source": {
644
+ "type": "git",
645
+ "url": "https://git.onthegosystems.com/wpml-packages/core-api.git",
646
+ "reference": "369cfd53dba15e4dceb55e0e0458c16a5a142eab"
647
+ },
648
+ "require-dev": {
649
+ "10up/wp_mock": "0.2.0",
650
+ "antecedent/patchwork": "^2.0",
651
+ "cvuorinen/phpdoc-markdown-public": "^0.2.0",
652
+ "otgs/unit-tests-framework": "~1.2.0",
653
+ "wpml/collect": "dev-wpml-collect-rename",
654
+ "wpml/fp": "dev-develop",
655
+ "wpml/wp": "dev-develop"
656
+ },
657
+ "time": "2021-11-16T12:50:12+00:00",
658
+ "type": "library",
659
+ "installation-source": "source",
660
+ "autoload": {
661
+ "classmap": [
662
+ "core"
663
+ ],
664
+ "files": []
665
+ },
666
+ "notification-url": "https://packagist.org/downloads/",
667
+ "license": [
668
+ "MIT"
669
+ ],
670
+ "authors": [
671
+ {
672
+ "name": "Bruce Pearson",
673
+ "email": "bruce@onthegosystems.com"
674
+ }
675
+ ],
676
+ "description": "Class and utilities to interface with WPML core functionality"
677
+ },
678
+ {
679
+ "name": "wpml/fp",
680
+ "version": "0.1.8",
681
+ "version_normalized": "0.1.8.0",
682
+ "source": {
683
+ "type": "git",
684
+ "url": "https://git.onthegosystems.com/wpml-packages/fp.git",
685
+ "reference": "5f233620422988ca47f3180d2fc1c2aa18191bee"
686
+ },
687
+ "require-dev": {
688
+ "cvuorinen/phpdoc-markdown-public": "^0.2.0",
689
+ "lucatume/function-mocker": "~1.0",
690
+ "phpunit/phpunit": "^5",
691
+ "wpml/collect": "dev-wpml-collect-rename"
692
+ },
693
+ "time": "2021-10-19T01:39:15+00:00",
694
+ "type": "library",
695
+ "installation-source": "source",
696
+ "autoload": {
697
+ "classmap": [
698
+ "core"
699
+ ],
700
+ "files": [
701
+ "core/functions.php",
702
+ "core/strings_functions.php",
703
+ "core/system.php"
704
+ ]
705
+ },
706
+ "notification-url": "https://packagist.org/downloads/"
707
+ },
708
+ {
709
+ "name": "wpml/wp",
710
+ "version": "0.1.7",
711
+ "version_normalized": "0.1.7.0",
712
+ "source": {
713
+ "type": "git",
714
+ "url": "https://git.onthegosystems.com/wpml-packages/wp.git",
715
+ "reference": "dc2fbeb965133f5e569f51009b919a585a5fc1a9"
716
+ },
717
+ "require-dev": {
718
+ "antecedent/patchwork": "^2.0",
719
+ "otgs/unit-tests-framework": "~1.2.0",
720
+ "wpml/collect": "dev-wpml-collect-rename",
721
+ "wpml/fp": "dev-develop"
722
+ },
723
+ "time": "2021-10-08T07:51:31+00:00",
724
+ "type": "library",
725
+ "installation-source": "source",
726
+ "autoload": {
727
+ "classmap": [
728
+ "classes/"
729
+ ],
730
+ "files": []
731
+ },
732
+ "notification-url": "https://packagist.org/downloads/",
733
+ "license": [
734
+ "MIT"
735
+ ],
736
+ "authors": [
737
+ {
738
+ "name": "Bruce Pearson",
739
+ "email": "bruce@onthegosystems.com"
740
+ }
741
+ ],
742
+ "description": "Class and utilities to interface with WordPress from WPML"
743
+ },
744
+ {
745
+ "name": "wpml/wpml-dependencies",
746
+ "version": "dev-master",
747
+ "version_normalized": "9999999-dev",
748
+ "source": {
749
+ "type": "git",
750
+ "url": "ssh://git@git.onthegosystems.com:10022/glue-plugins/wpml/packages/wpml-dependencies.git",
751
+ "reference": "bd11271851a380365a6d97c5920c4cd089a07427"
752
+ },
753
+ "require": {
754
+ "otgs/auryn": "dev-master",
755
+ "otgs/icons": "~1.0",
756
+ "otgs/ui": "dev-master",
757
+ "wpml/collect": "dev-wpml-collect-rename",
758
+ "wpml/core-api": "0.1.5",
759
+ "wpml/fp": "0.1.8",
760
+ "wpml/wp": "0.1.7"
761
+ },
762
+ "require-dev": {
763
+ "bamarni/composer-bin-plugin": "^1.4",
764
+ "composer/composer": "~2.0"
765
+ },
766
+ "time": "2022-04-22T19:51:13+00:00",
767
+ "type": "library",
768
+ "installation-source": "source",
769
+ "autoload": {
770
+ "classmap": [
771
+ "lib/"
772
+ ],
773
+ "files": [
774
+ "lib/classes/container/functions.php"
775
+ ]
776
+ },
777
+ "scripts": {
778
+ "make": [
779
+ "make githooks"
780
+ ],
781
+ "post-install-cmd": [
782
+ "@make",
783
+ "@composer bin all install --ansi"
784
+ ],
785
+ "post-update-cmd": [
786
+ "@composer bin all update --ansi"
787
+ ]
788
+ },
789
+ "authors": [
790
+ {
791
+ "name": "WPML",
792
+ "email": "hello@wpml.com",
793
+ "homepage": "http://wpml.org"
794
+ }
795
+ ],
796
+ "description": "WPML dependencies for running WCML independently.",
797
+ "homepage": "https://git.onthegosystems.com/glue-plugins/wpml/packages/wpml-dependencies"
798
+ }
799
+ ]
addons/vendor/otgs/auryn/CONTRIBUTING.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Submitting useful bug reports
2
+
3
+ Please search existing issues first to make sure this is not a duplicate.
4
+ Every issue report has a cost for the developers required to field it; be
5
+ respectful of others' time and ensure your report isn't spurious prior to
6
+ submission. Additionally, please do us all a favor by adhering to the
7
+ principles of sound bug reporting laid out by Simon Tatham here:
8
+
9
+ http://www.chiark.greenend.org.uk/~sgtatham/bugs.html
10
+
11
+ ## Development ideology
12
+
13
+ Truths which we believe to be self-evident:
14
+
15
+ - **The answer is not more options.** If you feel compelled to expose
16
+ new preferences to the user it's very possible you've made a wrong
17
+ turn somewhere.
18
+
19
+ - **There are no power users.** The idea that some users "understand"
20
+ concepts better than others has proven to be, for the most part, false.
21
+ If anything, "power users" are more dangerous than the rest, and we
22
+ should avoid exposing dangerous functionality to them.
23
+
24
+ ## Code style
25
+
26
+ Please ensure any submissions adhere to the PSR-2 code style standard:
27
+
28
+ https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
addons/vendor/otgs/auryn/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013-2014 Daniel Lowrey, Levi Morrison, Dan Ackroyd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a
6
+ copy of this software and associated documentation files (the "Software"),
7
+ to deal in the Software without restriction, including without limitation
8
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
+ and/or sell copies of the Software, and to permit persons to whom the
10
+ Software is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included
13
+ in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ IN THE SOFTWARE.
addons/vendor/otgs/auryn/README.md ADDED
@@ -0,0 +1,847 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # auryn [![Build Status](https://travis-ci.org/rdlowrey/auryn.svg?branch=master)](https://travis-ci.org/rdlowrey/auryn)
2
+
3
+ auryn is a recursive dependency injector. Use auryn to bootstrap and wire together
4
+ S.O.L.I.D., object-oriented PHP applications.
5
+
6
+ ##### How It Works
7
+
8
+ Among other things, auryn recursively instantiates class dependencies based on the parameter
9
+ type-hints specified in class constructor signatures. This requires the use of Reflection. You may
10
+ have heard that "reflection is slow". Let's clear something up: *anything* can be "slow" if you're
11
+ doing it wrong. Reflection is an order of magnitude faster than disk access and several orders of
12
+ magnitude faster than retrieving information (for example) from a remote database. Additionally,
13
+ each reflection offers the opportunity to cache the results if you're worried about speed. auryn
14
+ caches any reflections it generates to minimize the potential performance impact.
15
+
16
+ > auryn **is NOT** a Service Locator. DO NOT turn it into one by passing the injector into your
17
+ > application classes. Service Locator is an anti-pattern; it hides class dependencies, makes code
18
+ > more difficult to maintain and makes a liar of your API! You should *only* use an injector for
19
+ > wiring together the disparate parts of your application during your bootstrap phase.
20
+
21
+ ## The Guide
22
+
23
+ **Basic Usage**
24
+
25
+ * [Basic Instantiation](#basic-instantiation)
26
+ * [Injection Definitions](#injection-definitions)
27
+ * [Type-Hint Aliasing](#type-hint-aliasing)
28
+ * [Non-Class Parameters](#non-class-parameters)
29
+ * [Global Parameter Definitions](#global-parameter-definitions)
30
+
31
+ **Advanced Usage**
32
+
33
+ * [Instance Sharing](#instance-sharing)
34
+ * [Instantiation Delegates](#instantiation-delegates)
35
+ * [Prepares and Setter Injection](#prepares-and-setter-injection)
36
+ * [Injecting for Execution](#injecting-for-execution)
37
+ * [Dependency Resolution](#dependency-resolution)
38
+
39
+ **Example Use Cases**
40
+
41
+ * [Avoiding Evil Singletons](#avoiding-evil-singletons)
42
+ * [Application Bootstrapping](#app-bootstrapping)
43
+
44
+
45
+ ## Requirements and Installation
46
+
47
+ - auryn requires PHP 5.3 or higher.
48
+
49
+ #### Installation
50
+
51
+ ###### Github
52
+
53
+ You can clone the latest auryn iteration at anytime from the github repository:
54
+
55
+ ```bash
56
+ $ git clone git://github.com/rdlowrey/auryn.git
57
+ ```
58
+
59
+ ###### Composer
60
+
61
+ You may also use composer to include auryn as a dependency in your projects `composer.json`. The relevant package is `rdlowrey/auryn`.
62
+
63
+ Alternatively require the package using composer cli:
64
+
65
+ ```bash
66
+ composer require rdlowrey/auryn
67
+ ```
68
+
69
+ ##### Manual Download
70
+
71
+ Archived tagged release versions are also available for manual download on the project
72
+ [tags page](https://github.com/rdlowrey/auryn/tags)
73
+
74
+
75
+ ## Basic Usage
76
+
77
+ To start using the injector, simply create a new instance of the `Auryn\Injector` ("the Injector")
78
+ class:
79
+
80
+ ```php
81
+ <?php
82
+ $injector = new Auryn\Injector;
83
+ ```
84
+
85
+ ### Basic Instantiation
86
+
87
+ If a class doesn't specify any dependencies in its constructor signature there's little point in
88
+ using the Injector to generate it. However, for the sake of completeness consider that you can do
89
+ the following with equivalent results:
90
+
91
+ ```php
92
+ <?php
93
+ $injector = new Auryn\Injector;
94
+ $obj1 = new SomeNamespace\MyClass;
95
+ $obj2 = $injector->make('SomeNamespace\MyClass');
96
+
97
+ var_dump($obj2 instanceof SomeNamespace\MyClass); // true
98
+ ```
99
+
100
+ ###### Concrete Type-hinted Dependencies
101
+
102
+ If a class only asks for concrete dependencies you can use the Injector to inject them without
103
+ specifying any injection definitions. For example, in the following scenario you can use the
104
+ Injector to automatically provision `MyClass` with the required `SomeDependency` and `AnotherDependency`
105
+ class instances:
106
+
107
+ ```php
108
+ <?php
109
+ class SomeDependency {}
110
+
111
+ class AnotherDependency {}
112
+
113
+ class MyClass {
114
+ public $dep1;
115
+ public $dep2;
116
+ public function __construct(SomeDependency $dep1, AnotherDependency $dep2) {
117
+ $this->dep1 = $dep1;
118
+ $this->dep2 = $dep2;
119
+ }
120
+ }
121
+
122
+ $injector = new Auryn\Injector;
123
+ $myObj = $injector->make('MyClass');
124
+
125
+ var_dump($myObj->dep1 instanceof SomeDependency); // true
126
+ var_dump($myObj->dep2 instanceof AnotherDependency); // true
127
+ ```
128
+
129
+ ###### Recursive Dependency Instantiation
130
+
131
+ One of the Injector's key attributes is that it recursively traverses class dependency trees to
132
+ instantiate objects. This is just a fancy way of saying, "if you instantiate object A which asks for
133
+ object B, the Injector will instantiate any of object B's dependencies so that B can be instantiated
134
+ and provided to A". This is perhaps best understood with a simple example. Consider the following
135
+ classes in which a `Car` asks for `Engine` and the `Engine` class has concrete dependencies of its
136
+ own:
137
+
138
+ ```php
139
+ <?php
140
+ class Car {
141
+ private $engine;
142
+ public function __construct(Engine $engine) {
143
+ $this->engine = $engine;
144
+ }
145
+ }
146
+
147
+ class Engine {
148
+ private $sparkPlug;
149
+ private $piston;
150
+ public function __construct(SparkPlug $sparkPlug, Piston $piston) {
151
+ $this->sparkPlug = $sparkPlug;
152
+ $this->piston = $piston;
153
+ }
154
+ }
155
+
156
+ $injector = new Auryn\Injector;
157
+ $car = $injector->make('Car');
158
+ var_dump($car instanceof Car); // true
159
+ ```
160
+
161
+ ### Injection Definitions
162
+
163
+ You may have noticed that the previous examples all demonstrated instantiation of classes with
164
+ explicit, type-hinted, concrete constructor parameters. Obviously, many of your classes won't fit
165
+ this mold. Some classes will type-hint interfaces and abstract classes. Some will specify scalar
166
+ parameters which offer no possibility of type-hinting in PHP. Still other parameters will be arrays,
167
+ etc. In such cases we need to assist the Injector by telling it exactly what we want to inject.
168
+
169
+ ###### Defining Class Names for Constructor Parameters
170
+
171
+ Let's look at how to provision a class with non-concrete type-hints in its constructor signature.
172
+ Consider the following code in which a `Car` needs an `Engine` and `Engine` is an interface:
173
+
174
+ ```php
175
+ <?php
176
+ interface Engine {}
177
+
178
+ class V8 implements Engine {}
179
+
180
+ class Car {
181
+ private $engine;
182
+ public function __construct(Engine $engine) {
183
+ $this->engine = $engine;
184
+ }
185
+ }
186
+ ```
187
+
188
+ To instantiate a `Car` in this case, we simply need to define an injection definition for the class
189
+ ahead of time:
190
+
191
+ ```php
192
+ <?php
193
+ $injector = new Auryn\Injector;
194
+ $injector->define('Car', ['engine' => 'V8']);
195
+ $car = $injector->make('Car');
196
+
197
+ var_dump($car instanceof Car); // true
198
+ ```
199
+
200
+ The most important points to notice here are:
201
+
202
+ 1. A custom definition is an `array` whose keys match constructor parameter names
203
+ 2. The values in the definition array represent the class names to inject for the specified
204
+ parameter key
205
+
206
+ Because the `Car` constructor parameter we needed to define was named `$engine`, our definition
207
+ specified an `engine` key whose value was the name of the class (`V8`) that we want to inject.
208
+
209
+ Custom injection definitions are only necessary on a per-parameter basis. For example, in the
210
+ following class we only need to define the injectable class for `$arg2` because `$arg1` specifies a
211
+ concrete class type-hint:
212
+
213
+ ```php
214
+ <?php
215
+ class MyClass {
216
+ private $arg1;
217
+ private $arg2;
218
+ public function __construct(SomeConcreteClass $arg1, SomeInterface $arg2) {
219
+ $this->arg1 = $arg1;
220
+ $this->arg2 = $arg2;
221
+ }
222
+ }
223
+
224
+ $injector = new Auryn\Injector;
225
+ $injector->define('MyClass', ['arg2' => 'SomeImplementationClass']);
226
+
227
+ $myObj = $injector->make('MyClass');
228
+ ```
229
+
230
+ > **NOTE:** Injecting instances where an abstract class is type-hinted works in exactly the same way
231
+ as the above examples for interface type-hints.
232
+
233
+ ###### Using Existing Instances in Injection Definitions
234
+
235
+ Injection definitions may also specify a pre-existing instance of the requisite class instead of the
236
+ string class name:
237
+
238
+ ```php
239
+ <?php
240
+ interface SomeInterface {}
241
+
242
+ class SomeImplementation implements SomeInterface {}
243
+
244
+ class MyClass {
245
+ private $dependency;
246
+ public function __construct(SomeInterface $dependency) {
247
+ $this->dependency = $dependency;
248
+ }
249
+ }
250
+
251
+ $injector = new Auryn\Injector;
252
+ $dependencyInstance = new SomeImplementation;
253
+ $injector->define('MyClass', [':dependency' => $dependencyInstance]);
254
+
255
+ $myObj = $injector->make('MyClass');
256
+
257
+ var_dump($myObj instanceof MyClass); // true
258
+ ```
259
+
260
+ > **NOTE:** Since this `define()` call is passing raw values (as evidenced by the colon `:` usage),
261
+ you can achieve the same result by omitting the array key(s) and relying on parameter order rather
262
+ than name. Like so: `$injector->define('MyClass', [$dependencyInstance]);`
263
+
264
+ ###### Specifying Injection Definitions On the Fly
265
+
266
+ You may also specify injection definitions at call-time with `Auryn\Injector::make`. Consider:
267
+
268
+ ```php
269
+ <?php
270
+ interface SomeInterface {}
271
+
272
+ class SomeImplementationClass implements SomeInterface {}
273
+
274
+ class MyClass {
275
+ private $dependency;
276
+ public function __construct(SomeInterface $dependency) {
277
+ $this->dependency = $dependency;
278
+ }
279
+ }
280
+
281
+ $injector = new Auryn\Injector;
282
+ $myObj = $injector->make('MyClass', ['dependency' => 'SomeImplementationClass']);
283
+
284
+ var_dump($myObj instanceof MyClass); // true
285
+ ```
286
+
287
+ The above code shows how even though we haven't called the Injector's `define` method, the
288
+ call-time specification allows us to instantiate `MyClass`.
289
+
290
+ > **NOTE:** on-the-fly instantiation definitions will override a pre-defined definition for the
291
+ specified class, but only in the context of that particular call to `Auryn\Injector::make`.
292
+
293
+ ### Type-Hint Aliasing
294
+
295
+ Programming to interfaces is one of the most useful concepts in object-oriented design (OOD), and
296
+ well-designed code should type-hint interfaces whenever possible. But does this mean we have to
297
+ assign injection definitions for every class in our application to reap the benefits of abstracted
298
+ dependencies? Thankfully the answer to this question is, "NO." The Injector accommodates this goal
299
+ by accepting "aliases". Consider:
300
+
301
+ ```php
302
+ <?php
303
+ interface Engine {}
304
+ class V8 implements Engine {}
305
+ class Car {
306
+ private $engine;
307
+ public function __construct(Engine $engine) {
308
+ $this->engine = $engine;
309
+ }
310
+ }
311
+
312
+ $injector = new Auryn\Injector;
313
+
314
+ // Tell the Injector class to inject an instance of V8 any time
315
+ // it encounters an Engine type-hint
316
+ $injector->alias('Engine', 'V8');
317
+
318
+ $car = $injector->make('Car');
319
+ var_dump($car instanceof Car); // bool(true)
320
+ ```
321
+
322
+ In this example we've demonstrated how to specify an alias class for any occurrence of a particular
323
+ interface or abstract class type-hint. Once an implementation is assigned, the Injector will use it
324
+ to provision any parameter with a matching type-hint.
325
+
326
+ > **IMPORTANT:** If an injection definition is defined for a parameter covered by an implementation
327
+ assignment, the definition takes precedence over the implementation.
328
+
329
+ ### Non-Class Parameters
330
+
331
+ All of the previous examples have demonstrated how the Injector class instantiates parameters based
332
+ on type-hints, class name definitions and existing instances. But what happens if we want to inject
333
+ a scalar or other non-object variable into a class? First, let's establish the following behavioral
334
+ rule:
335
+
336
+ > **IMPORTANT:** The Injector assumes all named-parameter definitions are class names by default.
337
+
338
+ If you want the Injector to treat a named-parameter definition as a "raw" value and not a class name,
339
+ you must prefix the parameter name in your definition with a colon character `:`. For example,
340
+ consider the following code in which we tell the Injector to share a `PDO` database connection
341
+ instance and define its scalar constructor parameters:
342
+
343
+ ```php
344
+ <?php
345
+ $injector = new Auryn\Injector;
346
+ $injector->share('PDO');
347
+ $injector->define('PDO', [
348
+ ':dsn' => 'mysql:dbname=testdb;host=127.0.0.1',
349
+ ':username' => 'dbuser',
350
+ ':passwd' => 'dbpass'
351
+ ]);
352
+
353
+ $db = $injector->make('PDO');
354
+ ```
355
+
356
+ The colon character preceding the parameter names tells the Injector that the associated values ARE
357
+ NOT class names. If the colons had been omitted above, auryn would attempt to instantiate classes of
358
+ the names specified in the string and an exception would result. Also, note that we could just as
359
+ easily specified arrays or integers or any other data type in the above definitions. As long as the
360
+ parameter name is prefixed with a `:`, auryn will inject the value directly without attempting to
361
+ instantiate it.
362
+
363
+ > **NOTE:** As mentioned previously, since this `define()` call is passing raw values, you may opt to
364
+ assign the values by parameter order rather than name. Since PDO's first three parameters are `$dsn`,
365
+ `$username`, and `$password`, in that order, you could accomplish the same result by leaving out the
366
+ array keys, like so:
367
+ `$injector->define('PDO', ['mysql:dbname=testdb;host=127.0.0.1', 'dbuser', 'dbpass']);`
368
+
369
+ ### Global Parameter Definitions
370
+
371
+ Sometimes applications may reuse the same value everywhere. However, it can be a hassle to manually
372
+ specify definitions for this sort of thing everywhere it might be used in the app. auryn mitigates
373
+ this problem by exposing the `Injector::defineParam()` method. Consider the following example ...
374
+
375
+ ```php
376
+ <?php
377
+ $myUniversalValue = 42;
378
+
379
+ class MyClass {
380
+ public $myValue;
381
+ public function __construct($myValue) {
382
+ $this->myValue = $myValue;
383
+ }
384
+ }
385
+
386
+ $injector = new Auryn\Injector;
387
+ $injector->defineParam('myValue', $myUniversalValue);
388
+ $obj = $injector->make('MyClass');
389
+ var_dump($obj->myValue === 42); // bool(true)
390
+ ```
391
+
392
+ Because we specified a global definition for `myValue`, all parameters that are not in some other
393
+ way defined (as below) that match the specified parameter name are auto-filled with the global value.
394
+ If a parameter matches any of the following criteria the global value is not used:
395
+
396
+ - A typehint
397
+ - A predefined injection definition
398
+ - A custom call time definition
399
+
400
+
401
+ ## Advanced Usage
402
+
403
+ ### Instance Sharing
404
+
405
+ One of the more ubiquitous plagues in modern OOP is the Singleton anti-pattern. Coders looking to
406
+ limit classes to a single instance often fall into the trap of using `static` Singleton
407
+ implementations for things like configuration classes and database connections. While it's often
408
+ necessary to prevent multiple instances of a class, the Singleton method spells death to testability
409
+ and should generally be avoided. `Auryn\Injector` makes sharing class instances across contexts a
410
+ triviality while allowing maximum testability and API transparency.
411
+
412
+ Let's consider how a typical problem facing object-oriented web applications is easily solved by
413
+ wiring together your application using auryn. Here, we want to inject a single database connection
414
+ instance across multiple layers of an application. We have a controller class that asks for a
415
+ DataMapper that requires a `PDO` database connection instance:
416
+
417
+ ```php
418
+ <?php
419
+ class DataMapper {
420
+ private $pdo;
421
+ public function __construct(PDO $pdo) {
422
+ $this->pdo = $pdo;
423
+ }
424
+ }
425
+
426
+ class MyController {
427
+ private $mapper;
428
+ public function __construct(DataMapper $mapper) {
429
+ $this->mapper = $mapper;
430
+ }
431
+ }
432
+
433
+ $db = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
434
+
435
+ $injector = new Auryn\Injector;
436
+ $injector->share($db);
437
+
438
+ $myController = $injector->make('MyController');
439
+ ```
440
+
441
+ In the above code, the `DataMapper` instance will be provisioned with the same `PDO` database
442
+ connection instance we originally shared. This example is contrived and overly simple, but the
443
+ implication should be clear:
444
+
445
+ > By sharing an instance of a class, `Auryn\Injector` will always use that instance when
446
+ > provisioning classes that type-hint the shared class.
447
+
448
+ ###### A Simpler Example
449
+
450
+ Let's look at a simple proof of concept:
451
+
452
+ ```php
453
+ <?php
454
+ class Person {
455
+ public $name = 'John Snow';
456
+ }
457
+
458
+ $injector = new Auryn\Injector;
459
+ $injector->share('Person');
460
+
461
+ $person = $injector->make('Person');
462
+ var_dump($person->name); // John Snow
463
+
464
+ $person->name = 'Arya Stark';
465
+
466
+ $anotherPerson = $injector->make('Person');
467
+ var_dump($anotherPerson->name); // Arya Stark
468
+ var_dump($person === $anotherPerson); // bool(true) because it's the same instance!
469
+ ```
470
+
471
+ Defining an object as shared will store the provisioned instance in the Injector's shared cache and
472
+ all future requests to the provider for an injected instance of that class will return the
473
+ originally created object. Note that in the above code, we shared the class name (`Person`)
474
+ instead of an actual instance. Sharing works with either a class name or an instance of a class.
475
+ The difference is that when you specify a class name, the Injector
476
+ will cache the shared instance the first time it is asked to create it.
477
+
478
+ > **NOTE:** Once the Injector caches a shared instance, call-time definitions passed to
479
+ `Auryn\Injector::make` will have no effect. Once shared, an instance will always be returned for
480
+ instantiations of its type until the object is un-shared or refreshed:
481
+
482
+ ### Instantiation Delegates
483
+
484
+ Often factory classes/methods are used to prepare an object for use after instantiation. auryn
485
+ allows you to integrate factories and builders directly into the injection process by specifying
486
+ callable instantiation delegates on a per-class basis. Let's look at a very basic example to
487
+ demonstrate the concept of injection delegates:
488
+
489
+ ```php
490
+ <?php
491
+ class MyComplexClass {
492
+ public $verification = false;
493
+ public function doSomethingAfterInstantiation() {
494
+ $this->verification = true;
495
+ }
496
+ }
497
+
498
+ $complexClassFactory = function() {
499
+ $obj = new MyComplexClass;
500
+ $obj->doSomethingAfterInstantiation();
501
+
502
+ return $obj;
503
+ };
504
+
505
+ $injector = new Auryn\Injector;
506
+ $injector->delegate('MyComplexClass', $complexClassFactory);
507
+
508
+ $obj = $injector->make('MyComplexClass');
509
+ var_dump($obj->verification); // bool(true)
510
+ ```
511
+
512
+ In the above code we delegate instantiation of the `MyComplexClass` class to a closure,
513
+ `$complexClassFactory`. Once this delegation is made, the Injector will return the results of the
514
+ specified closure when asked to instantiate `MyComplexClass`.
515
+
516
+ ###### Available Delegate Types
517
+
518
+ Any valid PHP callable may be registered as a class instantiation delegate using
519
+ `Auryn\Injector::delegate`. Additionally you may specify the name of a delegate class that
520
+ specifies an `__invoke` method and it will be automatically provisioned and have its `__invoke`
521
+ method called at delegation time. Instance methods from uninstantiated classes may also be specified
522
+ using the `['NonStaticClassName', 'factoryMethod']` construction. For example:
523
+
524
+ ```php
525
+ <?php
526
+ class SomeClassWithDelegatedInstantiation {
527
+ public $value = 0;
528
+ }
529
+ class SomeFactoryDependency {}
530
+ class MyFactory {
531
+ private $dependency;
532
+ function __construct(SomeFactoryDependency $dep) {
533
+ $this->dependency = $dep;
534
+ }
535
+ function __invoke() {
536
+ $obj = new SomeClassWithDelegatedInstantiation;
537
+ $obj->value = 1;
538
+ return $obj;
539
+ }
540
+ function factoryMethod() {
541
+ $obj = new SomeClassWithDelegatedInstantiation;
542
+ $obj->value = 2;
543
+ return $obj;
544
+ }
545
+ }
546
+
547
+ // Works because MyFactory specifies a magic __invoke method
548
+ $injector->delegate('SomeClassWithDelegatedInstantiation', 'MyFactory');
549
+ $obj = $injector->make('SomeClassWithDelegatedInstantiation');
550
+ var_dump($obj->value); // int(1)
551
+
552
+ // This also works
553
+ $injector->delegate('SomeClassWithDelegatedInstantiation', 'MyFactory::factoryMethod');
554
+ $obj = $injector->make('SomeClassWithDelegatedInstantiation');
555
+ $obj = $injector->make('SomeClassWithDelegatedInstantiation');
556
+ var_dump($obj->value); // int(2)
557
+ ```
558
+
559
+ ### Prepares and Setter Injection
560
+
561
+ Constructor injection is almost always preferable to setter injection. However, some APIs require
562
+ additional post-instantiation mutations. auryn accommodates these use cases with its
563
+ `Injector::prepare()` method. Users may register any class or interface name for post-instantiation
564
+ modification. Consider:
565
+
566
+ ```php
567
+ <?php
568
+
569
+ class MyClass {
570
+ public $myProperty = 0;
571
+ }
572
+
573
+ $injector->prepare('MyClass', function($myObj, $injector) {
574
+ $myObj->myProperty = 42;
575
+ });
576
+
577
+ $myObj = $injector->make('MyClass');
578
+ var_dump($myObj->myProperty); // int(42)
579
+ ```
580
+
581
+ While the above example is contrived, the usefulness should be clear.
582
+
583
+
584
+ ### Injecting for Execution
585
+
586
+ In addition to provisioning class instances using constructors, auryn can also recursively instantiate
587
+ the parameters of any [valid PHP callable](http://php.net/manual/en/language.types.callable.php).
588
+ The following examples all work:
589
+
590
+ ```php
591
+ <?php
592
+ $injector = new Auryn\Injector;
593
+ $injector->execute(function(){});
594
+ $injector->execute([$objectInstance, 'methodName']);
595
+ $injector->execute('globalFunctionName');
596
+ $injector->execute('MyStaticClass::myStaticMethod');
597
+ $injector->execute(['MyStaticClass', 'myStaticMethod']);
598
+ $injector->execute(['MyChildStaticClass', 'parent::myStaticMethod']);
599
+ $injector->execute('ClassThatHasMagicInvoke');
600
+ $injector->execute($instanceOfClassThatHasMagicInvoke);
601
+ $injector->execute('MyClass::myInstanceMethod');
602
+ ```
603
+
604
+ Additionally, you can pass in the name of a class for a non-static method and the injector will
605
+ automatically provision an instance of the class (subject to any definitions or shared instances
606
+ already stored by the injector) before provisioning and invoking the specified method:
607
+
608
+ ```php
609
+ <?php
610
+ class Dependency {}
611
+ class AnotherDependency {}
612
+ class Example {
613
+ function __construct(Dependency $dep){}
614
+ function myMethod(AnotherDependency $arg1, $arg2) {
615
+ return $arg2;
616
+ }
617
+ }
618
+
619
+ $injector = new Auryn\Injector;
620
+
621
+ // outputs: int(42)
622
+ var_dump($injector->execute('Example::myMethod', $args = [':arg2' => 42]));
623
+ ```
624
+
625
+
626
+ ### Dependency Resolution
627
+
628
+ `Auryn\Injector` resolves dependencies in the following order:
629
+
630
+ 1. If a shared instance exists for the class in question, the shared instance will always be returned
631
+ 2. If a delegate callable is assigned for a class, its return result will always be used
632
+ 3. If a call-time definition is passed to `Auryn\Injector::make`, that definition will be used
633
+ 4. If a pre-defined definition exists, it will be used
634
+ 5. If a dependency is type-hinted, the Injector will recursively instantiate it subject to any implementations or definitions
635
+ 6. If no type-hint exists and the parameter has a default value, the default value is injected
636
+ 7. If a global parameter value is defined that value is used
637
+ 8. Throw an exception because you did something stupid
638
+
639
+ ## Example Use Cases
640
+
641
+ Dependency Injection Containers (DIC) are generally misunderstood in the PHP community. One of the
642
+ primary culprits is the misuse of such containers in the mainstream application frameworks. Often,
643
+ these frameworks warp their DICs into Service Locator anti-patterns. This is a shame because a
644
+ good DIC should be the exact opposite of a Service Locator.
645
+
646
+ ###### auryn Is NOT A Service Locator!
647
+
648
+ There's a galaxy of differences between using a DIC to wire together your application versus
649
+ passing the DIC as a dependency to your objects (Service Locator). Service Locator (SL) is an
650
+ anti-pattern -- it hides class dependencies, makes code difficult to maintain and makes a liar of
651
+ your API.
652
+
653
+ When you pass a SL into your constructors it makes it difficult to determine what the class dependencies
654
+ really are. A `House` object depends on `Door` and `Window` objects. A `House` object DOES NOT depend
655
+ on an instance of `ServiceLocator` regardless of whether the `ServiceLocator` can provide `Door` and
656
+ `Window` objects.
657
+
658
+ In real life you wouldn't build a house by transporting the entire hardware store (hopefully) to
659
+ the construction site so you can access any parts you need. Instead, the foreman (`__construct()`)
660
+ asks for the specific parts that will be needed (`Door` and `Window`) and goes about procuring them.
661
+ Your objects should function in the same way; they should ask only for the specific dependencies
662
+ required to do their jobs. Giving the `House` access to the entire hardware store is at best poor
663
+ OOP style and at worst a maintainability nightmare. The takeaway here is this:
664
+
665
+ > **IMPORTANT:** do not use auryn like a Service Locator!
666
+
667
+
668
+ ### Avoiding Evil Singletons
669
+
670
+ A common difficulty in web applications is limiting the number of database connection instances.
671
+ It's wasteful and slow to open up new connections each time we need to talk to a database.
672
+ Unfortunately, using singletons to limit these instances makes code brittle and hard to test. Let's
673
+ see how we can use auryn to inject the same `PDO` instance across the entire scope of our application.
674
+
675
+ Say we have a service class that requires two separate data mappers to persist information to a database:
676
+
677
+ ```php
678
+ <?php
679
+
680
+ class HouseMapper {
681
+ private $pdo;
682
+ public function __construct(PDO $pdo) {
683
+ $this->pdo = $pdo;
684
+ }
685
+ public function find($houseId) {
686
+ $query = 'SELECT * FROM houses WHERE houseId = :houseId';
687
+
688
+ $stmt = $this->pdo->prepare($query);
689
+ $stmt->bindValue(':houseId', $houseId);
690
+
691
+ $stmt->setFetchMode(PDO::FETCH_CLASS, 'Model\\Entities\\House');
692
+ $stmt->execute();
693
+ $house = $stmt->fetch(PDO::FETCH_CLASS);
694
+
695
+ if (false === $house) {
696
+ throw new RecordNotFoundException(
697
+ 'No houses exist for the specified ID'
698
+ );
699
+ }
700
+
701
+ return $house;
702
+ }
703
+
704
+ // more data mapper methods here ...
705
+ }
706
+
707
+ class PersonMapper {
708
+ private $pdo;
709
+ public function __construct(PDO $pdo) {
710
+ $this->pdo = $pdo;
711
+ }
712
+ // data mapper methods here
713
+ }
714
+
715
+ class SomeService {
716
+ private $houseMapper;
717
+ private $personMapper;
718
+ public function __construct(HouseMapper $hm, PersonMapper $pm) {
719
+ $this->houseMapper = $hm;
720
+ $this->personMapper = $pm;
721
+ }
722
+ public function doSomething() {
723
+ // do something with the mappers
724
+ }
725
+ }
726
+ ```
727
+
728
+ In our wiring/bootstrap code, we simply instantiate the `PDO` instance once and share it in the
729
+ context of the `Injector`:
730
+
731
+ ```php
732
+ <?php
733
+ $pdo = new PDO('sqlite:some_sqlite_file.db');
734
+ $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
735
+
736
+ $injector = new Auryn\Injector;
737
+
738
+ $injector->share($pdo);
739
+ $mapper = $injector->make('SomeService');
740
+ ```
741
+
742
+ In the above code, the DIC instantiates our service class. More importantly, the data mapper classes
743
+ it generates to do so are injected *with the same database connection instance we originally shared*.
744
+
745
+ Of course, we don't have to manually instantiate our `PDO` instance. We could just as easily seed
746
+ the container with a definition for how to create the `PDO` object and let it handle things for us:
747
+
748
+ ```php
749
+ <?php
750
+ $injector->define('PDO', [
751
+ ':dsn' => 'sqlite:some_sqlite_file.db'
752
+ ]);
753
+ $injector->share('PDO');
754
+ $service = $injector->make('SomeService');
755
+ ```
756
+
757
+ In the above code, the injector will pass the string definition as the `$dsn` argument in the
758
+ `PDO::__construct` method and generate the shared PDO instance automatically only if one of the
759
+ classes it instantiates requires a `PDO` instance!
760
+
761
+
762
+
763
+ ### App-Bootstrapping
764
+
765
+ DICs should be used to wire together the disparate objects of your application into a cohesive
766
+ functional unit (generally at the bootstrap or front-controller stage of the application). One such
767
+ usage provides an elegant solution for one of the thorny problems in object-oriented (OO) web
768
+ applications: how to instantiate classes in a routed environment where the dependencies are not
769
+ known ahead of time.
770
+
771
+ Consider the following front controller code whose job is to:
772
+
773
+ 1. Load a list of application routes and pass them to the router
774
+ 2. Generate a model of the client's HTTP request
775
+ 3. Route the request instance given the application's route list
776
+ 4. Instantiate the routed controller and invoke a method appropriate to the HTTP request
777
+
778
+ ```php
779
+ <?php
780
+
781
+ define('CONTROLLER_ROUTES', '/hard/path/to/routes.xml');
782
+
783
+ $routeLoader = new RouteLoader();
784
+ $routes = $routeLoader->loadFromXml(CONTROLLER_ROUTES);
785
+ $router = new Router($routes);
786
+
787
+ $requestDetector = new RequestDetector();
788
+ $request = $requestDetector->detectFromSuperglobal($_SERVER);
789
+
790
+ $requestUri = $request->getUri();
791
+ $requestMethod = strtolower($request->getMethod());
792
+
793
+ $injector = new Auryn\Injector;
794
+ $injector->share($request);
795
+
796
+ try {
797
+ if (!$controllerClass = $router->route($requestUri, $requestMethod)) {
798
+ throw new NoRouteMatchException();
799
+ }
800
+
801
+ $controller = $injector->make($controllerClass);
802
+ $callableController = array($controller, $requestMethod);
803
+
804
+ if (!is_callable($callableController)) {
805
+ throw new MethodNotAllowedException();
806
+ } else {
807
+ $callableController();
808
+ }
809
+
810
+ } catch (NoRouteMatchException $e) {
811
+ // send 404 response
812
+ } catch (MethodNotAllowedException $e) {
813
+ // send 405 response
814
+ } catch (Exception $e) {
815
+ // send 500 response
816
+ }
817
+ ```
818
+
819
+ And elsewhere we have various controller classes, each of which ask for their own individual
820
+ dependencies:
821
+
822
+ ```php
823
+ <?php
824
+
825
+ class WidgetController {
826
+ private $request;
827
+ private $mapper;
828
+ public function __construct(Request $request, WidgetDataMapper $mapper) {
829
+ $this->request = $request;
830
+ $this->mapper = $mapper;
831
+ }
832
+ public function get() {
833
+ // do something for HTTP GET requests
834
+ }
835
+ public function post() {
836
+ // do something for HTTP POST requests
837
+ }
838
+ }
839
+ ```
840
+
841
+ In the above example the auryn DIC allows us to write fully testable, fully OO controllers that ask
842
+ for their dependencies. Because the DIC recursively instantiates the dependencies of objects it
843
+ creates we have no need to pass around a Service Locator. Additionally, this example shows how we can
844
+ eliminate evil Singletons using the sharing capabilities of the auryn DIC. In the front controller
845
+ code, we share the request object so that any classes instantiated by the `Auryn\Injector` that ask
846
+ for a `Request` will receive the same instance. This feature not only helps eliminate Singletons,
847
+ but also the need for hard-to-test `static` properties.
addons/vendor/otgs/auryn/lib/CachingReflector.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class CachingReflector implements Reflector
6
+ {
7
+ const CACHE_KEY_CLASSES = 'auryn.refls.classes.';
8
+ const CACHE_KEY_CTORS = 'auryn.refls.ctors.';
9
+ const CACHE_KEY_CTOR_PARAMS = 'auryn.refls.ctor-params.';
10
+ const CACHE_KEY_FUNCS = 'auryn.refls.funcs.';
11
+ const CACHE_KEY_METHODS = 'auryn.refls.methods.';
12
+
13
+ private $reflector;
14
+ private $cache;
15
+
16
+ public function __construct(Reflector $reflector = null, ReflectionCache $cache = null)
17
+ {
18
+ $this->reflector = $reflector ?: new StandardReflector;
19
+ $this->cache = $cache ?: new ReflectionCacheArray;
20
+ }
21
+
22
+ public function getClass($class)
23
+ {
24
+ $cacheKey = self::CACHE_KEY_CLASSES . strtolower($class);
25
+
26
+ if (($reflectionClass = $this->cache->fetch($cacheKey)) === false) {
27
+ $this->cache->store($cacheKey, $reflectionClass = $this->reflector->getClass($class));
28
+ }
29
+
30
+ return $reflectionClass;
31
+ }
32
+
33
+ public function getCtor($class)
34
+ {
35
+ $cacheKey = self::CACHE_KEY_CTORS . strtolower($class);
36
+
37
+ if (($reflectedCtor = $this->cache->fetch($cacheKey)) === false) {
38
+ $this->cache->store($cacheKey, $reflectedCtor = $this->reflector->getCtor($class));
39
+ }
40
+
41
+ return $reflectedCtor;
42
+ }
43
+
44
+ public function getCtorParams($class)
45
+ {
46
+ $cacheKey = self::CACHE_KEY_CTOR_PARAMS . strtolower($class);
47
+
48
+ if (($reflectedCtorParams = $this->cache->fetch($cacheKey)) === false) {
49
+ $this->cache->store($cacheKey, $reflectedCtorParams = $this->reflector->getCtorParams($class));
50
+ }
51
+
52
+ return $reflectedCtorParams;
53
+ }
54
+
55
+ public function getParamTypeHint(\ReflectionFunctionAbstract $function, \ReflectionParameter $param)
56
+ {
57
+ $lowParam = strtolower($param->name);
58
+
59
+ if ($function instanceof \ReflectionMethod) {
60
+ $lowClass = strtolower($function->class);
61
+ $lowMethod = strtolower($function->name);
62
+ $paramCacheKey = self::CACHE_KEY_CLASSES . "{$lowClass}.{$lowMethod}.param-{$lowParam}";
63
+ } else {
64
+ $lowFunc = strtolower($function->name);
65
+ $paramCacheKey = (strpos($lowFunc, '{closure}') === false)
66
+ ? self::CACHE_KEY_FUNCS . ".{$lowFunc}.param-{$lowParam}"
67
+ : null;
68
+ }
69
+
70
+ $typeHint = ($paramCacheKey === null) ? false : $this->cache->fetch($paramCacheKey);
71
+
72
+ if (false === $typeHint) {
73
+ $typeHint = $this->reflector->getParamTypeHint($function, $param);
74
+ if ($paramCacheKey !== null) {
75
+ $this->cache->store($paramCacheKey, $typeHint);
76
+ }
77
+ }
78
+
79
+ return $typeHint;
80
+ }
81
+
82
+ public function getFunction($functionName)
83
+ {
84
+ $lowFunc = strtolower($functionName);
85
+ $cacheKey = self::CACHE_KEY_FUNCS . $lowFunc;
86
+
87
+ if (($reflectedFunc = $this->cache->fetch($cacheKey)) === false) {
88
+ $this->cache->store($cacheKey, $reflectedFunc = $this->reflector->getFunction($functionName));
89
+ }
90
+
91
+ return $reflectedFunc;
92
+ }
93
+
94
+ public function getMethod($classNameOrInstance, $methodName)
95
+ {
96
+ $className = is_string($classNameOrInstance)
97
+ ? $classNameOrInstance
98
+ : get_class($classNameOrInstance);
99
+
100
+ $cacheKey = self::CACHE_KEY_METHODS . strtolower($className) . '.' . strtolower($methodName);
101
+
102
+ if (($reflectedMethod = $this->cache->fetch($cacheKey)) === false) {
103
+ $this->cache->store($cacheKey, $reflectedMethod = $this->reflector->getMethod($classNameOrInstance, $methodName));
104
+ }
105
+
106
+ return $reflectedMethod;
107
+ }
108
+ }
addons/vendor/otgs/auryn/lib/ConfigException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class ConfigException extends InjectorException
6
+ {
7
+ }
addons/vendor/otgs/auryn/lib/Executable.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class Executable
6
+ {
7
+ private $callableReflection;
8
+ private $invocationObject;
9
+ private $isInstanceMethod;
10
+
11
+ public function __construct(\ReflectionFunctionAbstract $reflFunc, $invocationObject = null)
12
+ {
13
+ if ($reflFunc instanceof \ReflectionMethod) {
14
+ $this->isInstanceMethod = true;
15
+ $this->setMethodCallable($reflFunc, $invocationObject);
16
+ } else {
17
+ $this->isInstanceMethod = false;
18
+ $this->callableReflection = $reflFunc;
19
+ }
20
+ }
21
+
22
+ private function setMethodCallable(\ReflectionMethod $reflection, $invocationObject)
23
+ {
24
+ if (is_object($invocationObject)) {
25
+ $this->callableReflection = $reflection;
26
+ $this->invocationObject = $invocationObject;
27
+ } elseif ($reflection->isStatic()) {
28
+ $this->callableReflection = $reflection;
29
+ } else {
30
+ throw new \InvalidArgumentException(
31
+ 'ReflectionMethod callables must specify an invocation object'
32
+ );
33
+ }
34
+ }
35
+
36
+ public function __invoke()
37
+ {
38
+ $args = func_get_args();
39
+ $reflection = $this->callableReflection;
40
+
41
+ if ($this->isInstanceMethod) {
42
+ return $reflection->invokeArgs($this->invocationObject, $args);
43
+ }
44
+
45
+ return $this->callableReflection->isClosure()
46
+ ? $this->invokeClosureCompat($reflection, $args)
47
+ : $reflection->invokeArgs($args);
48
+ }
49
+
50
+ /**
51
+ * @TODO Remove this extra indirection when 5.3 support is dropped
52
+ */
53
+ private function invokeClosureCompat($reflection, $args)
54
+ {
55
+ if (version_compare(PHP_VERSION, '5.4.0') >= 0) {
56
+ $scope = $reflection->getClosureScopeClass();
57
+ $closure = \Closure::bind(
58
+ $reflection->getClosure(),
59
+ $reflection->getClosureThis(),
60
+ $scope ? $scope->name : null
61
+ );
62
+ return call_user_func_array($closure, $args);
63
+ } else {
64
+ return $reflection->invokeArgs($args);
65
+ }
66
+ }
67
+
68
+ public function getCallableReflection()
69
+ {
70
+ return $this->callableReflection;
71
+ }
72
+
73
+ public function getInvocationObject()
74
+ {
75
+ return $this->invocationObject;
76
+ }
77
+
78
+ public function isInstanceMethod()
79
+ {
80
+ return $this->isInstanceMethod;
81
+ }
82
+ }
addons/vendor/otgs/auryn/lib/InjectionException.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class InjectionException extends InjectorException
6
+ {
7
+ public $dependencyChain;
8
+
9
+ public function __construct(array $inProgressMakes, $message = "", $code = 0, \Exception $previous = null)
10
+ {
11
+ $this->dependencyChain = array_flip($inProgressMakes);
12
+ ksort($this->dependencyChain);
13
+
14
+ parent::__construct($message, $code, $previous);
15
+ }
16
+
17
+ /**
18
+ * Add a human readable version of the invalid callable to the standard 'invalid invokable' message.
19
+ */
20
+ public static function fromInvalidCallable(
21
+ array $inProgressMakes,
22
+ $callableOrMethodStr,
23
+ \Exception $previous = null
24
+ ) {
25
+ $callableString = null;
26
+
27
+ if (is_string($callableOrMethodStr)) {
28
+ $callableString .= $callableOrMethodStr;
29
+ } else if (is_array($callableOrMethodStr) &&
30
+ array_key_exists(0, $callableOrMethodStr) &&
31
+ array_key_exists(0, $callableOrMethodStr)) {
32
+ if (is_string($callableOrMethodStr[0]) && is_string($callableOrMethodStr[1])) {
33
+ $callableString .= $callableOrMethodStr[0].'::'.$callableOrMethodStr[1];
34
+ } else if (is_object($callableOrMethodStr[0]) && is_string($callableOrMethodStr[1])) {
35
+ $callableString .= sprintf(
36
+ "[object(%s), '%s']",
37
+ get_class($callableOrMethodStr[0]),
38
+ $callableOrMethodStr[1]
39
+ );
40
+ }
41
+ }
42
+
43
+ if ($callableString) {
44
+ // Prevent accidental usage of long strings from filling logs.
45
+ $callableString = substr($callableString, 0, 250);
46
+ $message = sprintf(
47
+ "%s. Invalid callable was '%s'",
48
+ Injector::M_INVOKABLE,
49
+ $callableString
50
+ );
51
+ } else {
52
+ $message = Injector::M_INVOKABLE;
53
+ }
54
+
55
+ return new self($inProgressMakes, $message, Injector::E_INVOKABLE, $previous);
56
+ }
57
+
58
+ /**
59
+ * Returns the hierarchy of dependencies that were being created when
60
+ * the exception occurred.
61
+ * @return array
62
+ */
63
+ public function getDependencyChain()
64
+ {
65
+ return $this->dependencyChain;
66
+ }
67
+ }
addons/vendor/otgs/auryn/lib/Injector.php ADDED
@@ -0,0 +1,757 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class Injector
6
+ {
7
+ const A_RAW = ':';
8
+ const A_DELEGATE = '+';
9
+ const A_DEFINE = '@';
10
+ const I_BINDINGS = 1;
11
+ const I_DELEGATES = 2;
12
+ const I_PREPARES = 4;
13
+ const I_ALIASES = 8;
14
+ const I_SHARES = 16;
15
+ const I_ALL = 31;
16
+
17
+ const E_NON_EMPTY_STRING_ALIAS = 1;
18
+ const M_NON_EMPTY_STRING_ALIAS = "Invalid alias: non-empty string required at arguments 1 and 2";
19
+ const E_SHARED_CANNOT_ALIAS = 2;
20
+ const M_SHARED_CANNOT_ALIAS = "Cannot alias class %s to %s because it is currently shared";
21
+ const E_SHARE_ARGUMENT = 3;
22
+ const M_SHARE_ARGUMENT = "%s::share() requires a string class name or object instance at Argument 1; %s specified";
23
+ const E_ALIASED_CANNOT_SHARE = 4;
24
+ const M_ALIASED_CANNOT_SHARE = "Cannot share class %s because it is currently aliased to %s";
25
+ const E_INVOKABLE = 5;
26
+ const M_INVOKABLE = "Invalid invokable: callable or provisional string required";
27
+ const E_NON_PUBLIC_CONSTRUCTOR = 6;
28
+ const M_NON_PUBLIC_CONSTRUCTOR = "Cannot instantiate protected/private constructor in class %s";
29
+ const E_NEEDS_DEFINITION = 7;
30
+ const M_NEEDS_DEFINITION = "Injection definition required for %s %s";
31
+ const E_MAKE_FAILURE = 8;
32
+ const M_MAKE_FAILURE = "Could not make %s: %s";
33
+ const E_UNDEFINED_PARAM = 9;
34
+ const M_UNDEFINED_PARAM = "No definition available to provision typeless parameter \$%s at position %d in %s()%s";
35
+ const E_DELEGATE_ARGUMENT = 10;
36
+ const M_DELEGATE_ARGUMENT = "%s::delegate expects a valid callable or executable class::method string at Argument 2%s";
37
+ const E_CYCLIC_DEPENDENCY = 11;
38
+ const M_CYCLIC_DEPENDENCY = "Detected a cyclic dependency while provisioning %s";
39
+ const E_MAKING_FAILED = 12;
40
+ const M_MAKING_FAILED = "Making %s did not result in an object, instead result is of type '%s'";
41
+
42
+ private $reflector;
43
+ private $classDefinitions = array();
44
+ private $paramDefinitions = array();
45
+ private $aliases = array();
46
+ private $shares = array();
47
+ private $prepares = array();
48
+ private $delegates = array();
49
+ private $inProgressMakes = array();
50
+
51
+ public function __construct(Reflector $reflector = null)
52
+ {
53
+ $this->reflector = $reflector ?: new CachingReflector;
54
+ }
55
+
56
+ public function __clone()
57
+ {
58
+ $this->inProgressMakes = array();
59
+ }
60
+
61
+ /**
62
+ * Define instantiation directives for the specified class
63
+ *
64
+ * @param string $name The class (or alias) whose constructor arguments we wish to define
65
+ * @param array $args An array mapping parameter names to values/instructions
66
+ * @return self
67
+ */
68
+ public function define($name, array $args)
69
+ {
70
+ list(, $normalizedName) = $this->resolveAlias($name);
71
+ $this->classDefinitions[$normalizedName] = $args;
72
+
73
+ return $this;
74
+ }
75
+
76
+ /**
77
+ * Assign a global default value for all parameters named $paramName
78
+ *
79
+ * Global parameter definitions are only used for parameters with no typehint, pre-defined or
80
+ * call-time definition.
81
+ *
82
+ * @param string $paramName The parameter name for which this value applies
83
+ * @param mixed $value The value to inject for this parameter name
84
+ * @return self
85
+ */
86
+ public function defineParam($paramName, $value)
87
+ {
88
+ $this->paramDefinitions[$paramName] = $value;
89
+
90
+ return $this;
91
+ }
92
+
93
+ /**
94
+ * Define an alias for all occurrences of a given typehint
95
+ *
96
+ * Use this method to specify implementation classes for interface and abstract class typehints.
97
+ *
98
+ * @param string $original The typehint to replace
99
+ * @param string $alias The implementation name
100
+ * @throws ConfigException if any argument is empty or not a string
101
+ * @return self
102
+ */
103
+ public function alias($original, $alias)
104
+ {
105
+ if (empty($original) || !is_string($original)) {
106
+ throw new ConfigException(
107
+ self::M_NON_EMPTY_STRING_ALIAS,
108
+ self::E_NON_EMPTY_STRING_ALIAS
109
+ );
110
+ }
111
+ if (empty($alias) || !is_string($alias)) {
112
+ throw new ConfigException(
113
+ self::M_NON_EMPTY_STRING_ALIAS,
114
+ self::E_NON_EMPTY_STRING_ALIAS
115
+ );
116
+ }
117
+
118
+ $originalNormalized = $this->normalizeName($original);
119
+
120
+ if (isset($this->shares[$originalNormalized])) {
121
+ throw new ConfigException(
122
+ sprintf(
123
+ self::M_SHARED_CANNOT_ALIAS,
124
+ $this->normalizeName(get_class($this->shares[$originalNormalized])),
125
+ $alias
126
+ ),
127
+ self::E_SHARED_CANNOT_ALIAS
128
+ );
129
+ }
130
+
131
+ if (array_key_exists($originalNormalized, $this->shares)) {
132
+ $aliasNormalized = $this->normalizeName($alias);
133
+ $this->shares[$aliasNormalized] = null;
134
+ unset($this->shares[$originalNormalized]);
135
+ }
136
+
137
+ $this->aliases[$originalNormalized] = $alias;
138
+
139
+ return $this;
140
+ }
141
+
142
+ private function normalizeName($className)
143
+ {
144
+ return ltrim(strtolower($className), '\\');
145
+ }
146
+
147
+ /**
148
+ * Share the specified class/instance across the Injector context
149
+ *
150
+ * @param mixed $nameOrInstance The class or object to share
151
+ * @throws ConfigException if $nameOrInstance is not a string or an object
152
+ * @return self
153
+ */
154
+ public function share($nameOrInstance)
155
+ {
156
+ if (is_string($nameOrInstance)) {
157
+ $this->shareClass($nameOrInstance);
158
+ } elseif (is_object($nameOrInstance)) {
159
+ $this->shareInstance($nameOrInstance);
160
+ } else {
161
+ throw new ConfigException(
162
+ sprintf(
163
+ self::M_SHARE_ARGUMENT,
164
+ __CLASS__,
165
+ gettype($nameOrInstance)
166
+ ),
167
+ self::E_SHARE_ARGUMENT
168
+ );
169
+ }
170
+
171
+ return $this;
172
+ }
173
+
174
+ private function shareClass($nameOrInstance)
175
+ {
176
+ list(, $normalizedName) = $this->resolveAlias($nameOrInstance);
177
+ $this->shares[$normalizedName] = isset($this->shares[$normalizedName])
178
+ ? $this->shares[$normalizedName]
179
+ : null;
180
+ }
181
+
182
+ private function resolveAlias($name)
183
+ {
184
+ $normalizedName = $this->normalizeName($name);
185
+ if (isset($this->aliases[$normalizedName])) {
186
+ $name = $this->aliases[$normalizedName];
187
+ $normalizedName = $this->normalizeName($name);
188
+ }
189
+
190
+ return array($name, $normalizedName);
191
+ }
192
+
193
+ private function shareInstance($obj)
194
+ {
195
+ $normalizedName = $this->normalizeName(get_class($obj));
196
+ if (isset($this->aliases[$normalizedName])) {
197
+ // You cannot share an instance of a class name that is already aliased
198
+ throw new ConfigException(
199
+ sprintf(
200
+ self::M_ALIASED_CANNOT_SHARE,
201
+ $normalizedName,
202
+ $this->aliases[$normalizedName]
203
+ ),
204
+ self::E_ALIASED_CANNOT_SHARE
205
+ );
206
+ }
207
+ $this->shares[$normalizedName] = $obj;
208
+ }
209
+
210
+ /**
211
+ * Register a prepare callable to modify/prepare objects of type $name after instantiation
212
+ *
213
+ * Any callable or provisionable invokable may be specified. Preparers are passed two
214
+ * arguments: the instantiated object to be mutated and the current Injector instance.
215
+ *
216
+ * @param string $name
217
+ * @param mixed $callableOrMethodStr Any callable or provisionable invokable method
218
+ * @throws InjectionException if $callableOrMethodStr is not a callable.
219
+ * See https://github.com/rdlowrey/auryn#injecting-for-execution
220
+ * @return self
221
+ */
222
+ public function prepare($name, $callableOrMethodStr)
223
+ {
224
+ if ($this->isExecutable($callableOrMethodStr) === false) {
225
+ throw InjectionException::fromInvalidCallable(
226
+ $this->inProgressMakes,
227
+ $callableOrMethodStr
228
+ );
229
+ }
230
+
231
+ list(, $normalizedName) = $this->resolveAlias($name);
232
+ $this->prepares[$normalizedName] = $callableOrMethodStr;
233
+
234
+ return $this;
235
+ }
236
+
237
+ private function isExecutable($exe)
238
+ {
239
+ if (is_callable($exe)) {
240
+ return true;
241
+ }
242
+ if (is_string($exe) && method_exists($exe, '__invoke')) {
243
+ return true;
244
+ }
245
+ if (is_array($exe) && isset($exe[0], $exe[1]) && method_exists($exe[0], $exe[1])) {
246
+ return true;
247
+ }
248
+
249
+ return false;
250
+ }
251
+
252
+ /**
253
+ * Delegate the creation of $name instances to the specified callable
254
+ *
255
+ * @param string $name
256
+ * @param mixed $callableOrMethodStr Any callable or provisionable invokable method
257
+ * @throws ConfigException if $callableOrMethodStr is not a callable.
258
+ * @return self
259
+ */
260
+ public function delegate($name, $callableOrMethodStr)
261
+ {
262
+ if ($this->isExecutable($callableOrMethodStr) === false) {
263
+ $errorDetail = '';
264
+ if (is_string($callableOrMethodStr)) {
265
+ $errorDetail = " but received '$callableOrMethodStr'";
266
+ } elseif (is_array($callableOrMethodStr) &&
267
+ count($callableOrMethodStr) === 2 &&
268
+ array_key_exists(0, $callableOrMethodStr) &&
269
+ array_key_exists(1, $callableOrMethodStr)
270
+ ) {
271
+ if (is_string($callableOrMethodStr[0]) && is_string($callableOrMethodStr[1])) {
272
+ $errorDetail = " but received ['".$callableOrMethodStr[0]."', '".$callableOrMethodStr[1]."']";
273
+ }
274
+ }
275
+ throw new ConfigException(
276
+ sprintf(self::M_DELEGATE_ARGUMENT, __CLASS__, $errorDetail),
277
+ self::E_DELEGATE_ARGUMENT
278
+ );
279
+ }
280
+ $normalizedName = $this->normalizeName($name);
281
+ $this->delegates[$normalizedName] = $callableOrMethodStr;
282
+
283
+ return $this;
284
+ }
285
+
286
+ /**
287
+ * Retrieve stored data for the specified definition type
288
+ *
289
+ * Exposes introspection of existing binds/delegates/shares/etc for decoration and composition.
290
+ *
291
+ * @param string $nameFilter An optional class name filter
292
+ * @param int $typeFilter A bitmask of Injector::* type constant flags
293
+ * @return array
294
+ */
295
+ public function inspect($nameFilter = null, $typeFilter = null)
296
+ {
297
+ $result = array();
298
+ $name = $nameFilter ? $this->normalizeName($nameFilter) : null;
299
+
300
+ if (empty($typeFilter)) {
301
+ $typeFilter = self::I_ALL;
302
+ }
303
+
304
+ $types = array(
305
+ self::I_BINDINGS => "classDefinitions",
306
+ self::I_DELEGATES => "delegates",
307
+ self::I_PREPARES => "prepares",
308
+ self::I_ALIASES => "aliases",
309
+ self::I_SHARES => "shares"
310
+ );
311
+
312
+ foreach ($types as $type => $source) {
313
+ if ($typeFilter & $type) {
314
+ $result[$type] = $this->filter($this->{$source}, $name);
315
+ }
316
+ }
317
+
318
+ return $result;
319
+ }
320
+
321
+ private function filter($source, $name)
322
+ {
323
+ if (empty($name)) {
324
+ return $source;
325
+ } elseif (array_key_exists($name, $source)) {
326
+ return array($name => $source[$name]);
327
+ } else {
328
+ return array();
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Instantiate/provision a class instance
334
+ *
335
+ * @param string $name
336
+ * @param array $args
337
+ * @throws InjectionException if a cyclic gets detected when provisioning
338
+ * @return mixed
339
+ */
340
+ public function make($name, array $args = array())
341
+ {
342
+ list($className, $normalizedClass) = $this->resolveAlias($name);
343
+
344
+ if (isset($this->inProgressMakes[$normalizedClass])) {
345
+ throw new InjectionException(
346
+ $this->inProgressMakes,
347
+ sprintf(
348
+ self::M_CYCLIC_DEPENDENCY,
349
+ $className
350
+ ),
351
+ self::E_CYCLIC_DEPENDENCY
352
+ );
353
+ }
354
+
355
+ $this->inProgressMakes[$normalizedClass] = count($this->inProgressMakes);
356
+
357
+ // isset() is used specifically here because classes may be marked as "shared" before an
358
+ // instance is stored. In these cases the class is "shared," but it has a null value and
359
+ // instantiation is needed.
360
+ if (isset($this->shares[$normalizedClass])) {
361
+ unset($this->inProgressMakes[$normalizedClass]);
362
+
363
+ return $this->shares[$normalizedClass];
364
+ }
365
+
366
+ try {
367
+ if (isset($this->delegates[$normalizedClass])) {
368
+ $executable = $this->buildExecutable($this->delegates[$normalizedClass]);
369
+ $reflectionFunction = $executable->getCallableReflection();
370
+ $args = $this->provisionFuncArgs($reflectionFunction, $args, null, $className);
371
+ $obj = call_user_func_array(array($executable, '__invoke'), $args);
372
+ } else {
373
+ $obj = $this->provisionInstance($className, $normalizedClass, $args);
374
+ }
375
+
376
+ $obj = $this->prepareInstance($obj, $normalizedClass);
377
+
378
+ if (array_key_exists($normalizedClass, $this->shares)) {
379
+ $this->shares[$normalizedClass] = $obj;
380
+ }
381
+
382
+ unset($this->inProgressMakes[$normalizedClass]);
383
+ }
384
+ catch (\Throwable $exception) {
385
+ unset($this->inProgressMakes[$normalizedClass]);
386
+ throw $exception;
387
+ }
388
+ catch (\Exception $exception) {
389
+ unset($this->inProgressMakes[$normalizedClass]);
390
+ throw $exception;
391
+ }
392
+
393
+ return $obj;
394
+ }
395
+
396
+ private function provisionInstance($className, $normalizedClass, array $definition)
397
+ {
398
+ try {
399
+ $ctor = $this->reflector->getCtor($className);
400
+
401
+ if (!$ctor) {
402
+ $obj = $this->instantiateWithoutCtorParams($className);
403
+ } elseif (!$ctor->isPublic()) {
404
+ throw new InjectionException(
405
+ $this->inProgressMakes,
406
+ sprintf(self::M_NON_PUBLIC_CONSTRUCTOR, $className),
407
+ self::E_NON_PUBLIC_CONSTRUCTOR
408
+ );
409
+ } elseif ($ctorParams = $this->reflector->getCtorParams($className)) {
410
+ $reflClass = $this->reflector->getClass($className);
411
+ $definition = isset($this->classDefinitions[$normalizedClass])
412
+ ? array_replace($this->classDefinitions[$normalizedClass], $definition)
413
+ : $definition;
414
+ $args = $this->provisionFuncArgs($ctor, $definition, $ctorParams, $className);
415
+ $obj = $reflClass->newInstanceArgs($args);
416
+ } else {
417
+ $obj = $this->instantiateWithoutCtorParams($className);
418
+ }
419
+
420
+ return $obj;
421
+ } catch (\ReflectionException $e) {
422
+ throw new InjectionException(
423
+ $this->inProgressMakes,
424
+ sprintf(self::M_MAKE_FAILURE, $className, $e->getMessage()),
425
+ self::E_MAKE_FAILURE,
426
+ $e
427
+ );
428
+ }
429
+ }
430
+
431
+ private function instantiateWithoutCtorParams($className)
432
+ {
433
+ $reflClass = $this->reflector->getClass($className);
434
+
435
+ if (!$reflClass->isInstantiable()) {
436
+ $type = $reflClass->isInterface() ? 'interface' : 'abstract class';
437
+ throw new InjectionException(
438
+ $this->inProgressMakes,
439
+ sprintf(self::M_NEEDS_DEFINITION, $type, $className),
440
+ self::E_NEEDS_DEFINITION
441
+ );
442
+ }
443
+
444
+ return new $className;
445
+ }
446
+
447
+ private function provisionFuncArgs(\ReflectionFunctionAbstract $reflFunc, array $definition, array $reflParams = null, $className = null)
448
+ {
449
+ $args = array();
450
+
451
+ // @TODO store this in ReflectionStorage
452
+ if (!isset($reflParams)) {
453
+ $reflParams = $reflFunc->getParameters();
454
+ }
455
+
456
+ foreach ($reflParams as $i => $reflParam) {
457
+ $name = $reflParam->name;
458
+
459
+ if (isset($definition[$i]) || array_key_exists($i, $definition)) {
460
+ // indexed arguments take precedence over named parameters
461
+ $arg = $definition[$i];
462
+ } elseif (isset($definition[$name]) || array_key_exists($name, $definition)) {
463
+ // interpret the param as a class name to be instantiated
464
+ $arg = $this->make($definition[$name]);
465
+ } elseif (($prefix = self::A_RAW . $name) && (isset($definition[$prefix]) || array_key_exists($prefix, $definition))) {
466
+ // interpret the param as a raw value to be injected
467
+ $arg = $definition[$prefix];
468
+ } elseif (($prefix = self::A_DELEGATE . $name) && isset($definition[$prefix])) {
469
+ // interpret the param as an invokable delegate
470
+ $arg = $this->buildArgFromDelegate($name, $definition[$prefix]);
471
+ } elseif (($prefix = self::A_DEFINE . $name) && isset($definition[$prefix])) {
472
+ // interpret the param as a class definition
473
+ $arg = $this->buildArgFromParamDefineArr($definition[$prefix]);
474
+ } elseif (!$arg = $this->buildArgFromTypeHint($reflFunc, $reflParam)) {
475
+ $arg = $this->buildArgFromReflParam($reflParam, $className);
476
+
477
+ if ($arg === null && PHP_VERSION_ID >= 50600 && $reflParam->isVariadic()) {
478
+ // buildArgFromReflParam might return null in case the parameter is optional
479
+ // in case of variadics, the parameter is optional, but null might not be allowed
480
+ continue;
481
+ }
482
+ }
483
+
484
+ $args[] = $arg;
485
+ }
486
+
487
+ return $args;
488
+ }
489
+
490
+ private function buildArgFromParamDefineArr($definition)
491
+ {
492
+ if (!is_array($definition)) {
493
+ throw new InjectionException(
494
+ $this->inProgressMakes
495
+ // @TODO Add message
496
+ );
497
+ }
498
+
499
+ if (!isset($definition[0], $definition[1])) {
500
+ throw new InjectionException(
501
+ $this->inProgressMakes
502
+ // @TODO Add message
503
+ );
504
+ }
505
+
506
+ list($class, $definition) = $definition;
507
+
508
+ return $this->make($class, $definition);
509
+ }
510
+
511
+ private function buildArgFromDelegate($paramName, $callableOrMethodStr)
512
+ {
513
+ if ($this->isExecutable($callableOrMethodStr) === false) {
514
+ throw InjectionException::fromInvalidCallable(
515
+ $this->inProgressMakes,
516
+ $callableOrMethodStr
517
+ );
518
+ }
519
+
520
+ $executable = $this->buildExecutable($callableOrMethodStr);
521
+
522
+ return $executable($paramName, $this);
523
+ }
524
+
525
+ private function buildArgFromTypeHint(\ReflectionFunctionAbstract $reflFunc, \ReflectionParameter $reflParam)
526
+ {
527
+ $typeHint = $this->reflector->getParamTypeHint($reflFunc, $reflParam);
528
+
529
+ if (!$typeHint) {
530
+ $obj = null;
531
+ } elseif ($reflParam->isDefaultValueAvailable()) {
532
+ $normalizedName = $this->normalizeName($typeHint);
533
+ // Injector has been told explicitly how to make this type
534
+ if (isset($this->aliases[$normalizedName]) ||
535
+ isset($this->delegates[$normalizedName]) ||
536
+ isset($this->shares[$normalizedName])) {
537
+ $obj = $this->make($typeHint);
538
+ } else {
539
+ $obj = $reflParam->getDefaultValue();
540
+ }
541
+ } else {
542
+ $obj = $this->make($typeHint);
543
+ }
544
+
545
+ return $obj;
546
+ }
547
+
548
+ private function buildArgFromReflParam(\ReflectionParameter $reflParam, $className = null)
549
+ {
550
+ if (array_key_exists($reflParam->name, $this->paramDefinitions)) {
551
+ $arg = $this->paramDefinitions[$reflParam->name];
552
+ } elseif ($reflParam->isDefaultValueAvailable()) {
553
+ $arg = $reflParam->getDefaultValue();
554
+ } elseif ($reflParam->isOptional()) {
555
+ // This branch is required to work around PHP bugs where a parameter is optional
556
+ // but has no default value available through reflection. Specifically, PDO exhibits
557
+ // this behavior.
558
+ $arg = null;
559
+ } else {
560
+ $reflFunc = $reflParam->getDeclaringFunction();
561
+ $classDeclare = ($reflFunc instanceof \ReflectionMethod)
562
+ ? " declared in " . $reflFunc->getDeclaringClass()->name . "::"
563
+ : "";
564
+ $classWord = ($reflFunc instanceof \ReflectionMethod)
565
+ ? $className . '::'
566
+ : '';
567
+ $funcWord = $classWord . $reflFunc->name;
568
+
569
+ throw new InjectionException(
570
+ $this->inProgressMakes,
571
+ sprintf(
572
+ self::M_UNDEFINED_PARAM,
573
+ $reflParam->name,
574
+ $reflParam->getPosition(),
575
+ $funcWord,
576
+ $classDeclare
577
+ ),
578
+ self::E_UNDEFINED_PARAM
579
+ );
580
+ }
581
+
582
+ return $arg;
583
+ }
584
+
585
+ private function prepareInstance($obj, $normalizedClass)
586
+ {
587
+ if (isset($this->prepares[$normalizedClass])) {
588
+ $prepare = $this->prepares[$normalizedClass];
589
+ $executable = $this->buildExecutable($prepare);
590
+ $result = $executable($obj, $this);
591
+ if ($result instanceof $normalizedClass) {
592
+ $obj = $result;
593
+ }
594
+ }
595
+
596
+ $interfaces = @class_implements($obj);
597
+
598
+ if ($interfaces === false) {
599
+ throw new InjectionException(
600
+ $this->inProgressMakes,
601
+ sprintf(
602
+ self::M_MAKING_FAILED,
603
+ $normalizedClass,
604
+ gettype($obj)
605
+ ),
606
+ self::E_MAKING_FAILED
607
+ );
608
+ }
609
+
610
+ if (empty($interfaces)) {
611
+ return $obj;
612
+ }
613
+
614
+ $interfaces = array_flip(array_map(array($this, 'normalizeName'), $interfaces));
615
+ $prepares = array_intersect_key($this->prepares, $interfaces);
616
+ foreach ($prepares as $interfaceName => $prepare) {
617
+ $executable = $this->buildExecutable($prepare);
618
+ $result = $executable($obj, $this);
619
+ if ($result instanceof $normalizedClass) {
620
+ $obj = $result;
621
+ }
622
+ }
623
+
624
+ return $obj;
625
+ }
626
+
627
+ /**
628
+ * Invoke the specified callable or class::method string, provisioning dependencies along the way
629
+ *
630
+ * @param mixed $callableOrMethodStr A valid PHP callable or a provisionable ClassName::methodName string
631
+ * @param array $args Optional array specifying params with which to invoke the provisioned callable
632
+ * @throws \Auryn\InjectionException
633
+ * @return mixed Returns the invocation result returned from calling the generated executable
634
+ */
635
+ public function execute($callableOrMethodStr, array $args = array())
636
+ {
637
+ list($reflFunc, $invocationObj) = $this->buildExecutableStruct($callableOrMethodStr);
638
+ $executable = new Executable($reflFunc, $invocationObj);
639
+ $args = $this->provisionFuncArgs($reflFunc, $args, null, $invocationObj === null ? null : get_class($invocationObj));
640
+
641
+ return call_user_func_array(array($executable, '__invoke'), $args);
642
+ }
643
+
644
+ /**
645
+ * Provision an Executable instance from any valid callable or class::method string
646
+ *
647
+ * @param mixed $callableOrMethodStr A valid PHP callable or a provisionable ClassName::methodName string
648
+ * @return \Auryn\Executable
649
+ */
650
+ public function buildExecutable($callableOrMethodStr)
651
+ {
652
+ try {
653
+ list($reflFunc, $invocationObj) = $this->buildExecutableStruct($callableOrMethodStr);
654
+ } catch (\ReflectionException $e) {
655
+ throw InjectionException::fromInvalidCallable(
656
+ $this->inProgressMakes,
657
+ $callableOrMethodStr,
658
+ $e
659
+ );
660
+ }
661
+
662
+ return new Executable($reflFunc, $invocationObj);
663
+ }
664
+
665
+ private function buildExecutableStruct($callableOrMethodStr)
666
+ {
667
+ if (is_string($callableOrMethodStr)) {
668
+ $executableStruct = $this->buildExecutableStructFromString($callableOrMethodStr);
669
+ } elseif ($callableOrMethodStr instanceof \Closure) {
670
+ $callableRefl = new \ReflectionFunction($callableOrMethodStr);
671
+ $executableStruct = array($callableRefl, null);
672
+ } elseif (is_object($callableOrMethodStr) && is_callable($callableOrMethodStr)) {
673
+ $invocationObj = $callableOrMethodStr;
674
+ $callableRefl = $this->reflector->getMethod($invocationObj, '__invoke');
675
+ $executableStruct = array($callableRefl, $invocationObj);
676
+ } elseif (is_array($callableOrMethodStr)
677
+ && isset($callableOrMethodStr[0], $callableOrMethodStr[1])
678
+ && count($callableOrMethodStr) === 2
679
+ ) {
680
+ $executableStruct = $this->buildExecutableStructFromArray($callableOrMethodStr);
681
+ } else {
682
+ throw InjectionException::fromInvalidCallable(
683
+ $this->inProgressMakes,
684
+ $callableOrMethodStr
685
+ );
686
+ }
687
+
688
+ return $executableStruct;
689
+ }
690
+
691
+ private function buildExecutableStructFromString($stringExecutable)
692
+ {
693
+ if (function_exists($stringExecutable)) {
694
+ $callableRefl = $this->reflector->getFunction($stringExecutable);
695
+ $executableStruct = array($callableRefl, null);
696
+ } elseif (method_exists($stringExecutable, '__invoke')) {
697
+ $invocationObj = $this->make($stringExecutable);
698
+ $callableRefl = $this->reflector->getMethod($invocationObj, '__invoke');
699
+ $executableStruct = array($callableRefl, $invocationObj);
700
+ } elseif (strpos($stringExecutable, '::') !== false) {
701
+ list($class, $method) = explode('::', $stringExecutable, 2);
702
+ $executableStruct = $this->buildStringClassMethodCallable($class, $method);
703
+ } else {
704
+ throw InjectionException::fromInvalidCallable(
705
+ $this->inProgressMakes,
706
+ $stringExecutable
707
+ );
708
+ }
709
+
710
+ return $executableStruct;
711
+ }
712
+
713
+ private function buildStringClassMethodCallable($class, $method)
714
+ {
715
+ $relativeStaticMethodStartPos = strpos($method, 'parent::');
716
+
717
+ if ($relativeStaticMethodStartPos === 0) {
718
+ $childReflection = $this->reflector->getClass($class);
719
+ $class = $childReflection->getParentClass()->name;
720
+ $method = substr($method, $relativeStaticMethodStartPos + 8);
721
+ }
722
+
723
+ list($className, $normalizedClass) = $this->resolveAlias($class);
724
+ $reflectionMethod = $this->reflector->getMethod($className, $method);
725
+
726
+ if ($reflectionMethod->isStatic()) {
727
+ return array($reflectionMethod, null);
728
+ }
729
+
730
+ $instance = $this->make($className);
731
+ // If the class was delegated, the instance may not be of the type
732
+ // $class but some other type. We need to get the reflection on the
733
+ // actual class to be able to call the method correctly.
734
+ $reflectionMethod = $this->reflector->getMethod($instance, $method);
735
+
736
+ return array($reflectionMethod, $instance);
737
+ }
738
+
739
+ private function buildExecutableStructFromArray($arrayExecutable)
740
+ {
741
+ list($classOrObj, $method) = $arrayExecutable;
742
+
743
+ if (is_object($classOrObj) && method_exists($classOrObj, $method)) {
744
+ $callableRefl = $this->reflector->getMethod($classOrObj, $method);
745
+ $executableStruct = array($callableRefl, $classOrObj);
746
+ } elseif (is_string($classOrObj)) {
747
+ $executableStruct = $this->buildStringClassMethodCallable($classOrObj, $method);
748
+ } else {
749
+ throw InjectionException::fromInvalidCallable(
750
+ $this->inProgressMakes,
751
+ $arrayExecutable
752
+ );
753
+ }
754
+
755
+ return $executableStruct;
756
+ }
757
+ }
addons/vendor/otgs/auryn/lib/InjectorException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class InjectorException extends \Exception
6
+ {
7
+ }
addons/vendor/otgs/auryn/lib/ReflectionCache.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ interface ReflectionCache
6
+ {
7
+ public function fetch($key);
8
+ public function store($key, $data);
9
+ }
addons/vendor/otgs/auryn/lib/ReflectionCacheApc.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class ReflectionCacheApc implements ReflectionCache
6
+ {
7
+ private $localCache;
8
+ private $timeToLive = 5;
9
+
10
+ public function __construct(ReflectionCache $localCache = null)
11
+ {
12
+ $this->localCache = $localCache ?: new ReflectionCacheArray;
13
+ }
14
+
15
+ public function setTimeToLive($seconds)
16
+ {
17
+ $seconds = (int) $seconds;
18
+ $this->timeToLive = ($seconds > 0) ? $seconds : $this->timeToLive;
19
+
20
+ return $this;
21
+ }
22
+
23
+ public function fetch($key)
24
+ {
25
+ $localData = $this->localCache->fetch($key);
26
+
27
+ if ($localData != false) {
28
+ return $localData;
29
+ } else {
30
+ $success = null; // stupid by-ref parameter that scrutinizer complains about
31
+ $data = apc_fetch($key, $success);
32
+ return $success ? $data : false;
33
+ }
34
+ }
35
+
36
+ public function store($key, $data)
37
+ {
38
+ $this->localCache->store($key, $data);
39
+ apc_store($key, $data, $this->timeToLive);
40
+ }
41
+ }
addons/vendor/otgs/auryn/lib/ReflectionCacheArray.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class ReflectionCacheArray implements ReflectionCache
6
+ {
7
+ private $cache = array();
8
+
9
+ public function fetch($key)
10
+ {
11
+ // The additional isset() check here improves performance but we also
12
+ // need array_key_exists() because some cached values === NULL.
13
+ return (isset($this->cache[$key]) || array_key_exists($key, $this->cache))
14
+ ? $this->cache[$key]
15
+ : false;
16
+ }
17
+
18
+ public function store($key, $data)
19
+ {
20
+ $this->cache[$key] = $data;
21
+ }
22
+ }
addons/vendor/otgs/auryn/lib/Reflector.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ interface Reflector
6
+ {
7
+ /**
8
+ * Retrieves ReflectionClass instances, caching them for future retrieval
9
+ *
10
+ * @param string $class
11
+ * @return \ReflectionClass
12
+ */
13
+ public function getClass($class);
14
+
15
+ /**
16
+ * Retrieves and caches the constructor (ReflectionMethod) for the specified class
17
+ *
18
+ * @param string $class
19
+ * @return \ReflectionMethod
20
+ */
21
+ public function getCtor($class);
22
+
23
+ /**
24
+ * Retrieves and caches an array of constructor parameters for the given class
25
+ *
26
+ * @param string $class
27
+ * @return \ReflectionParameter[]
28
+ */
29
+ public function getCtorParams($class);
30
+
31
+ /**
32
+ * Retrieves the class type-hint from a given ReflectionParameter
33
+ *
34
+ * There is no way to directly access a parameter's type-hint without
35
+ * instantiating a new ReflectionClass instance and calling its getName()
36
+ * method. This method stores the results of this approach so that if
37
+ * the same parameter type-hint or ReflectionClass is needed again we
38
+ * already have it cached.
39
+ *
40
+ * @param \ReflectionFunctionAbstract $function
41
+ * @param \ReflectionParameter $param
42
+ */
43
+ public function getParamTypeHint(\ReflectionFunctionAbstract $function, \ReflectionParameter $param);
44
+
45
+ /**
46
+ * Retrieves and caches a reflection for the specified function
47
+ *
48
+ * @param string $functionName
49
+ * @return \ReflectionFunction
50
+ */
51
+ public function getFunction($functionName);
52
+
53
+ /**
54
+ * Retrieves and caches a reflection for the specified class method
55
+ *
56
+ * @param mixed $classNameOrInstance
57
+ * @param string $methodName
58
+ * @return \ReflectionMethod
59
+ */
60
+ public function getMethod($classNameOrInstance, $methodName);
61
+ }
addons/vendor/otgs/auryn/lib/StandardReflector.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Auryn;
4
+
5
+ class StandardReflector implements Reflector
6
+ {
7
+ public function getClass($class)
8
+ {
9
+ return new \ReflectionClass($class);
10
+ }
11
+
12
+ public function getCtor($class)
13
+ {
14
+ $reflectionClass = new \ReflectionClass($class);
15
+
16
+ return $reflectionClass->getConstructor();
17
+ }
18
+
19
+ public function getCtorParams($class)
20
+ {
21
+ return ($reflectedCtor = $this->getCtor($class))
22
+ ? $reflectedCtor->getParameters()
23
+ : null;
24
+ }
25
+
26
+ public function getParamTypeHint( \ReflectionFunctionAbstract $function, \ReflectionParameter $param ) {
27
+ if ( version_compare( '7.1.0', phpversion(), '<' ) ) {
28
+ $reflectionClass = $param->getType() && ! $param->getType()->isBuiltin()
29
+ ? new \ReflectionClass( $param->getType()->getName() )
30
+ : null;
31
+ } else {
32
+ $reflectionClass = $param->getClass();
33
+ }
34
+
35
+ return ( $reflectionClass )
36
+ ? $reflectionClass->getName()
37
+ : null;
38
+ }
39
+
40
+ public function getFunction($functionName)
41
+ {
42
+ return new \ReflectionFunction($functionName);
43
+ }
44
+
45
+ public function getMethod($classNameOrInstance, $methodName)
46
+ {
47
+ $className = is_string($classNameOrInstance)
48
+ ? $classNameOrInstance
49
+ : get_class($classNameOrInstance);
50
+
51
+ return new \ReflectionMethod($className, $methodName);
52
+ }
53
+ }
addons/vendor/otgs/auryn/phpunit.xml ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <phpunit backupGlobals="false"
2
+ backupStaticAttributes="false"
3
+ colors="true"
4
+ convertErrorsToExceptions="true"
5
+ convertNoticesToExceptions="true"
6
+ convertWarningsToExceptions="true"
7
+ processIsolation="false"
8
+ stopOnFailure="false"
9
+ syntaxCheck="false"
10
+ bootstrap="vendor/autoload.php"
11
+ >
12
+ <testsuites>
13
+ <testsuite name="Unit-Tests">
14
+ <directory>./test</directory>
15
+ </testsuite>
16
+ </testsuites>
17
+ <filter>
18
+ <whitelist addUncoveredFilesFromWhitelist="true">
19
+ <directory>./lib</directory>
20
+ </whitelist>
21
+ </filter>
22
+
23
+ <logging>
24
+ <log
25
+ type="coverage-text"
26
+ target="php://stdout"
27
+ lowUpperBound="35"
28
+ highLowerBound="75"
29
+ />
30
+ <!-- uncomment below to generate HTML code coverage reports in ./test/coverage -->
31
+ <!--
32
+ <log
33
+ type="coverage-html"
34
+ target="./test/coverage"
35
+ charset="UTF-8"
36
+ yui="true"
37
+ lowUpperBound="35"
38
+ highLowerBound="70"
39
+ showUncoveredFiles="true"
40
+ />
41
+ -->
42
+ </logging>
43
+ </phpunit>
addons/vendor/otgs/icons ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit 4dbce75c1ba493c7d4d2c86f318d2ad10fa4f24b
addons/vendor/otgs/ui ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit d8b11b073ba3247f25108b0dd88742ca3b0d4628
addons/vendor/wpml/collect/collect-logo.png ADDED
Binary file
addons/vendor/wpml/collect/phpunit.xml ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <phpunit backupGlobals="false"
3
+ backupStaticAttributes="false"
4
+ bootstrap="tests/bootstrap.php"
5
+ colors="true"
6
+ convertErrorsToExceptions="true"
7
+ convertNoticesToExceptions="true"
8
+ convertWarningsToExceptions="true"
9
+ processIsolation="false"
10
+ stopOnError="false"
11
+ stopOnFailure="false"
12
+ syntaxCheck="true"
13
+ verbose="true"
14
+ >
15
+ <testsuites>
16
+ <testsuite name="Laravel Test Suite">
17
+ <directory suffix="Test.php">./tests</directory>
18
+ </testsuite>
19
+ </testsuites>
20
+ </phpunit>
addons/vendor/wpml/collect/readme.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![Codeship Status for tightenco/collect](https://codeship.com/projects/7a88b780-04ee-0134-0d48-3e31f9e0f6b8/status?branch=master)](https://codeship.com/projects/154325)
2
+
3
+ ![](https://raw.githubusercontent.com/tightenco/collect/master/collect-logo.png)
4
+
5
+ # Collect - Illuminate Collections
6
+
7
+ Import [Laravel's Collections](https://laravel.com/docs/collections) into non-Laravel packages easily, without needing to require the entire `Illuminate\Support` package. ([Why not pull `Illuminate\Support` in framework-agnostic packages](https://yuloh.github.io/2016/dont-use-illuminate-support/))
8
+
9
+ Written by Taylor Otwell as a part of Laravel's [Illuminate/Support](https://github.com/illuminate/support) package, Collect is just the code from Support needed in order to use Collections on their own.
10
+
11
+ Lovingly split by Matt Stauffer for [Tighten Co.](http://tighten.co/), with a kick in the butt to finally do it from [@assertchris](https://github.com/assertchris).
12
+
13
+ ## FAQ
14
+ - **Will this develop independently from Illuminate's Collections?**
15
+ No. Right now it's split manually, but the goal is for it shortly to be split automatically to keep it in sync with Laravel's Collections, even mirroring the release numbers.
16
+ - **Why isn't this just under the Illuminate namespace?**
17
+ Because that would require adding a lot of complexity and duplication to Illuminate\Support's internal structure. One day Taylor may choose to do that, but right now he hasn't and doesn't have any immediate plans to do so. If he does, we'll deprecate this package and point to the core version.
18
+ - **Why not just use an array?**
19
+ What a great question. [Tightenite Adam Wathan has a book about that.](http://adamwathan.me/refactoring-to-collections/)
addons/vendor/wpml/collect/src/Illuminate/Contracts/Support/Arrayable.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Collect\Contracts\Support;
4
+
5
+ interface Arrayable
6
+ {
7
+ /**
8
+ * Get the instance as an array.
9
+ *
10
+ * @return array
11
+ */
12
+ public function toArray();
13
+ }
addons/vendor/wpml/collect/src/Illuminate/Contracts/Support/Jsonable.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Collect\Contracts\Support;
4
+
5
+ interface Jsonable
6
+ {
7
+ /**
8
+ * Convert the object to its JSON representation.
9
+ *
10
+ * @param int $options
11
+ * @return string
12
+ */
13
+ public function toJson($options = 0);
14
+ }
addons/vendor/wpml/collect/src/Illuminate/Support/Arr.php ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Collect\Support;
4
+
5
+ use ArrayAccess;
6
+ use WPML\Collect\Support\Traits\Macroable;
7
+
8
+ class Arr
9
+ {
10
+ use Macroable;
11
+
12
+ /**
13
+ * Determine whether the given value is array accessible.
14
+ *
15
+ * @param mixed $value
16
+ * @return bool
17
+ */
18
+ public static function accessible($value)
19
+ {
20
+ return is_array($value) || $value instanceof ArrayAccess;
21
+ }
22
+
23
+ /**
24
+ * Add an element to an array using "dot" notation if it doesn't exist.
25
+ *
26
+ * @param mixed[] $array
27
+ * @param string $key
28
+ * @param mixed $value
29
+ * @return mixed[]
30
+ */
31
+ public static function add($array, $key, $value)
32
+ {
33
+ if (is_null(static::get($array, $key))) {
34
+ static::set($array, $key, $value);
35
+ }
36
+
37
+ return $array;
38
+ }
39
+
40
+ /**
41
+ * Collapse an array of arrays into a single array.
42
+ *
43
+ * @param mixed[] $array
44
+ * @return mixed[]
45
+ */
46
+ public static function collapse($array)
47
+ {
48
+ $results = [];
49
+
50
+ foreach ($array as $values) {
51
+ if ($values instanceof Collection) {
52
+ $values = $values->all();
53
+ } elseif (! is_array($values)) {
54
+ continue;
55
+ }
56
+
57
+ $results = array_merge($results, $values);
58
+ }
59
+
60
+ return $results;
61
+ }
62
+
63
+ /**
64
+ * Divide an array into two arrays. One with keys and the other with values.
65
+ *
66
+ * @param mixed[] $array
67
+ * @return mixed[]
68
+ */
69
+ public static function divide($array)
70
+ {
71
+ return [array_keys($array), array_values($array)];
72
+ }
73
+
74
+ /**
75
+ * Flatten a multi-dimensional associative array with dots.
76
+ *
77
+ * @param mixed[] $array
78
+ * @param string $prepend
79
+ * @return mixed[]
80
+ */
81
+ public static function dot($array, $prepend = '')
82
+ {
83
+ $results = [];
84
+
85
+ foreach ($array as $key => $value) {
86
+ if (is_array($value) && ! empty($value)) {
87
+ $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
88
+ } else {
89
+ $results[$prepend.$key] = $value;
90
+ }
91
+ }
92
+
93
+ return $results;
94
+ }
95
+
96
+ /**
97
+ * Get all of the given array except for a specified array of items.
98
+ *
99
+ * @param mixed[] $array
100
+ * @param mixed[]|string $keys
101
+ * @return mixed[]
102
+ */
103
+ public static function except($array, $keys)
104
+ {
105
+ static::forget($array, $keys);
106
+
107
+ return $array;
108
+ }
109
+
110
+ /**
111
+ * Determine if the given key exists in the provided array.
112
+ *
113
+ * @param \ArrayAccess<mixed>|mixed[] $array
114
+ * @param string|int $key
115
+ * @return bool
116
+ */
117
+ public static function exists($array, $key)
118
+ {
119
+ if ($array instanceof ArrayAccess) {
120
+ return $array->offsetExists($key);
121
+ }
122
+
123
+ return array_key_exists($key, $array);
124
+ }
125
+
126
+ /**
127
+ * Return the first element in an array passing a given truth test.
128
+ *
129
+ * @param mixed[] $array
130
+ * @param callable|null $callback
131
+ * @param mixed $default
132
+ * @return mixed
133
+ */
134
+ public static function first($array, callable $callback = null, $default = null)
135
+ {
136
+ if (is_null($callback)) {
137
+ if (empty($array)) {
138
+ return value($default);
139
+ }
140
+
141
+ foreach ($array as $item) {
142
+ return $item;
143
+ }
144
+ }
145
+
146
+ foreach ($array as $key => $value) {
147
+ if (call_user_func($callback, $value, $key)) {
148
+ return $value;
149
+ }
150
+ }
151
+
152
+ return value($default);
153
+ }
154
+
155
+ /**
156
+ * Return the last element in an array passing a given truth test.
157
+ *
158
+ * @param mixed[] $array
159
+ * @param callable|null $callback
160
+ * @param mixed $default
161
+ * @return mixed
162
+ */
163
+ public static function last($array, callable $callback = null, $default = null)
164
+ {
165
+ if (is_null($callback)) {
166
+ return empty($array) ? value($default) : end($array);
167
+ }
168
+
169
+ return static::first(array_reverse($array, true), $callback, $default);
170
+ }
171
+
172
+ /**
173
+ * Flatten a multi-dimensional array into a single level.
174
+ *
175
+ * @param mixed[] $array
176
+ * @param int $depth
177
+ * @return array
178
+ */
179
+ public static function flatten($array, $depth = INF)
180
+ {
181
+ return array_reduce($array, function ($result, $item) use ($depth) {
182
+ $item = $item instanceof Collection ? $item->all() : $item;
183
+
184
+ if (! is_array($item)) {
185
+ return array_merge($result, [$item]);
186
+ } elseif ($depth === 1) {
187
+ return array_merge($result, array_values($item));
188
+ } else {
189
+ return array_merge($result, static::flatten($item, $depth - 1));
190
+ }
191
+ }, []);
192
+ }
193
+
194
+ /**
195
+ * Remove one or many array items from a given array using "dot" notation.
196
+ *
197
+ * @param mixed[] $array
198
+ * @param mixed[]|string $keys
199
+ * @return void
200
+ */
201
+ public static function forget(&$array, $keys)
202
+ {
203
+ $original = &$array;
204
+
205
+ $keys = (array) $keys;
206
+
207
+ if (count($keys) === 0) {
208
+ return;
209
+ }
210
+
211
+ foreach ($keys as $key) {
212
+ // if the exact key exists in the top-level, remove it
213
+ if (static::exists($array, $key)) {
214
+ unset($array[$key]);
215
+
216
+ continue;
217
+ }
218
+
219
+ $parts = explode('.', $key);
220
+
221
+ // clean up before each pass
222
+ $array = &$original;
223
+
224
+ while (count($parts) > 1) {
225
+ $part = array_shift($parts);
226
+
227
+ if (isset($array[$part]) && is_array($array[$part])) {
228
+ $array = &$array[$part];
229
+ } else {
230
+ continue 2;
231
+ }
232
+ }
233
+
234
+ unset($array[array_shift($parts)]);
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Get an item from an array using "dot" notation.
240
+ *
241
+ * @param \ArrayAccess<mixed>|mixed[] $array
242
+ * @param string $key
243
+ * @param mixed $default
244
+ * @return mixed
245
+ */
246
+ public static function get($array, $key, $default = null)
247
+ {
248
+ if (! static::accessible($array)) {
249
+ return value($default);
250
+ }
251
+
252
+ if (is_null($key)) {
253
+ return $array;
254
+ }
255
+
256
+ if (static::exists($array, $key)) {
257
+ return $array[$key];
258
+ }
259
+
260
+ foreach (explode('.', $key) as $segment) {
261
+ if (static::accessible($array) && static::exists($array, $segment)) {
262
+ $array = $array[$segment];
263
+ } else {
264
+ return value($default);
265
+ }
266
+ }
267
+
268
+ return $array;
269
+ }
270
+
271
+ /**
272
+ * Check if an item or items exist in an array using "dot" notation.
273
+ *
274
+ * @param \ArrayAccess<mixed>|mixed[] $array
275
+ * @param string|mixed[] $keys
276
+ * @return bool
277
+ */
278
+ public static function has($array, $keys)
279
+ {
280
+ if (is_null($keys)) {
281
+ return false;
282
+ }
283
+
284
+ $keys = (array) $keys;
285
+
286
+ if (! $array) {
287
+ return false;
288
+ }
289
+
290
+ if ($keys === []) {
291
+ return false;
292
+ }
293
+
294
+ foreach ($keys as $key) {
295
+ $subKeyArray = $array;
296
+
297
+ if (static::exists($array, $key)) {
298
+ continue;
299
+ }
300
+
301
+ foreach (explode('.', $key) as $segment) {
302
+ if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
303
+ $subKeyArray = $subKeyArray[$segment];
304
+ } else {
305
+ return false;
306
+ }
307
+ }
308
+ }
309
+
310
+ return true;
311
+ }
312
+
313
+ /**
314
+ * Determines if an array is associative.
315
+ *
316
+ * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
317
+ *
318
+ * @param mixed[] $array
319
+ * @return bool
320
+ */
321
+ public static function isAssoc(array $array)
322
+ {
323
+ $keys = array_keys($array);
324
+
325
+ return array_keys($keys) !== $keys;
326
+ }
327
+
328
+ /**
329
+ * Get a subset of the items from the given array.
330
+ *
331
+ * @param mixed[] $array
332
+ * @param mixed[]|string $keys
333
+ * @return array
334
+ */
335
+ public static function only($array, $keys)
336
+ {
337
+ return array_intersect_key($array, array_flip((array) $keys));
338
+ }
339
+
340
+ /**
341
+ * Pluck an array of values from an array.
342
+ *
343
+ * @param mixed[] $array
344
+ * @param string|mixed[] $value
345
+ * @param string|mixed[]|null $key
346
+ * @return mixed[]
347
+ */
348
+ public static function pluck($array, $value, $key = null)
349
+ {
350
+ $results = [];
351
+
352
+ list($value, $key) = static::explodePluckParameters($value, $key);
353
+
354
+ foreach ($array as $item) {
355
+ $itemValue = data_get($item, $value);
356
+
357
+ // If the key is "null", we will just append the value to the array and keep
358
+ // looping. Otherwise we will key the array using the value of the key we
359
+ // received from the developer. Then we'll return the final array form.
360
+ if (is_null($key)) {
361
+ $results[] = $itemValue;
362
+ } else {
363
+ $itemKey = data_get($item, $key);
364
+
365
+ $results[$itemKey] = $itemValue;
366
+ }
367
+ }
368
+
369
+ return $results;
370
+ }
371
+
372
+ /**
373
+ * Explode the "value" and "key" arguments passed to "pluck".
374
+ *
375
+ * @param string|mixed[] $value
376
+ * @param string|mixed[]|null $key
377
+ * @return mixed[]
378
+ */
379
+ protected static function explodePluckParameters($value, $key)
380
+ {
381
+ $value = is_string($value) ? explode('.', $value) : $value;
382
+
383
+ $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
384
+
385
+ return [$value, $key];
386
+ }
387
+
388
+ /**
389
+ * Push an item onto the beginning of an array.
390
+ *
391
+ * @param mixed[] $array
392
+ * @param mixed $value
393
+ * @param mixed $key
394
+ * @return mixed[]
395
+ */
396
+ public static function prepend($array, $value, $key = null)
397
+ {
398
+ if (is_null($key)) {
399
+ array_unshift($array, $value);
400
+ } else {
401
+ $array = [$key => $value] + $array;
402
+ }
403
+
404
+ return $array;
405
+ }
406
+
407
+ /**
408
+ * Get a value from the array, and remove it.
409
+ *
410
+ * @param mixed[] $array
411
+ * @param string $key
412
+ * @param mixed $default
413
+ * @return mixed
414
+ */
415
+ public static function pull(&$array, $key, $default = null)
416
+ {
417
+ $value = static::get($array, $key, $default);
418
+
419
+ static::forget($array, $key);
420
+
421
+ return $value;
422
+ }
423
+
424
+ /**
425
+ * Set an array item to a given value using "dot" notation.
426
+ *
427
+ * If no key is given to the method, the entire array will be replaced.
428
+ *
429
+ * @param mixed[] $array
430
+ * @param string $key
431
+ * @param mixed $value
432
+ * @return mixed[]
433
+ */
434
+ public static function set(&$array, $key, $value)
435
+ {
436
+ if (is_null($key)) {
437
+ return $array = $value;
438
+ }
439
+
440
+ $keys = explode('.', $key);
441
+
442
+ while (count($keys) > 1) {
443
+ $key = array_shift($keys);
444
+
445
+ // If the key doesn't exist at this depth, we will just create an empty array
446
+ // to hold the next value, allowing us to create the arrays to hold final
447
+ // values at the correct depth. Then we'll keep digging into the array.
448
+ if (! isset($array[$key]) || ! is_array($array[$key])) {
449
+ $array[$key] = [];
450
+ }
451
+
452
+ $array = &$array[$key];
453
+ }
454
+
455
+ $array[array_shift($keys)] = $value;
456
+
457
+ return $array;
458
+ }
459
+
460
+ /**
461
+ * Sort the array using the given callback or "dot" notation.
462
+ *
463
+ * @param mixed[] $array
464
+ * @param callable|string $callback
465
+ * @return mixed[]
466
+ */
467
+ public static function sort($array, $callback)
468
+ {
469
+ return Collection::make($array)->sortBy($callback)->all();
470
+ }
471
+
472
+ /**
473
+ * Recursively sort an array by keys and values.
474
+ *
475
+ * @param mixed[] $array
476
+ * @return mixed[]
477
+ */
478
+ public static function sortRecursive($array)
479
+ {
480
+ foreach ($array as &$value) {
481
+ if (is_array($value)) {
482
+ $value = static::sortRecursive($value);
483
+ }
484
+ }
485
+
486
+ if (static::isAssoc($array)) {
487
+ ksort($array);
488
+ } else {
489
+ sort($array);
490
+ }
491
+
492
+ return $array;
493
+ }
494
+
495
+ /**
496
+ * Filter the array using the given callback.
497
+ *
498
+ * @param mixed[] $array
499
+ * @param callable $callback
500
+ * @return mixed[]
501
+ */
502
+ public static function where($array, callable $callback)
503
+ {
504
+ return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
505
+ }
506
+
507
+
508
+ /**
509
+ * @param mixed ...$arrays
510
+ *
511
+ * @return mixed[]|mixed[mixed]
512
+ */
513
+ public static function crossJoin(...$arrays)
514
+ {
515
+ $results = [[]];
516
+
517
+ foreach ($arrays as $index => $array) {
518
+ $append = [];
519
+
520
+ foreach ($results as $product) {
521
+ foreach ($array as $item) {
522
+ $product[$index] = $item;
523
+
524
+ $append[] = $product;
525
+ }
526
+ }
527
+
528
+ $results = $append;
529
+ }
530
+
531
+ return $results;
532
+ }
533
+ }
addons/vendor/wpml/collect/src/Illuminate/Support/Collection.php ADDED
@@ -0,0 +1,1500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Collect\Support;
4
+
5
+ use Countable;
6
+ use ArrayAccess;
7
+ use Traversable;
8
+ use ArrayIterator;
9
+ use CachingIterator;
10
+ use JsonSerializable;
11
+ use IteratorAggregate;
12
+ use InvalidArgumentException;
13
+ use WPML\Collect\Support\Traits\Macroable;
14
+ use WPML\Collect\Contracts\Support\Jsonable;
15
+ use WPML\Collect\Contracts\Support\Arrayable;
16
+
17
+ class Collection implements ArrayAccess, Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable
18
+ {
19
+ use Macroable;
20
+
21
+ /**
22
+ * The items contained in the collection.
23
+ *
24
+ * @var mixed[]
25
+ */
26
+ protected $items = [];
27
+
28
+ /**
29
+ * Create a new collection.
30
+ *
31
+ * @param mixed $items
32
+ * @return void
33
+ */
34
+ public function __construct($items = [])
35
+ {
36
+ $this->items = $this->getArrayableItems($items);
37
+ }
38
+
39
+ /**
40
+ * Create a new collection instance if the value isn't one already.
41
+ *
42
+ * @param mixed[] $items
43
+ * @return static
44
+ */
45
+ public static function make($items = [])
46
+ {
47
+ return new static($items);
48
+ }
49
+
50
+ /**
51
+ * Get all of the items in the collection.
52
+ *
53
+ * @return mixed[]
54
+ */
55
+ public function all()
56
+ {
57
+ return $this->items;
58
+ }
59
+
60
+ /**
61
+ * Get the average value of a given key.
62
+ *
63
+ * @param callable|string|null $callback
64
+ * @return float|void
65
+ */
66
+ public function avg($callback = null)
67
+ {
68
+ if ($count = $this->count()) {
69
+ return $this->sum($callback) / $count;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Alias for the "avg" method.
75
+ *
76
+ * @param callable|string|null $callback
77
+ * @return float|void
78
+ */
79
+ public function average($callback = null)
80
+ {
81
+ return $this->avg($callback);
82
+ }
83
+
84
+ /**
85
+ * Get the median of a given key.
86
+ *
87
+ * @param null $key
88
+ * @return float|void
89
+ */
90
+ public function median($key = null)
91
+ {
92
+ $count = $this->count();
93
+
94
+ if ($count == 0) {
95
+ return;
96
+ }
97
+
98
+ $values = with(isset($key) ? $this->pluck($key) : $this)
99
+ ->sort()->values();
100
+
101
+ $middle = (int) ($count / 2);
102
+
103
+ if ($count % 2) {
104
+ return $values->get($middle);
105
+ }
106
+
107
+ return (new static([
108
+ $values->get($middle - 1), $values->get($middle),
109
+ ]))->average();
110
+ }
111
+
112
+ /**
113
+ * Get the mode of a given key.
114
+ *
115
+ * @param null $key
116
+ * @return mixed[]|void
117
+ */
118
+ public function mode($key = null)
119
+ {
120
+ $count = $this->count();
121
+
122
+ if ($count == 0) {
123
+ return;
124
+ }
125
+
126
+ $collection = isset($key) ? $this->pluck($key) : $this;
127
+
128
+ $counts = new self;
129
+
130
+ $collection->each(function ($value) use ($counts) {
131
+ $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
132
+ });
133
+
134
+ $sorted = $counts->sort();
135
+
136
+ $highestValue = $sorted->last();
137
+
138
+ return $sorted->filter(function ($value) use ($highestValue) {
139
+ return $value == $highestValue;
140
+ })->sort()->keys()->all();
141
+ }
142
+
143
+ /**
144
+ * Collapse the collection of items into a single array.
145
+ *
146
+ * @return static
147
+ */
148
+ public function collapse()
149
+ {
150
+ return new static(Arr::collapse($this->items));
151
+ }
152
+
153
+ /**
154
+ * Determine if an item exists in the collection.
155
+ *
156
+ * @param mixed $key
157
+ * @param mixed $value
158
+ * @return bool
159
+ */
160
+ public function contains($key, $value = null)
161
+ {
162
+ if (func_num_args() == 2) {
163
+ return $this->contains(function ($item) use ($key, $value) {
164
+ return data_get($item, $key) == $value;
165
+ });
166
+ }
167
+
168
+ if ($this->useAsCallable($key)) {
169
+ return ! is_null($this->first($key));
170
+ }
171
+
172
+ return in_array($key, $this->items);
173
+ }
174
+
175
+ /**
176
+ * Determine if an item exists in the collection using strict comparison.
177
+ *
178
+ * @param mixed $key
179
+ * @param mixed $value
180
+ * @return bool
181
+ */
182
+ public function containsStrict($key, $value = null)
183
+ {
184
+ if (func_num_args() == 2) {
185
+ return $this->contains(function ($item) use ($key, $value) {
186
+ return data_get($item, $key) === $value;
187
+ });
188
+ }
189
+
190
+ if ($this->useAsCallable($key)) {
191
+ return ! is_null($this->first($key));
192
+ }
193
+
194
+ return in_array($key, $this->items, true);
195
+ }
196
+
197
+ /**
198
+ * Get the items in the collection that are not present in the given items.
199
+ *
200
+ * @param mixed $items
201
+ * @return static
202
+ */
203
+ public function diff($items)
204
+ {
205
+ return new static(array_diff($this->items, $this->getArrayableItems($items)));
206
+ }
207
+
208
+ /**
209
+ * Get the items in the collection whose keys are not present in the given items.
210
+ *
211
+ * @param mixed $items
212
+ * @return static
213
+ */
214
+ public function diffKeys($items)
215
+ {
216
+ return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
217
+ }
218
+
219
+ /**
220
+ * Execute a callback over each item.
221
+ *
222
+ * @param callable $callback
223
+ * @return $this
224
+ */
225
+ public function each(callable $callback)
226
+ {
227
+ foreach ($this->items as $key => $item) {
228
+ if ($callback($item, $key) === false) {
229
+ break;
230
+ }
231
+ }
232
+
233
+ return $this;
234
+ }
235
+
236
+ /**
237
+ * Create a new collection consisting of every n-th element.
238
+ *
239
+ * @param int $step
240
+ * @param int $offset
241
+ * @return static
242
+ */
243
+ public function every($step, $offset = 0)
244
+ {
245
+ $new = [];
246
+
247
+ $position = 0;
248
+
249
+ foreach ($this->items as $item) {
250
+ if ($position % $step === $offset) {
251
+ $new[] = $item;
252
+ }
253
+
254
+ $position++;
255
+ }
256
+
257
+ return new static($new);
258
+ }
259
+
260
+ /**
261
+ * Get all items except for those with the specified keys.
262
+ *
263
+ * @param mixed $keys
264
+ * @return static
265
+ */
266
+ public function except($keys)
267
+ {
268
+ $keys = is_array($keys) ? $keys : func_get_args();
269
+
270
+ return new static(Arr::except($this->items, $keys));
271
+ }
272
+
273
+ /**
274
+ * Run a filter over each of the items.
275
+ *
276
+ * @param callable|null $callback
277
+ * @return static
278
+ */
279
+ public function filter(callable $callback = null)
280
+ {
281
+ if ($callback) {
282
+ return new static(Arr::where($this->items, $callback));
283
+ }
284
+
285
+ return new static(array_filter($this->items));
286
+ }
287
+
288
+ /**
289
+ * Filter items by the given key value pair.
290
+ *
291
+ * @param string $key
292
+ * @param mixed $operator
293
+ * @param mixed $value
294
+ * @return static
295
+ */
296
+ public function where($key, $operator, $value = null)
297
+ {
298
+ if (func_num_args() == 2) {
299
+ $value = $operator;
300
+
301
+ $operator = '=';
302
+ }
303
+
304
+ return $this->filter($this->operatorForWhere($key, $operator, $value));
305
+ }
306
+
307
+ /**
308
+ * Get an operator checker callback.
309
+ *
310
+ * @param string $key
311
+ * @param string $operator
312
+ * @param mixed $value
313
+ * @return \Closure
314
+ */
315
+ protected function operatorForWhere($key, $operator, $value)
316
+ {
317
+ return function ($item) use ($key, $operator, $value) {
318
+ $retrieved = data_get($item, $key);
319
+
320
+ switch ($operator) {
321
+ default:
322
+ case '=':
323
+ case '==': return $retrieved == $value;
324
+ case '!=':
325
+ case '<>': return $retrieved != $value;
326
+ case '<': return $retrieved < $value;
327
+ case '>': return $retrieved > $value;
328
+ case '<=': return $retrieved <= $value;
329
+ case '>=': return $retrieved >= $value;
330
+ case '===': return $retrieved === $value;
331
+ case '!==': return $retrieved !== $value;
332
+ }
333
+ };
334
+ }
335
+
336
+ /**
337
+ * Filter items by the given key value pair using strict comparison.
338
+ *
339
+ * @param string $key
340
+ * @param mixed $value
341
+ * @return static
342
+ */
343
+ public function whereStrict($key, $value)
344
+ {
345
+ return $this->where($key, '===', $value);
346
+ }
347
+
348
+ /**
349
+ * Filter items by the given key value pair.
350
+ *
351
+ * @param string $key
352
+ * @param mixed $values
353
+ * @param bool $strict
354
+ * @return static
355
+ */
356
+ public function whereIn($key, $values, $strict = false)
357
+ {
358
+ $values = $this->getArrayableItems($values);
359
+
360
+ return $this->filter(function ($item) use ($key, $values, $strict) {
361
+ return in_array(data_get($item, $key), $values, $strict);
362
+ });
363
+ }
364
+
365
+ /**
366
+ * Filter items by the given key value pair using strict comparison.
367
+ *
368
+ * @param string $key
369
+ * @param mixed $values
370
+ * @return static
371
+ */
372
+ public function whereInStrict($key, $values)
373
+ {
374
+ return $this->whereIn($key, $values, true);
375
+ }
376
+
377
+ /**
378
+ * Get the first item from the collection.
379
+ *
380
+ * @param callable|null $callback
381
+ * @param mixed $default
382
+ * @return mixed
383
+ */
384
+ public function first(callable $callback = null, $default = null)
385
+ {
386
+ return Arr::first($this->items, $callback, $default);
387
+ }
388
+
389
+ /**
390
+ * Get a flattened array of the items in the collection.
391
+ *
392
+ * @param int $depth
393
+ * @return static
394
+ */
395
+ public function flatten($depth = INF)
396
+ {
397
+ return new static(Arr::flatten($this->items, $depth));
398
+ }
399
+
400
+ /**
401
+ * Flip the items in the collection.
402
+ *
403
+ * @return static
404
+ */
405
+ public function flip()
406
+ {
407
+ return new static(array_flip($this->items));
408
+ }
409
+
410
+ /**
411
+ * Remove an item from the collection by key.
412
+ *
413
+ * @param string|array $keys
414
+ * @return $this
415
+ */
416
+ public function forget($keys)
417
+ {
418
+ foreach ((array) $keys as $key) {
419
+ $this->offsetUnset($key);
420
+ }
421
+
422
+ return $this;
423
+ }
424
+
425
+ /**
426
+ * Get an item from the collection by key.
427
+ *
428
+ * @param mixed $key
429
+ * @param mixed $default
430
+ * @return mixed
431
+ */
432
+ public function get($key, $default = null)
433
+ {
434
+ if ($this->offsetExists($key)) {
435
+ return $this->items[$key];
436
+ }
437
+
438
+ return value($default);
439
+ }
440
+
441
+ /**
442
+ * Group an associative array by a field or using a callback.
443
+ *
444
+ * @param callable|string $groupBy
445
+ * @param bool $preserveKeys
446
+ * @return static
447
+ */
448
+ public function groupBy($groupBy, $preserveKeys = false)
449
+ {
450
+ $groupBy = $this->valueRetriever($groupBy);
451
+
452
+ $results = [];
453
+
454
+ foreach ($this->items as $key => $value) {
455
+ $groupKeys = $groupBy($value, $key);
456
+
457
+ if (! is_array($groupKeys)) {
458
+ $groupKeys = [$groupKeys];
459
+ }
460
+
461
+ foreach ($groupKeys as $groupKey) {
462
+ if (! array_key_exists($groupKey, $results)) {
463
+ $results[$groupKey] = new static;
464
+ }
465
+
466
+ $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
467
+ }
468
+ }
469
+
470
+ return new static($results);
471
+ }
472
+
473
+ /**
474
+ * Key an associative array by a field or using a callback.
475
+ *
476
+ * @param callable|string $keyBy
477
+ * @return static
478
+ */
479
+ public function keyBy($keyBy)
480
+ {
481
+ $keyBy = $this->valueRetriever($keyBy);
482
+
483
+ $results = [];
484
+
485
+ foreach ($this->items as $key => $item) {
486
+ $resolvedKey = $keyBy($item, $key);
487
+
488
+ if (is_object($resolvedKey)) {
489
+ $resolvedKey = (string) $resolvedKey;
490
+ }
491
+
492
+ $results[$resolvedKey] = $item;
493
+ }
494
+
495
+ return new static($results);
496
+ }
497
+
498
+ /**
499
+ * Determine if an item exists in the collection by key.
500
+ *
501
+ * @param mixed $key
502
+ * @return bool
503
+ */
504
+ public function has($key)
505
+ {
506
+ return $this->offsetExists($key);
507
+ }
508
+
509
+ /**
510
+ * Concatenate values of a given key as a string.
511
+ *
512
+ * @param string $value
513
+ * @param string $glue
514
+ * @return string
515
+ */
516
+ public function implode($value, $glue = null)
517
+ {
518
+ $first = $this->first();
519
+
520
+ if (is_array($first) || is_object($first)) {
521
+ return implode($glue, $this->pluck($value)->all());
522
+ }
523
+
524
+ return implode($value, $this->items);
525
+ }
526
+
527
+ /**
528
+ * Intersect the collection with the given items.
529
+ *
530
+ * @param mixed $items
531
+ * @return static
532
+ */
533
+ public function intersect($items)
534
+ {
535
+ return new static(array_intersect($this->items, $this->getArrayableItems($items)));
536
+ }
537
+
538
+ /**
539
+ * Determine if the collection is empty or not.
540
+ *
541
+ * @return bool
542
+ */
543
+ public function isEmpty()
544
+ {
545
+ return empty($this->items);
546
+ }
547
+
548
+ /**
549
+ * Determine if the given value is callable, but not a string.
550
+ *
551
+ * @param mixed $value
552
+ * @return bool
553
+ */
554
+ protected function useAsCallable($value)
555
+ {
556
+ return ! is_string($value) && is_callable($value);
557
+ }
558
+
559
+ /**
560
+ * Get the keys of the collection items.
561
+ *
562
+ * @return static
563
+ */
564
+ public function keys()
565
+ {
566
+ return new static(array_keys($this->items));
567
+ }
568
+
569
+ /**
570
+ * Get the last item from the collection.
571
+ *
572
+ * @param callable|null $callback
573
+ * @param mixed $default
574
+ * @return mixed
575
+ */
576
+ public function last(callable $callback = null, $default = null)
577
+ {
578
+ return Arr::last($this->items, $callback, $default);
579
+ }
580
+
581
+ /**
582
+ * Get the values of a given key.
583
+ *
584
+ * @param string $value
585
+ * @param string|null $key
586
+ * @return static
587
+ */
588
+ public function pluck($value, $key = null)
589
+ {
590
+ return new static(Arr::pluck($this->items, $value, $key));
591
+ }
592
+
593
+ /**
594
+ * Run a map over each of the items.
595
+ *
596
+ * @param callable $callback
597
+ * @return static
598
+ */
599
+ public function map(callable $callback)
600
+ {
601
+ $keys = array_keys($this->items);
602
+
603
+ $items = array_map($callback, $this->items, $keys);
604
+
605
+ return new static(array_combine($keys, $items));
606
+ }
607
+
608
+ /**
609
+ * Run an associative map over each of the items.
610
+ *
611
+ * The callback should return an associative array with a single key/value pair.
612
+ *
613
+ * @param callable $callback
614
+ * @return static
615
+ */
616
+ public function mapWithKeys(callable $callback)
617
+ {
618
+ return $this->flatMap($callback);
619
+ }
620
+
621
+ /**
622
+ * Map a collection and flatten the result by a single level.
623
+ *
624
+ * @param callable $callback
625
+ * @return static
626
+ */
627
+ public function flatMap(callable $callback)
628
+ {
629
+ return $this->map($callback)->collapse();
630
+ }
631
+
632
+ /**
633
+ * Get the max value of a given key.
634
+ *
635
+ * @param callable|string|null $callback
636
+ * @return mixed
637
+ */
638
+ public function max($callback = null)
639
+ {
640
+ $callback = $this->valueRetriever($callback);
641
+
642
+ return $this->reduce(function ($result, $item) use ($callback) {
643
+ $value = $callback($item);
644
+
645
+ return is_null($result) || $value > $result ? $value : $result;
646
+ });
647
+ }
648
+
649
+ /**
650
+ * Merge the collection with the given items.
651
+ *
652
+ * @param mixed $items
653
+ * @return static
654
+ */
655
+ public function merge($items)
656
+ {
657
+ return new static(array_merge($this->items, $this->getArrayableItems($items)));
658
+ }
659
+
660
+ /**
661
+ * Create a collection by using this collection for keys and another for its values.
662
+ *
663
+ * @param mixed $values
664
+ * @return static
665
+ */
666
+ public function combine($values)
667
+ {
668
+ return new static(array_combine($this->all(), $this->getArrayableItems($values)));
669
+ }
670
+
671
+ /**
672
+ * Union the collection with the given items.
673
+ *
674
+ * @param mixed $items
675
+ * @return static
676
+ */
677
+ public function union($items)
678
+ {
679
+ return new static($this->items + $this->getArrayableItems($items));
680
+ }
681
+
682
+ /**
683
+ * Get the min value of a given key.
684
+ *
685
+ * @param callable|string|null $callback
686
+ * @return mixed
687
+ */
688
+ public function min($callback = null)
689
+ {
690
+ $callback = $this->valueRetriever($callback);
691
+
692
+ return $this->reduce(function ($result, $item) use ($callback) {
693
+ $value = $callback($item);
694
+
695
+ return is_null($result) || $value < $result ? $value : $result;
696
+ });
697
+ }
698
+
699
+ /**
700
+ * Get the items with the specified keys.
701
+ *
702
+ * @param mixed $keys
703
+ * @return static
704
+ */
705
+ public function only($keys)
706
+ {
707
+ if (is_null($keys)) {
708
+ return new static($this->items);
709
+ }
710
+
711
+ $keys = is_array($keys) ? $keys : func_get_args();
712
+
713
+ return new static(Arr::only($this->items, $keys));
714
+ }
715
+
716
+ /**
717
+ * "Paginate" the collection by slicing it into a smaller collection.
718
+ *
719
+ * @param int $page
720
+ * @param int $perPage
721
+ * @return static
722
+ */
723
+ public function forPage($page, $perPage)
724
+ {
725
+ return $this->slice(($page - 1) * $perPage, $perPage);
726
+ }
727
+
728
+ /**
729
+ * Partition the collection into two arrays using the given callback or key.
730
+ *
731
+ * @param callable|string $key
732
+ * @param mixed $operator
733
+ * @param mixed $value
734
+ * @return static
735
+ */
736
+ public function partition($key, $operator = null, $value = null)
737
+ {
738
+ $partitions = [new static, new static];
739
+
740
+ $callback = func_num_args() === 1
741
+ ? $this->valueRetriever($key)
742
+ : $this->operatorForWhere(...func_get_args());
743
+
744
+ foreach ($this->items as $key => $item) {
745
+ $partitions[(int) ! $callback($item, $key)][$key] = $item;
746
+ }
747
+
748
+ return new static($partitions);
749
+ }
750
+ /**
751
+ * Pass the collection to the given callback and return the result.
752
+ *
753
+ * @param callable $callback
754
+ * @return mixed
755
+ */
756
+ public function pipe(callable $callback)
757
+ {
758
+ return $callback($this);
759
+ }
760
+
761
+ /**
762
+ * Get and remove the last item from the collection.
763
+ *
764
+ * @return mixed
765
+ */
766
+ public function pop()
767
+ {
768
+ return array_pop($this->items);
769
+ }
770
+
771
+ /**
772
+ * Push an item onto the beginning of the collection.
773
+ *
774
+ * @param mixed $value
775
+ * @param mixed $key
776
+ * @return $this
777
+ */
778
+ public function prepend($value, $key = null)
779
+ {
780
+ $this->items = Arr::prepend($this->items, $value, $key);
781
+
782
+ return $this;
783
+ }
784
+
785
+ /**
786
+ * Push an item onto the end of the collection.
787
+ *
788
+ * @param mixed $value
789
+ * @return $this
790
+ */
791
+ public function push($value)
792
+ {
793
+ $this->offsetSet(null, $value);
794
+
795
+ return $this;
796
+ }
797
+
798
+ /**
799
+ * Get and remove an item from the collection.
800
+ *
801
+ * @param mixed $key
802
+ * @param mixed $default
803
+ * @return mixed
804
+ */
805
+ public function pull($key, $default = null)
806
+ {
807
+ return Arr::pull($this->items, $key, $default);
808
+ }
809
+
810
+ /**
811
+ * Put an item in the collection by key.
812
+ *
813
+ * @param mixed $key
814
+ * @param mixed $value
815
+ * @return $this
816
+ */
817
+ public function put($key, $value)
818
+ {
819
+ $this->offsetSet($key, $value);
820
+
821
+ return $this;
822
+ }
823
+
824
+ /**
825
+ * Get one or more items randomly from the collection.
826
+ *
827
+ * @param int $amount
828
+ * @return mixed
829
+ *
830
+ * @throws \InvalidArgumentException
831
+ */
832
+ public function random($amount = 1)
833
+ {
834
+ if ($amount > ($count = $this->count())) {
835
+ throw new InvalidArgumentException("You requested {$amount} items, but there are only {$count} items in the collection");
836
+ }
837
+
838
+ $keys = array_rand($this->items, $amount);
839
+
840
+ if ($amount == 1) {
841
+ return $this->items[$keys];
842
+ }
843
+
844
+ return new static(array_intersect_key($this->items, array_flip($keys)));
845
+ }
846
+
847
+ /**
848
+ * Reduce the collection to a single value.
849
+ *
850
+ * @param callable $callback
851
+ * @param mixed $initial
852
+ * @return mixed
853
+ */
854
+ public function reduce(callable $callback, $initial = null)
855
+ {
856
+ return array_reduce($this->items, $callback, $initial);
857
+ }
858
+
859
+ /**
860
+ * Create a collection of all elements that do not pass a given truth test.
861
+ *
862
+ * @param callable|mixed $callback
863
+ * @return static
864
+ */
865
+ public function reject($callback)
866
+ {
867
+ if ($this->useAsCallable($callback)) {
868
+ return $this->filter(function ($value, $key) use ($callback) {
869
+ return ! $callback($value, $key);
870
+ });
871
+ }
872
+
873
+ return $this->filter(function ($item) use ($callback) {
874
+ return $item != $callback;
875
+ });
876
+ }
877
+
878
+ /**
879
+ * Reverse items order.
880
+ *
881
+ * @return static
882
+ */
883
+ public function reverse()
884
+ {
885
+ return new static(array_reverse($this->items, true));
886
+ }
887
+
888
+ /**
889
+ * Search the collection for a given value and return the corresponding key if successful.
890
+ *
891
+ * @param mixed $value
892
+ * @param bool $strict
893
+ * @return mixed
894
+ */
895
+ public function search($value, $strict = false)
896
+ {
897
+ if (! $this->useAsCallable($value)) {
898
+ return array_search($value, $this->items, $strict);
899
+ }
900
+
901
+ foreach ($this->items as $key => $item) {
902
+ if (call_user_func($value, $item, $key)) {
903
+ return $key;
904
+ }
905
+ }
906
+
907
+ return false;
908
+ }
909
+
910
+ /**
911
+ * Get and remove the first item from the collection.
912
+ *
913
+ * @return mixed
914
+ */
915
+ public function shift()
916
+ {
917
+ return array_shift($this->items);
918
+ }
919
+
920
+ /**
921
+ * Shuffle the items in the collection.
922
+ *
923
+ * @param int $seed
924
+ * @return static
925
+ */
926
+ public function shuffle($seed = null)
927
+ {
928
+ $items = $this->items;
929
+
930
+ if (is_null($seed)) {
931
+ shuffle($items);
932
+ } else {
933
+ srand($seed);
934
+
935
+ usort($items, function () {
936
+ return rand(-1, 1);
937
+ });
938
+ }
939
+
940
+ return new static($items);
941
+ }
942
+
943
+ /**
944
+ * Slice the underlying collection array.
945
+ *
946
+ * @param int $offset
947
+ * @param int $length
948
+ * @return static
949
+ */
950
+ public function slice($offset, $length = null)
951
+ {
952
+ return new static(array_slice($this->items, $offset, $length, true));
953
+ }
954
+
955
+ /**
956
+ * Split a collection into a certain number of groups.
957
+ *
958
+ * @param int $numberOfGroups
959
+ * @return static
960
+ */
961
+ public function split($numberOfGroups)
962
+ {
963
+ if ($this->isEmpty()) {
964
+ return new static;
965
+ }
966
+
967
+ $groupSize = ceil($this->count() / $numberOfGroups);
968
+
969
+ return $this->chunk($groupSize);
970
+ }
971
+
972
+ /**
973
+ * Chunk the underlying collection array.
974
+ *
975
+ * @param int $size
976
+ * @return static
977
+ */
978
+ public function chunk($size)
979
+ {
980
+ $chunks = [];
981
+
982
+ foreach (array_chunk($this->items, $size, true) as $chunk) {
983
+ $chunks[] = new static($chunk);
984
+ }
985
+
986
+ return new static($chunks);
987
+ }
988
+
989
+ /**
990
+ * Sort through each item with a callback.
991
+ *
992
+ * @param callable|null $callback
993
+ * @return static
994
+ */
995
+ public function sort(callable $callback = null)
996
+ {
997
+ $items = $this->items;
998
+
999
+ $callback
1000
+ ? uasort($items, $callback)
1001
+ : asort($items);
1002
+
1003
+ return new static($items);
1004
+ }
1005
+
1006
+ /**
1007
+ * Sort the collection using the given callback.
1008
+ *
1009
+ * @param callable|string $callback
1010
+ * @param int $options
1011
+ * @param bool $descending
1012
+ * @return static
1013
+ */
1014
+ public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
1015
+ {
1016
+ $results = [];
1017
+
1018
+ $callback = $this->valueRetriever($callback);
1019
+
1020
+ // First we will loop through the items and get the comparator from a callback
1021
+ // function which we were given. Then, we will sort the returned values and
1022
+ // and grab the corresponding values for the sorted keys from this array.
1023
+ foreach ($this->items as $key => $value) {
1024
+ $results[$key] = $callback($value, $key);
1025
+ }
1026
+
1027
+ $descending ? arsort($results, $options)
1028
+ : asort($results, $options);
1029
+
1030
+ // Once we have sorted all of the keys in the array, we will loop through them
1031
+ // and grab the corresponding model so we can set the underlying items list
1032
+ // to the sorted version. Then we'll just return the collection instance.
1033
+ foreach (array_keys($results) as $key) {
1034
+ $results[$key] = $this->items[$key];
1035
+ }
1036
+
1037
+ return new static($results);
1038
+ }
1039
+
1040
+ /**
1041
+ * Sort the collection in descending order using the given callback.
1042
+ *
1043
+ * @param callable|string $callback
1044
+ * @param int $options
1045
+ * @return static
1046
+ */
1047
+ public function sortByDesc($callback, $options = SORT_REGULAR)
1048
+ {
1049
+ return $this->sortBy($callback, $options, true);
1050
+ }
1051
+
1052
+ /**
1053
+ * Splice a portion of the underlying collection array.
1054
+ *
1055
+ * @param int $offset
1056
+ * @param int|null $length
1057
+ * @param mixed $replacement
1058
+ * @return static
1059
+ */
1060
+ public function splice($offset, $length = null, $replacement = [])
1061
+ {
1062
+ if (func_num_args() == 1) {
1063
+ return new static(array_splice($this->items, $offset));
1064
+ }
1065
+
1066
+ return new static(array_splice($this->items, $offset, $length, $replacement));
1067
+ }
1068
+
1069
+ /**
1070
+ * Get the sum of the given values.
1071
+ *
1072
+ * @param callable|string|null $callback
1073
+ * @return mixed
1074
+ */
1075
+ public function sum($callback = null)
1076
+ {
1077
+ if (is_null($callback)) {
1078
+ return array_sum($this->items);
1079
+ }
1080
+
1081
+ $callback = $this->valueRetriever($callback);
1082
+
1083
+ return $this->reduce(function ($result, $item) use ($callback) {
1084
+ return $result + $callback($item);
1085
+ }, 0);
1086
+ }
1087
+
1088
+ /**
1089
+ * Take the first or last {$limit} items.
1090
+ *
1091
+ * @param int $limit
1092
+ * @return static
1093
+ */
1094
+ public function take($limit)
1095
+ {
1096
+ if ($limit < 0) {
1097
+ return $this->slice($limit, abs($limit));
1098
+ }
1099
+
1100
+ return $this->slice(0, $limit);
1101
+ }
1102
+
1103
+ /**
1104
+ * Transform each item in the collection using a callback.
1105
+ *
1106
+ * @param callable $callback
1107
+ * @return $this
1108
+ */
1109
+ public function transform(callable $callback)
1110
+ {
1111
+ $this->items = $this->map($callback)->all();
1112
+
1113
+ return $this;
1114
+ }
1115
+
1116
+ /**
1117
+ * Return only unique items from the collection array.
1118
+ *
1119
+ * @param string|callable|null $key
1120
+ * @param bool $strict
1121
+ *
1122
+ * @return static
1123
+ */
1124
+ public function unique($key = null, $strict = false)
1125
+ {
1126
+ if (is_null($key)) {
1127
+ return new static(array_unique($this->items, SORT_REGULAR));
1128
+ }
1129
+
1130
+ $key = $this->valueRetriever($key);
1131
+
1132
+ $exists = [];
1133
+
1134
+ return $this->reject(function ($item) use ($key, $strict, &$exists) {
1135
+ if (in_array($id = $key($item), $exists, $strict)) {
1136
+ return true;
1137
+ }
1138
+
1139
+ $exists[] = $id;
1140
+ });
1141
+ }
1142
+
1143
+ /**
1144
+ * Return only unique items from the collection array using strict comparison.
1145
+ *
1146
+ * @param string|callable|null $key
1147
+ * @return static
1148
+ */
1149
+ public function uniqueStrict($key = null)
1150
+ {
1151
+ return $this->unique($key, true);
1152
+ }
1153
+
1154
+ /**
1155
+ * Reset the keys on the underlying array.
1156
+ *
1157
+ * @return static
1158
+ */
1159
+ public function values()
1160
+ {
1161
+ return new static(array_values($this->items));
1162
+ }
1163
+
1164
+ /**
1165
+ * Get a value retrieving callback.
1166
+ *
1167
+ * @param string $value
1168
+ * @return callable
1169
+ */
1170
+ protected function valueRetriever($value)
1171
+ {
1172
+ if ($this->useAsCallable($value)) {
1173
+ return $value;
1174
+ }
1175
+
1176
+ return function ($item) use ($value) {
1177
+ return data_get($item, $value);
1178
+ };
1179
+ }
1180
+
1181
+ /**
1182
+ * Zip the collection together with one or more arrays.
1183
+ *
1184
+ * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]);
1185
+ * => [[1, 4], [2, 5], [3, 6]]
1186
+ *
1187
+ * @param mixed ...$items
1188
+ * @return static
1189
+ */
1190
+ public function zip($items)
1191
+ {
1192
+ $arrayableItems = array_map(function ($items) {
1193
+ return $this->getArrayableItems($items);
1194
+ }, func_get_args());
1195
+
1196
+ $params = array_merge([function () {
1197
+ return new static(func_get_args());
1198
+ }, $this->items], $arrayableItems);
1199
+
1200
+ return new static(call_user_func_array('array_map', $params));
1201
+ }
1202
+
1203
+ /**
1204
+ * Get the collection of items as a plain array.
1205
+ *
1206
+ * @return array
1207
+ */
1208
+ public function toArray()
1209
+ {
1210
+ return array_map(function ($value) {
1211
+ return $value instanceof Arrayable ? $value->toArray() : $value;
1212
+ }, $this->items);
1213
+ }
1214
+
1215
+ /**
1216
+ * Convert the object into something JSON serializable.
1217
+ *
1218
+ * @return array
1219
+ */
1220
+ public function jsonSerialize()
1221
+ {
1222
+ return array_map(function ($value) {
1223
+ if ($value instanceof JsonSerializable) {
1224
+ return $value->jsonSerialize();
1225
+ } elseif ($value instanceof Jsonable) {
1226
+ return json_decode($value->toJson(), true);
1227
+ } elseif ($value instanceof Arrayable) {
1228
+ return $value->toArray();
1229
+ } else {
1230
+ return $value;
1231
+ }
1232
+ }, $this->items);
1233
+ }
1234
+
1235
+ /**
1236
+ * Get the collection of items as JSON.
1237
+ *
1238
+ * @param int $options
1239
+ * @return string
1240
+ */
1241
+ public function toJson($options = 0)
1242
+ {
1243
+ return json_encode($this->jsonSerialize(), $options);
1244
+ }
1245
+
1246
+ /**
1247
+ * Get an iterator for the items.
1248
+ *
1249
+ * @return \ArrayIterator
1250
+ */
1251
+ public function getIterator()
1252
+ {
1253
+ return new ArrayIterator($this->items);
1254
+ }
1255
+
1256
+ /**
1257
+ * Get a CachingIterator instance.
1258
+ *
1259
+ * @param int $flags
1260
+ * @return \CachingIterator
1261
+ */
1262
+ public function getCachingIterator($flags = CachingIterator::CALL_TOSTRING)
1263
+ {
1264
+ return new CachingIterator($this->getIterator(), $flags);
1265
+ }
1266
+
1267
+ /**
1268
+ * Count the number of items in the collection.
1269
+ *
1270
+ * @return int
1271
+ */
1272
+ public function count()
1273
+ {
1274
+ return count($this->items);
1275
+ }
1276
+
1277
+ /**
1278
+ * Get a base Support collection instance from this collection.
1279
+ *
1280
+ * @return \WPML\Collect\Support\Collection
1281
+ */
1282
+ public function toBase()
1283
+ {
1284
+ return new self($this);
1285
+ }
1286
+
1287
+ /**
1288
+ * Determine if an item exists at an offset.
1289
+ *
1290
+ * @param mixed $key
1291
+ * @return bool
1292
+ */
1293
+ public function offsetExists($key)
1294
+ {
1295
+ return array_key_exists($key, $this->items);
1296
+ }
1297
+
1298
+ /**
1299
+ * Get an item at a given offset.
1300
+ *
1301
+ * @param mixed $key
1302
+ * @return mixed
1303
+ */
1304
+ public function offsetGet($key)
1305
+ {
1306
+ return $this->items[$key];
1307
+ }
1308
+
1309
+ /**
1310
+ * Set the item at a given offset.
1311
+ *
1312
+ * @param mixed $key
1313
+ * @param mixed $value
1314
+ * @return void
1315
+ */
1316
+ public function offsetSet($key, $value)
1317
+ {
1318
+ if (is_null($key)) {
1319
+ $this->items[] = $value;
1320
+ } else {
1321
+ $this->items[$key] = $value;
1322
+ }
1323
+ }
1324
+
1325
+ /**
1326
+ * Unset the item at a given offset.
1327
+ *
1328
+ * @param string $key
1329
+ * @return void
1330
+ */
1331
+ public function offsetUnset($key)
1332
+ {
1333
+ unset($this->items[$key]);
1334
+ }
1335
+
1336
+ /**
1337
+ * Convert the collection to its string representation.
1338
+ *
1339
+ * @return string
1340
+ */
1341
+ public function __toString()
1342
+ {
1343
+ return $this->toJson();
1344
+ }
1345
+
1346
+ /**
1347
+ * Results array of items from Collection or Arrayable.
1348
+ *
1349
+ * @param mixed $items
1350
+ * @return array
1351
+ */
1352
+ protected function getArrayableItems($items)
1353
+ {
1354
+ if (is_array($items)) {
1355
+ return $items;
1356
+ } elseif ($items instanceof self) {
1357
+ return $items->all();
1358
+ } elseif ($items instanceof Arrayable) {
1359
+ return $items->toArray();
1360
+ } elseif ($items instanceof Jsonable) {
1361
+ return json_decode($items->toJson(), true);
1362
+ } elseif ($items instanceof JsonSerializable) {
1363
+ return $items->jsonSerialize();
1364
+ } elseif ($items instanceof Traversable) {
1365
+ return iterator_to_array($items);
1366
+ }
1367
+
1368
+ return (array) $items;
1369
+ }
1370
+
1371
+ /** Those methods exist in the latest version of the library and have been copied here */
1372
+
1373
+ /**
1374
+ * Run a dictionary map over the items.
1375
+ *
1376
+ * The callback should return an associative array with a single key/value pair.
1377
+ *
1378
+ * @param callable $callback
1379
+ * @return $this
1380
+ */
1381
+ public function mapToDictionary(callable $callback)
1382
+ {
1383
+ $dictionary = [];
1384
+
1385
+ foreach ($this->items as $key => $item) {
1386
+ $pair = $callback($item, $key);
1387
+
1388
+ $key = key($pair);
1389
+
1390
+ $value = reset($pair);
1391
+
1392
+ if (! isset($dictionary[$key])) {
1393
+ $dictionary[$key] = [];
1394
+ }
1395
+
1396
+ $dictionary[$key][] = $value;
1397
+ }
1398
+
1399
+ return new static($dictionary);
1400
+ }
1401
+
1402
+ /**
1403
+ * Run a grouping map over the items.
1404
+ *
1405
+ * The callback should return an associative array with a single key/value pair.
1406
+ *
1407
+ * @param callable $callback
1408
+ * @return static
1409
+ */
1410
+ public function mapToGroups(callable $callback)
1411
+ {
1412
+ $groups = $this->mapToDictionary($callback);
1413
+
1414
+ return $groups->map([$this, 'make']);
1415
+ }
1416
+
1417
+ /**
1418
+ * Move the items meeting the condition to the front of the collection
1419
+ *
1420
+ * @param callable $condition
1421
+ *
1422
+ * @return Collection - A new collection
1423
+ */
1424
+ public function prioritize( callable $condition ) {
1425
+ $nonPrioritized = $this->reject( $condition );
1426
+
1427
+ return $this
1428
+ ->filter( $condition )
1429
+ ->toBase()
1430
+ ->merge( $nonPrioritized );
1431
+ }
1432
+
1433
+ /**
1434
+ * Convert an associative array of key => value to array of pairs [ key, value ].
1435
+ *
1436
+ * @return Collection
1437
+ */
1438
+ public function assocToPair() {
1439
+ return $this->map( function ( $item, $key ) {
1440
+ return [ $key, $item ];
1441
+ } )->values();
1442
+ }
1443
+
1444
+ /**
1445
+ * Convert an array of pairs [ key, value ] to an associative array of key => value.
1446
+ *
1447
+ * @return Collection
1448
+ */
1449
+ public function pairToAssoc() {
1450
+ return $this->mapWithKeys( function ( $pair ) {
1451
+ return [ $pair[0] => $pair[1] ];
1452
+ } );
1453
+ }
1454
+
1455
+ /**
1456
+ * Executes the given function for each item while the total execution time is less than the time out.
1457
+ * Returns the unprocessed items if a timeout occurred.
1458
+ *
1459
+ * @param callable $fn Function to all for each item.
1460
+ * @param int $timeout Timeout in seconds.
1461
+ *
1462
+ * @return Collection
1463
+ */
1464
+ public function eachWithTimeout( callable $fn, $timeout ) {
1465
+ $endTime = time() + $timeout;
1466
+
1467
+ return $this->reduce( function ( Collection $unProcessed, $item ) use ( $endTime, $fn ) {
1468
+ if ( time() > $endTime ) {
1469
+ $unProcessed->push( $item );
1470
+ } else {
1471
+ $fn( $item );
1472
+ }
1473
+
1474
+ return $unProcessed;
1475
+ }, wpml_collect() );
1476
+ }
1477
+
1478
+ /**
1479
+ * Determine if the collection is not empty.
1480
+ *
1481
+ * @return bool
1482
+ */
1483
+ public function isNotEmpty()
1484
+ {
1485
+ return ! empty($this->items);
1486
+ }
1487
+
1488
+ /**
1489
+ * Cross join with the given lists, returning all possible permutations.
1490
+ *
1491
+ * @param mixed ...$lists
1492
+ * @return static
1493
+ */
1494
+ public function crossJoin(...$lists)
1495
+ {
1496
+ return new static(Arr::crossJoin(
1497
+ $this->items, ...array_map([$this, 'getArrayableItems'], $lists)
1498
+ ));
1499
+ }
1500
+ }
addons/vendor/wpml/collect/src/Illuminate/Support/Traits/Macroable.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WPML\Collect\Support\Traits;
4
+
5
+ use Closure;
6
+ use BadMethodCallException;
7
+
8
+ trait Macroable
9
+ {
10
+ /**
11
+ * The registered string macros.
12
+ *
13
+ * @var callable[]
14
+ */
15
+ protected static $macros = [];
16
+
17
+ /**
18
+ * Register a custom macro.
19
+ *
20
+ * @param string $name
21
+ * @param callable $macro
22
+ * @return void
23
+ */
24
+ public static function macro($name, callable $macro)
25
+ {
26
+ static::$macros[$name] = $macro;
27
+ }
28
+
29
+ /**
30
+ * Checks if macro is registered.
31
+ *
32
+ * @param string $name
33
+ * @return bool
34
+ */
35
+ public static function hasMacro($name)
36
+ {
37
+ return isset(static::$macros[$name]);
38
+ }
39
+
40
+ /**
41
+ * Dynamically handle calls to the class.
42
+ *
43
+ * @param string $method
44
+ * @param mixed[] $parameters
45
+ * @return mixed
46
+ *
47
+ * @throws \BadMethodCallException
48
+ */
49
+ public static function __callStatic($method, $parameters)
50
+ {
51
+ if (! static::hasMacro($method)) {
52
+ throw new BadMethodCallException("Method {$method} does not exist.");
53
+ }
54
+
55
+ if (static::$macros[$method] instanceof Closure) {
56
+ return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
57
+ }
58
+
59
+ return call_user_func_array(static::$macros[$method], $parameters);
60
+ }
61
+
62
+ /**
63
+ * Dynamically handle calls to the class.
64
+ *
65
+ * @param string $method
66
+ * @param mixed[] $parameters
67
+ * @return mixed
68
+ *
69
+ * @throws \BadMethodCallException
70
+ */
71
+ public function __call($method, $parameters)
72
+ {
73
+ if (! static::hasMacro($method)) {
74
+ throw new BadMethodCallException("Method {$method} does not exist.");
75
+ }
76
+
77
+ if (static::$macros[$method] instanceof Closure) {
78
+ return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters);
79
+ }
80
+
81
+ return call_user_func_array(static::$macros[$method], $parameters);
82
+ }
83
+ }
addons/vendor/wpml/collect/src/Illuminate/Support/helpers.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WPML\Collect\Support\Arr;
4
+ use WPML\Collect\Support\Collection;
5
+
6
+ if (! function_exists('wpml_collect')) {
7
+ /**
8
+ * @param mixed|null $value
9
+ *
10
+ * @return \WPML\Collect\Support\Collection<mixed>
11
+ */
12
+ function wpml_collect( $value = null ) {
13
+ return new Collection( $value );
14
+ }
15
+ }
16
+
17
+ if (! function_exists('value')) {
18
+ /**
19
+ * Return the default value of the given value.
20
+ *
21
+ * @param mixed $value
22
+ *
23
+ * @return mixed
24
+ */
25
+ function value( $value ) {
26
+ return $value instanceof Closure ? $value() : $value;
27
+ }
28
+ }
29
+
30
+ if (! function_exists('data_get')) {
31
+ /**
32
+ * Get an item from an array or object using "dot" notation.
33
+ *
34
+ * @param mixed $target
35
+ * @param string|string[] $key
36
+ * @param mixed $default
37
+ * @return mixed
38
+ */
39
+ function data_get($target, $key, $default = null)
40
+ {
41
+ if (is_null($key)) {
42
+ return $target;
43
+ }
44
+
45
+ $key = is_array($key) ? $key : explode('.', $key);
46
+
47
+ while (($segment = array_shift($key)) !== null) {
48
+ if ($segment === '*') {
49
+ if ($target instanceof Collection) {
50
+ $target = $target->all();
51
+ } elseif (! is_array($target)) {
52
+ return value($default);
53
+ }
54
+
55
+ $result = Arr::pluck($target, $key);
56
+
57
+ return in_array('*', $key) ? Arr::collapse($result) : $result;
58
+ }
59
+
60
+ if (Arr::accessible($target) && Arr::exists($target, $segment)) {
61
+ $target = $target[$segment];
62
+ } elseif (is_object($target) && isset($target->{$segment})) {
63
+ $target = $target->{$segment};
64
+ } else {
65
+ return value($default);
66
+ }
67
+ }
68
+
69
+ return $target;
70
+ }
71
+ }
72
+
73
+ if (! function_exists('with')) {
74
+ /**
75
+ * Return the given object. Useful for chaining.
76
+ *
77
+ * @param mixed $object
78
+ * @return mixed
79
+ */
80
+ function with($object)
81
+ {
82
+ return $object;
83
+ }
84
+ }
addons/vendor/wpml/collect/tests/Support/SupportCollectionTest.php ADDED
@@ -0,0 +1,1763 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use Mockery as m;
4
+ use WPML\Collect\Support\Collection;
5
+ use WPML\Collect\Contracts\Support\Jsonable;
6
+ use WPML\Collect\Contracts\Support\Arrayable;
7
+
8
+ class SupportCollectionTest extends PHPUnit_Framework_TestCase
9
+ {
10
+ public function testFirstReturnsFirstItemInCollection()
11
+ {
12
+ $c = new Collection(['foo', 'bar']);
13
+ $this->assertEquals('foo', $c->first());
14
+ }
15
+
16
+ public function testLastReturnsLastItemInCollection()
17
+ {
18
+ $c = new Collection(['foo', 'bar']);
19
+
20
+ $this->assertEquals('bar', $c->last());
21
+ }
22
+
23
+ public function testLastWithCallback()
24
+ {
25
+ $data = new Collection([100, 200, 300]);
26
+ $result = $data->last(function ($value) {
27
+ return $value < 250;
28
+ });
29
+ $this->assertEquals(200, $result);
30
+ $result = $data->last(function ($value, $key) {
31
+ return $key < 2;
32
+ });
33
+ $this->assertEquals(200, $result);
34
+ }
35
+
36
+ public function testLastWithCallbackAndDefault()
37
+ {
38
+ $data = new Collection(['foo', 'bar']);
39
+ $result = $data->last(function ($value) {
40
+ return $value === 'baz';
41
+ }, 'default');
42
+ $this->assertEquals('default', $result);
43
+ }
44
+
45
+ public function testLastWithDefaultAndWithoutCallback()
46
+ {
47
+ $data = new Collection;
48
+ $result = $data->last(null, 'default');
49
+ $this->assertEquals('default', $result);
50
+ }
51
+
52
+ public function testPopReturnsAndRemovesLastItemInCollection()
53
+ {
54
+ $c = new Collection(['foo', 'bar']);
55
+
56
+ $this->assertEquals('bar', $c->pop());
57
+ $this->assertEquals('foo', $c->first());
58
+ }
59
+
60
+ public function testShiftReturnsAndRemovesFirstItemInCollection()
61
+ {
62
+ $c = new Collection(['foo', 'bar']);
63
+
64
+ $this->assertEquals('foo', $c->shift());
65
+ $this->assertEquals('bar', $c->first());
66
+ }
67
+
68
+ public function testEmptyCollectionIsEmpty()
69
+ {
70
+ $c = new Collection();
71
+
72
+ $this->assertTrue($c->isEmpty());
73
+ }
74
+
75
+ public function testNotEmptyCollectionIsNotEmpty()
76
+ {
77
+ $c = new Collection( [ 1, 2, 3 ]);
78
+
79
+ $this->assertTrue($c->isNotEmpty());
80
+ }
81
+
82
+ public function testCollectionIsConstructed()
83
+ {
84
+ $collection = new Collection('foo');
85
+ $this->assertSame(['foo'], $collection->all());
86
+
87
+ $collection = new Collection(2);
88
+ $this->assertSame([2], $collection->all());
89
+
90
+ $collection = new Collection(false);
91
+ $this->assertSame([false], $collection->all());
92
+
93
+ $collection = new Collection(null);
94
+ $this->assertSame([], $collection->all());
95
+
96
+ $collection = new Collection;
97
+ $this->assertSame([], $collection->all());
98
+ }
99
+
100
+ public function testGetArrayableItems()
101
+ {
102
+ $collection = new Collection;
103
+
104
+ $class = new ReflectionClass($collection);
105
+ $method = $class->getMethod('getArrayableItems');
106
+ $method->setAccessible(true);
107
+
108
+ $items = new TestArrayableObject;
109
+ $array = $method->invokeArgs($collection, [$items]);
110
+ $this->assertSame(['foo' => 'bar'], $array);
111
+
112
+ $items = new TestJsonableObject;
113
+ $array = $method->invokeArgs($collection, [$items]);
114
+ $this->assertSame(['foo' => 'bar'], $array);
115
+
116
+ $items = new TestJsonSerializeObject;
117
+ $array = $method->invokeArgs($collection, [$items]);
118
+ $this->assertSame(['foo' => 'bar'], $array);
119
+
120
+ $items = new Collection(['foo' => 'bar']);
121
+ $array = $method->invokeArgs($collection, [$items]);
122
+ $this->assertSame(['foo' => 'bar'], $array);
123
+
124
+ $items = ['foo' => 'bar'];
125
+ $array = $method->invokeArgs($collection, [$items]);
126
+ $this->assertSame(['foo' => 'bar'], $array);
127
+ }
128
+
129
+ public function testToArrayCallsToArrayOnEachItemInCollection()
130
+ {
131
+ $item1 = m::mock('WPML\Collect\Contracts\Support\Arrayable');
132
+ $item1->shouldReceive('toArray')->once()->andReturn('foo.array');
133
+ $item2 = m::mock('WPML\Collect\Contracts\Support\Arrayable');
134
+ $item2->shouldReceive('toArray')->once()->andReturn('bar.array');
135
+ $c = new Collection([$item1, $item2]);
136
+ $results = $c->toArray();
137
+
138
+ $this->assertEquals(['foo.array', 'bar.array'], $results);
139
+ }
140
+
141
+ public function testJsonSerializeCallsToArrayOrJsonSerializeOnEachItemInCollection()
142
+ {
143
+ $item1 = m::mock('JsonSerializable');
144
+ $item1->shouldReceive('jsonSerialize')->once()->andReturn('foo.json');
145
+ $item2 = m::mock('WPML\Collect\Contracts\Support\Arrayable');
146
+ $item2->shouldReceive('toArray')->once()->andReturn('bar.array');
147
+ $c = new Collection([$item1, $item2]);
148
+ $results = $c->jsonSerialize();
149
+
150
+ $this->assertEquals(['foo.json', 'bar.array'], $results);
151
+ }
152
+
153
+ public function testToJsonEncodesTheJsonSerializeResult()
154
+ {
155
+ $c = $this->getMockBuilder(Collection::class)->setMethods(['jsonSerialize'])->getMock();
156
+ $c->expects($this->once())->method('jsonSerialize')->will($this->returnValue('foo'));
157
+ $results = $c->toJson();
158
+
159
+ $this->assertJsonStringEqualsJsonString(json_encode('foo'), $results);
160
+ }
161
+
162
+ public function testCastingToStringJsonEncodesTheToArrayResult()
163
+ {
164
+ $c = $this->getMockBuilder(Collection::class)->setMethods(['jsonSerialize'])->getMock();
165
+ $c->expects($this->once())->method('jsonSerialize')->will($this->returnValue('foo'));
166
+
167
+ $this->assertJsonStringEqualsJsonString(json_encode('foo'), (string) $c);
168
+ }
169
+
170
+ public function testOffsetAccess()
171
+ {
172
+ $c = new Collection(['name' => 'taylor']);
173
+ $this->assertEquals('taylor', $c['name']);
174
+ $c['name'] = 'dayle';
175
+ $this->assertEquals('dayle', $c['name']);
176
+ $this->assertTrue(isset($c['name']));
177
+ unset($c['name']);
178
+ $this->assertFalse(isset($c['name']));
179
+ $c[] = 'jason';
180
+ $this->assertEquals('jason', $c[0]);
181
+ }
182
+
183
+ public function testArrayAccessOffsetExists()
184
+ {
185
+ $c = new Collection(['foo', 'bar']);
186
+ $this->assertTrue($c->offsetExists(0));
187
+ $this->assertTrue($c->offsetExists(1));
188
+ $this->assertFalse($c->offsetExists(1000));
189
+ }
190
+
191
+ public function testArrayAccessOffsetGet()
192
+ {
193
+ $c = new Collection(['foo', 'bar']);
194
+ $this->assertEquals('foo', $c->offsetGet(0));
195
+ $this->assertEquals('bar', $c->offsetGet(1));
196
+ }
197
+
198
+ /**
199
+ * @expectedException PHPUnit_Framework_Error_Notice
200
+ */
201
+ public function testArrayAccessOffsetGetOnNonExist()
202
+ {
203
+ $c = new Collection(['foo', 'bar']);
204
+ $c->offsetGet(1000);
205
+ }
206
+
207
+ public function testArrayAccessOffsetSet()
208
+ {
209
+ $c = new Collection(['foo', 'foo']);
210
+
211
+ $c->offsetSet(1, 'bar');
212
+ $this->assertEquals('bar', $c[1]);
213
+
214
+ $c->offsetSet(null, 'qux');
215
+ $this->assertEquals('qux', $c[2]);
216
+ }
217
+
218
+ /**
219
+ * @expectedException PHPUnit_Framework_Error_Notice
220
+ */
221
+ public function testArrayAccessOffsetUnset()
222
+ {
223
+ $c = new Collection(['foo', 'bar']);
224
+
225
+ $c->offsetUnset(1);
226
+ $c[1];
227
+ }
228
+
229
+ public function testForgetSingleKey()
230
+ {
231
+ $c = new Collection(['foo', 'bar']);
232
+ $c->forget(0);
233
+ $this->assertFalse(isset($c['foo']));
234
+
235
+ $c = new Collection(['foo' => 'bar', 'baz' => 'qux']);
236
+ $c->forget('foo');
237
+ $this->assertFalse(isset($c['foo']));
238
+ }
239
+
240
+ public function testForgetArrayOfKeys()
241
+ {
242
+ $c = new Collection(['foo', 'bar', 'baz']);
243
+ $c->forget([0, 2]);
244
+ $this->assertFalse(isset($c[0]));
245
+ $this->assertFalse(isset($c[2]));
246
+ $this->assertTrue(isset($c[1]));
247
+
248
+ $c = new Collection(['name' => 'taylor', 'foo' => 'bar', 'baz' => 'qux']);
249
+ $c->forget(['foo', 'baz']);
250
+ $this->assertFalse(isset($c['foo']));
251
+ $this->assertFalse(isset($c['baz']));
252
+ $this->assertTrue(isset($c['name']));
253
+ }
254
+
255
+ public function testCountable()
256
+ {
257
+ $c = new Collection(['foo', 'bar']);
258
+ $this->assertCount(2, $c);
259
+ }
260
+
261
+ public function testIterable()
262
+ {
263
+ $c = new Collection(['foo']);
264
+ $this->assertInstanceOf('ArrayIterator', $c->getIterator());
265
+ $this->assertEquals(['foo'], $c->getIterator()->getArrayCopy());
266
+ }
267
+
268
+ public function testCachingIterator()
269
+ {
270
+ $c = new Collection(['foo']);
271
+ $this->assertInstanceOf('CachingIterator', $c->getCachingIterator());
272
+ }
273
+
274
+ public function testFilter()
275
+ {
276
+ $c = new Collection([['id' => 1, 'name' => 'Hello'], ['id' => 2, 'name' => 'World']]);
277
+ $this->assertEquals([1 => ['id' => 2, 'name' => 'World']], $c->filter(function ($item) {
278
+ return $item['id'] == 2;
279
+ })->all());
280
+
281
+ $c = new Collection(['', 'Hello', '', 'World']);
282
+ $this->assertEquals(['Hello', 'World'], $c->filter()->values()->toArray());
283
+
284
+ $c = new Collection(['id' => 1, 'first' => 'Hello', 'second' => 'World']);
285
+ $this->assertEquals(['first' => 'Hello', 'second' => 'World'], $c->filter(function ($item, $key) {
286
+ return $key != 'id';
287
+ })->all());
288
+ }
289
+
290
+ public function testWhere()
291
+ {
292
+ $c = new Collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
293
+
294
+ $this->assertEquals(
295
+ [['v' => 3], ['v' => '3']],
296
+ $c->where('v', 3)->values()->all()
297
+ );
298
+ $this->assertEquals(
299
+ [['v' => 3], ['v' => '3']],
300
+ $c->where('v', '=', 3)->values()->all()
301
+ );
302
+ $this->assertEquals(
303
+ [['v' => 3], ['v' => '3']],
304
+ $c->where('v', '==', 3)->values()->all()
305
+ );
306
+ $this->assertEquals(
307
+ [['v' => 3], ['v' => '3']],
308
+ $c->where('v', 'garbage', 3)->values()->all()
309
+ );
310
+ $this->assertEquals(
311
+ [['v' => 3]],
312
+ $c->where('v', '===', 3)->values()->all()
313
+ );
314
+
315
+ $this->assertEquals(
316
+ [['v' => 1], ['v' => 2], ['v' => 4]],
317
+ $c->where('v', '<>', 3)->values()->all()
318
+ );
319
+ $this->assertEquals(
320
+ [['v' => 1], ['v' => 2], ['v' => 4]],
321
+ $c->where('v', '!=', 3)->values()->all()
322
+ );
323
+ $this->assertEquals(
324
+ [['v' => 1], ['v' => 2], ['v' => '3'], ['v' => 4]],
325
+ $c->where('v', '!==', 3)->values()->all()
326
+ );
327
+ $this->assertEquals(
328
+ [['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3']],
329
+ $c->where('v', '<=', 3)->values()->all()
330
+ );
331
+ $this->assertEquals(
332
+ [['v' => 3], ['v' => '3'], ['v' => 4]],
333
+ $c->where('v', '>=', 3)->values()->all()
334
+ );
335
+ $this->assertEquals(
336
+ [['v' => 1], ['v' => 2]],
337
+ $c->where('v', '<', 3)->values()->all()
338
+ );
339
+ $this->assertEquals(
340
+ [['v' => 4]],
341
+ $c->where('v', '>', 3)->values()->all()
342
+ );
343
+ }
344
+
345
+ public function testWhereStrict()
346
+ {
347
+ $c = new Collection([['v' => 3], ['v' => '3']]);
348
+
349
+ $this->assertEquals(
350
+ [['v' => 3]],
351
+ $c->whereStrict('v', 3)->values()->all()
352
+ );
353
+ }
354
+
355
+ public function testWhereIn()
356
+ {
357
+ $c = new Collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
358
+ $this->assertEquals([['v' => 1], ['v' => 3], ['v' => '3']], $c->whereIn('v', [1, 3])->values()->all());
359
+ }
360
+
361
+ public function testWhereInStrict()
362
+ {
363
+ $c = new Collection([['v' => 1], ['v' => 2], ['v' => 3], ['v' => '3'], ['v' => 4]]);
364
+ $this->assertEquals([['v' => 1], ['v' => 3]], $c->whereInStrict('v', [1, 3])->values()->all());
365
+ }
366
+
367
+ public function testValues()
368
+ {
369
+ $c = new Collection([['id' => 1, 'name' => 'Hello'], ['id' => 2, 'name' => 'World']]);
370
+ $this->assertEquals([['id' => 2, 'name' => 'World']], $c->filter(function ($item) {
371
+ return $item['id'] == 2;
372
+ })->values()->all());
373
+ }
374
+
375
+ public function testFlatten()
376
+ {
377
+ // Flat arrays are unaffected
378
+ $c = new Collection(['#foo', '#bar', '#baz']);
379
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
380
+
381
+ // Nested arrays are flattened with existing flat items
382
+ $c = new Collection([['#foo', '#bar'], '#baz']);
383
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
384
+
385
+ // Sets of nested arrays are flattened
386
+ $c = new Collection([['#foo', '#bar'], ['#baz']]);
387
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
388
+
389
+ // Deeply nested arrays are flattened
390
+ $c = new Collection([['#foo', ['#bar']], ['#baz']]);
391
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
392
+
393
+ // Nested collections are flattened alongside arrays
394
+ $c = new Collection([new Collection(['#foo', '#bar']), ['#baz']]);
395
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
396
+
397
+ // Nested collections containing plain arrays are flattened
398
+ $c = new Collection([new Collection(['#foo', ['#bar']]), ['#baz']]);
399
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
400
+
401
+ // Nested arrays containing collections are flattened
402
+ $c = new Collection([['#foo', new Collection(['#bar'])], ['#baz']]);
403
+ $this->assertEquals(['#foo', '#bar', '#baz'], $c->flatten()->all());
404
+
405
+ // Nested arrays containing collections containing arrays are flattened
406
+ $c = new Collection([['#foo', new Collection(['#bar', ['#zap']])], ['#baz']]);
407
+ $this->assertEquals(['#foo', '#bar', '#zap', '#baz'], $c->flatten()->all());
408
+ }
409
+
410
+ public function testFlattenWithDepth()
411
+ {
412
+ // No depth flattens recursively
413
+ $c = new Collection([['#foo', ['#bar', ['#baz']]], '#zap']);
414
+ $this->assertEquals(['#foo', '#bar', '#baz', '#zap'], $c->flatten()->all());
415
+
416
+ // Specifying a depth only flattens to that depth
417
+ $c = new Collection([['#foo', ['#bar', ['#baz']]], '#zap']);
418
+ $this->assertEquals(['#foo', ['#bar', ['#baz']], '#zap'], $c->flatten(1)->all());
419
+
420
+ $c = new Collection([['#foo', ['#bar', ['#baz']]], '#zap']);
421
+ $this->assertEquals(['#foo', '#bar', ['#baz'], '#zap'], $c->flatten(2)->all());
422
+ }
423
+
424
+ public function testFlattenIgnoresKeys()
425
+ {
426
+ // No depth ignores keys
427
+ $c = new Collection(['#foo', ['key' => '#bar'], ['key' => '#baz'], 'key' => '#zap']);
428
+ $this->assertEquals(['#foo', '#bar', '#baz', '#zap'], $c->flatten()->all());
429
+
430
+ // Depth of 1 ignores keys
431
+ $c = new Collection(['#foo', ['key' => '#bar'], ['key' => '#baz'], 'key' => '#zap']);
432
+ $this->assertEquals(['#foo', '#bar', '#baz', '#zap'], $c->flatten(1)->all());
433
+ }
434
+
435
+ public function testMergeNull()
436
+ {
437
+ $c = new Collection(['name' => 'Hello']);
438
+ $this->assertEquals(['name' => 'Hello'], $c->merge(null)->all());
439
+ }
440
+
441
+ public function testMergeArray()
442
+ {
443
+ $c = new Collection(['name' => 'Hello']);
444
+ $this->assertEquals(['name' => 'Hello', 'id' => 1], $c->merge(['id' => 1])->all());
445
+ }
446
+
447
+ public function testMergeCollection()
448
+ {
449
+ $c = new Collection(['name' => 'Hello']);
450
+ $this->assertEquals(['name' => 'World', 'id' => 1], $c->merge(new Collection(['name' => 'World', 'id' => 1]))->all());
451
+ }
452
+
453
+ public function testUnionNull()
454
+ {
455
+ $c = new Collection(['name' => 'Hello']);
456
+ $this->assertEquals(['name' => 'Hello'], $c->union(null)->all());
457
+ }
458
+
459
+ public function testUnionArray()
460
+ {
461
+ $c = new Collection(['name' => 'Hello']);
462
+ $this->assertEquals(['name' => 'Hello', 'id' => 1], $c->union(['id' => 1])->all());
463
+ }
464
+
465
+ public function testUnionCollection()
466
+ {
467
+ $c = new Collection(['name' => 'Hello']);
468
+ $this->assertEquals(['name' => 'Hello', 'id' => 1], $c->union(new Collection(['name' => 'World', 'id' => 1]))->all());
469
+ }
470
+
471
+ public function testDiffCollection()
472
+ {
473
+ $c = new Collection(['id' => 1, 'first_word' => 'Hello']);
474
+ $this->assertEquals(['id' => 1], $c->diff(new Collection(['first_word' => 'Hello', 'last_word' => 'World']))->all());
475
+ }
476
+
477
+ public function testDiffNull()
478
+ {
479
+ $c = new Collection(['id' => 1, 'first_word' => 'Hello']);
480
+ $this->assertEquals(['id' => 1, 'first_word' => 'Hello'], $c->diff(null)->all());
481
+ }
482
+
483
+ public function testDiffKeys()
484
+ {
485
+ $c1 = new Collection(['id' => 1, 'first_word' => 'Hello']);
486
+ $c2 = new Collection(['id' => 123, 'foo_bar' => 'Hello']);
487
+ $this->assertEquals(['first_word' => 'Hello'], $c1->diffKeys($c2)->all());
488
+ }
489
+
490
+ public function testEach()
491
+ {
492
+ $c = new Collection($original = [1, 2, 'foo' => 'bar', 'bam' => 'baz']);
493
+
494
+ $result = [];
495
+ $c->each(function ($item, $key) use (&$result) {
496
+ $result[$key] = $item;
497
+ });
498
+ $this->assertEquals($original, $result);
499
+
500
+ $result = [];
501
+ $c->each(function ($item, $key) use (&$result) {
502
+ $result[$key] = $item;
503
+ if (is_string($key)) {
504
+ return false;
505
+ }
506
+ });
507
+ $this->assertEquals([1, 2, 'foo' => 'bar'], $result);
508
+ }
509
+
510
+ public function testIntersectNull()
511
+ {
512
+ $c = new Collection(['id' => 1, 'first_word' => 'Hello']);
513
+ $this->assertEquals([], $c->intersect(null)->all());
514
+ }
515
+
516
+ public function testIntersectCollection()
517
+ {
518
+ $c = new Collection(['id' => 1, 'first_word' => 'Hello']);
519
+ $this->assertEquals(['first_word' => 'Hello'], $c->intersect(new Collection(['first_world' => 'Hello', 'last_word' => 'World']))->all());
520
+ }
521
+
522
+ public function testUnique()
523
+ {
524
+ $c = new Collection(['Hello', 'World', 'World']);
525
+ $this->assertEquals(['Hello', 'World'], $c->unique()->all());
526
+
527
+ $c = new Collection([[1, 2], [1, 2], [2, 3], [3, 4], [2, 3]]);
528
+ $this->assertEquals([[1, 2], [2, 3], [3, 4]], $c->unique()->values()->all());
529
+ }
530
+
531
+ public function testUniqueWithCallback()
532
+ {
533
+ $c = new Collection([
534
+ 1 => ['id' => 1, 'first' => 'Taylor', 'last' => 'Otwell'], 2 => ['id' => 2, 'first' => 'Taylor', 'last' => 'Otwell'],
535
+ 3 => ['id' => 3, 'first' => 'Abigail', 'last' => 'Otwell'], 4 => ['id' => 4, 'first' => 'Abigail', 'last' => 'Otwell'],
536
+ 5 => ['id' => 5, 'first' => 'Taylor', 'last' => 'Swift'], 6 => ['id' => 6, 'first' => 'Taylor', 'last' => 'Swift'],
537
+ ]);
538
+
539
+ $this->assertEquals([
540
+ 1 => ['id' => 1, 'first' => 'Taylor', 'last' => 'Otwell'],
541
+ 3 => ['id' => 3, 'first' => 'Abigail', 'last' => 'Otwell'],
542
+ ], $c->unique('first')->all());
543
+
544
+ $this->assertEquals([
545
+ 1 => ['id' => 1, 'first' => 'Taylor', 'last' => 'Otwell'],
546
+ 3 => ['id' => 3, 'first' => 'Abigail', 'last' => 'Otwell'],
547
+ 5 => ['id' => 5, 'first' => 'Taylor', 'last' => 'Swift'],
548
+ ], $c->unique(function ($item) {
549
+ return $item['first'].$item['last'];
550
+ })->all());
551
+ }
552
+
553
+ public function testUniqueStrict()
554
+ {
555
+ $c = new Collection([
556
+ [
557
+ 'id' => '0',
558
+ 'name' => 'zero',
559
+ ],
560
+ [
561
+ 'id' => '00',
562
+ 'name' => 'double zero',
563
+ ],
564
+ [
565
+ 'id' => '0',
566
+ 'name' => 'again zero',
567
+ ],
568
+ ]);
569
+
570
+ $this->assertEquals([
571
+ [
572
+ 'id' => '0',
573
+ 'name' => 'zero',
574
+ ],
575
+ [
576
+ 'id' => '00',
577
+ 'name' => 'double zero',
578
+ ],
579
+ ], $c->uniqueStrict('id')->all());
580
+ }
581
+
582
+ public function testCollapse()
583
+ {
584
+ $data = new Collection([[$object1 = new StdClass], [$object2 = new StdClass]]);
585
+ $this->assertEquals([$object1, $object2], $data->collapse()->all());
586
+ }
587
+
588
+ public function testCollapseWithNestedCollactions()
589
+ {
590
+ $data = new Collection([new Collection([1, 2, 3]), new Collection([4, 5, 6])]);
591
+ $this->assertEquals([1, 2, 3, 4, 5, 6], $data->collapse()->all());
592
+ }
593
+
594
+ public function testSort()
595
+ {
596
+ $data = (new Collection([5, 3, 1, 2, 4]))->sort();
597
+ $this->assertEquals([1, 2, 3, 4, 5], $data->values()->all());
598
+
599
+ $data = (new Collection([-1, -3, -2, -4, -5, 0, 5, 3, 1, 2, 4]))->sort();
600
+ $this->assertEquals([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5], $data->values()->all());
601
+
602
+ $data = (new Collection(['foo', 'bar-10', 'bar-1']))->sort();
603
+ $this->assertEquals(['bar-1', 'bar-10', 'foo'], $data->values()->all());
604
+ }
605
+
606
+ public function testSortWithCallback()
607
+ {
608
+ $data = (new Collection([5, 3, 1, 2, 4]))->sort(function ($a, $b) {
609
+ if ($a === $b) {
610
+ return 0;
611
+ }
612
+
613
+ return ($a < $b) ? -1 : 1;
614
+ });
615
+
616
+ $this->assertEquals(range(1, 5), array_values($data->all()));
617
+ }
618
+
619
+ public function testSortBy()
620
+ {
621
+ $data = new Collection(['taylor', 'dayle']);
622
+ $data = $data->sortBy(function ($x) {
623
+ return $x;
624
+ });
625
+
626
+ $this->assertEquals(['dayle', 'taylor'], array_values($data->all()));
627
+
628
+ $data = new Collection(['dayle', 'taylor']);
629
+ $data = $data->sortByDesc(function ($x) {
630
+ return $x;
631
+ });
632
+
633
+ $this->assertEquals(['taylor', 'dayle'], array_values($data->all()));
634
+ }
635
+
636
+ public function testSortByString()
637
+ {
638
+ $data = new Collection([['name' => 'taylor'], ['name' => 'dayle']]);
639
+ $data = $data->sortBy('name');
640
+
641
+ $this->assertEquals([['name' => 'dayle'], ['name' => 'taylor']], array_values($data->all()));
642
+ }
643
+
644
+ public function testReverse()
645
+ {
646
+ $data = new Collection(['zaeed', 'alan']);
647
+ $reversed = $data->reverse();
648
+
649
+ $this->assertSame([1 => 'alan', 0 => 'zaeed'], $reversed->all());
650
+
651
+ $data = new Collection(['name' => 'taylor', 'framework' => 'laravel']);
652
+ $reversed = $data->reverse();
653
+
654
+ $this->assertSame(['framework' => 'laravel', 'name' => 'taylor'], $reversed->all());
655
+ }
656
+
657
+ public function testFlip()
658
+ {
659
+ $data = new Collection(['name' => 'taylor', 'framework' => 'laravel']);
660
+ $this->assertEquals(['taylor' => 'name', 'laravel' => 'framework'], $data->flip()->toArray());
661
+ }
662
+
663
+ public function testChunk()
664
+ {
665
+ $data = new Collection([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
666
+ $data = $data->chunk(3);
667
+
668
+ $this->assertInstanceOf(Collection::class, $data);
669
+ $this->assertInstanceOf(Collection::class, $data[0]);
670
+ $this->assertCount(4, $data);
671
+ $this->assertEquals([1, 2, 3], $data[0]->toArray());
672
+ $this->assertEquals([9 => 10], $data[3]->toArray());
673
+ }
674
+
675
+ public function testEvery()
676
+ {
677
+ $data = new Collection([
678
+ 6 => 'a',
679
+ 4 => 'b',
680
+ 7 => 'c',
681
+ 1 => 'd',
682
+ 5 => 'e',
683
+ 3 => 'f',
684
+ ]);
685
+
686
+ $this->assertEquals(['a', 'e'], $data->every(4)->all());
687
+ $this->assertEquals(['b', 'f'], $data->every(4, 1)->all());
688
+ $this->assertEquals(['c'], $data->every(4, 2)->all());
689
+ $this->assertEquals(['d'], $data->every(4, 3)->all());
690
+ }
691
+
692
+ public function testExcept()
693
+ {
694
+ $data = new Collection(['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com']);
695
+
696
+ $this->assertEquals(['first' => 'Taylor'], $data->except(['last', 'email', 'missing'])->all());
697
+ $this->assertEquals(['first' => 'Taylor'], $data->except('last', 'email', 'missing')->all());
698
+
699
+ $this->assertEquals(['first' => 'Taylor', 'email' => 'taylorotwell@gmail.com'], $data->except(['last'])->all());
700
+ $this->assertEquals(['first' => 'Taylor', 'email' => 'taylorotwell@gmail.com'], $data->except('last')->all());
701
+ }
702
+
703
+ public function testPluckWithArrayAndObjectValues()
704
+ {
705
+ $data = new Collection([(object) ['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']]);
706
+ $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->pluck('email', 'name')->all());
707
+ $this->assertEquals(['foo', 'bar'], $data->pluck('email')->all());
708
+ }
709
+
710
+ public function testPluckWithArrayAccessValues()
711
+ {
712
+ $data = new Collection([
713
+ new TestArrayAccessImplementation(['name' => 'taylor', 'email' => 'foo']),
714
+ new TestArrayAccessImplementation(['name' => 'dayle', 'email' => 'bar']),
715
+ ]);
716
+
717
+ $this->assertEquals(['taylor' => 'foo', 'dayle' => 'bar'], $data->pluck('email', 'name')->all());
718
+ $this->assertEquals(['foo', 'bar'], $data->pluck('email')->all());
719
+ }
720
+
721
+ public function testImplode()
722
+ {
723
+ $data = new Collection([['name' => 'taylor', 'email' => 'foo'], ['name' => 'dayle', 'email' => 'bar']]);
724
+ $this->assertEquals('foobar', $data->implode('email'));
725
+ $this->assertEquals('foo,bar', $data->implode('email', ','));
726
+
727
+ $data = new Collection(['taylor', 'dayle']);
728
+ $this->assertEquals('taylordayle', $data->implode(''));
729
+ $this->assertEquals('taylor,dayle', $data->implode(','));
730
+ }
731
+
732
+ public function testTake()
733
+ {
734
+ $data = new Collection(['taylor', 'dayle', 'shawn']);
735
+ $data = $data->take(2);
736
+ $this->assertEquals(['taylor', 'dayle'], $data->all());
737
+ }
738
+
739
+ public function testRandom()
740
+ {
741
+ $data = new Collection([1, 2, 3, 4, 5, 6]);
742
+
743
+ $random = $data->random();
744
+ $this->assertInternalType('integer', $random);
745
+ $this->assertContains($random, $data->all());
746
+
747
+ $random = $data->random(3);
748
+ $this->assertInstanceOf(Collection::class, $random);
749
+ $this->assertCount(3, $random);
750
+ }
751
+
752
+ /**
753
+ * @expectedException InvalidArgumentException
754
+ */
755
+ public function testRandomThrowsAnErrorWhenRequestingMoreItemsThanAreAvailable()
756
+ {
757
+ (new Collection)->random();
758
+ }
759
+
760
+ public function testTakeLast()
761
+ {
762
+ $data = new Collection(['taylor', 'dayle', 'shawn']);
763
+ $data = $data->take(-2);
764
+ $this->assertEquals([1 => 'dayle', 2 => 'shawn'], $data->all());
765
+ }
766
+
767
+ public function testMacroable()
768
+ {
769
+ // Foo() macro : unique values starting with A
770
+ Collection::macro('foo', function () {
771
+ return $this->filter(function ($item) {
772
+ return strpos($item, 'a') === 0;
773
+ })
774
+ ->unique()
775
+ ->values();
776
+ });
777
+
778
+ $c = new Collection(['a', 'a', 'aa', 'aaa', 'bar']);
779
+
780
+ $this->assertSame(['a', 'aa', 'aaa'], $c->foo()->all());
781
+ }
782
+
783
+ public function testMakeMethod()
784
+ {
785
+ $collection = Collection::make('foo');
786
+ $this->assertEquals(['foo'], $collection->all());
787
+ }
788
+
789
+ public function testMakeMethodFromNull()
790
+ {
791
+ $collection = Collection::make(null);
792
+ $this->assertEquals([], $collection->all());
793
+
794
+ $collection = Collection::make();
795
+ $this->assertEquals([], $collection->all());
796
+ }
797
+
798
+ public function testMakeMethodFromCollection()
799
+ {
800
+ $firstCollection = Collection::make(['foo' => 'bar']);
801
+ $secondCollection = Collection::make($firstCollection);
802
+ $this->assertEquals(['foo' => 'bar'], $secondCollection->all());
803
+ }
804
+
805
+ public function testMakeMethodFromArray()
806
+ {
807
+ $collection = Collection::make(['foo' => 'bar']);
808
+ $this->assertEquals(['foo' => 'bar'], $collection->all());
809
+ }
810
+
811
+ public function testConstructMakeFromObject()
812
+ {
813
+ $object = new stdClass();
814
+ $object->foo = 'bar';
815
+ $collection = Collection::make($object);
816
+ $this->assertEquals(['foo' => 'bar'], $collection->all());
817
+ }
818
+
819
+ public function testConstructMethod()
820
+ {
821
+ $collection = new Collection('foo');
822
+ $this->assertEquals(['foo'], $collection->all());
823
+ }
824
+
825
+ public function testConstructMethodFromNull()
826
+ {
827
+ $collection = new Collection(null);
828
+ $this->assertEquals([], $collection->all());
829
+
830
+ $collection = new Collection();
831
+ $this->assertEquals([], $collection->all());
832
+ }
833
+
834
+ public function testConstructMethodFromCollection()
835
+ {
836
+ $firstCollection = new Collection(['foo' => 'bar']);
837
+ $secondCollection = new Collection($firstCollection);
838
+ $this->assertEquals(['foo' => 'bar'], $secondCollection->all());
839
+ }
840
+
841
+ public function testConstructMethodFromArray()
842
+ {
843
+ $collection = new Collection(['foo' => 'bar']);
844
+ $this->assertEquals(['foo' => 'bar'], $collection->all());
845
+ }
846
+
847
+ public function testConstructMethodFromObject()
848
+ {
849
+ $object = new stdClass();
850
+ $object->foo = 'bar';
851
+ $collection = new Collection($object);
852
+ $this->assertEquals(['foo' => 'bar'], $collection->all());
853
+ }
854
+
855
+ public function testSplice()
856
+ {
857
+ $data = new Collection(['foo', 'baz']);
858
+ $data->splice(1);
859
+ $this->assertEquals(['foo'], $data->all());
860
+
861
+ $data = new Collection(['foo', 'baz']);
862
+ $data->splice(1, 0, 'bar');
863
+ $this->assertEquals(['foo', 'bar', 'baz'], $data->all());
864
+
865
+ $data = new Collection(['foo', 'baz']);
866
+ $data->splice(1, 1);
867
+ $this->assertEquals(['foo'], $data->all());
868
+
869
+ $data = new Collection(['foo', 'baz']);
870
+ $cut = $data->splice(1, 1, 'bar');
871
+ $this->assertEquals(['foo', 'bar'], $data->all());
872
+ $this->assertEquals(['baz'], $cut->all());
873
+ }
874
+
875
+ public function testGetPluckValueWithAccessors()
876
+ {
877
+ $model = new TestAccessorEloquentTestStub(['some' => 'foo']);
878
+ $modelTwo = new TestAccessorEloquentTestStub(['some' => 'bar']);
879
+ $data = new Collection([$model, $modelTwo]);
880
+
881
+ $this->assertEquals(['foo', 'bar'], $data->pluck('some')->all());
882
+ }
883
+
884
+ public function testMap()
885
+ {
886
+ $data = new Collection(['first' => 'taylor', 'last' => 'otwell']);
887
+ $data = $data->map(function ($item, $key) {
888
+ return $key.'-'.strrev($item);
889
+ });
890
+ $this->assertEquals(['first' => 'first-rolyat', 'last' => 'last-llewto'], $data->all());
891
+ }
892
+
893
+ public function testFlatMap()
894
+ {
895
+ $data = new Collection([
896
+ ['name' => 'taylor', 'hobbies' => ['programming', 'basketball']],
897
+ ['name' => 'adam', 'hobbies' => ['music', 'powerlifting']],
898
+ ]);
899
+ $data = $data->flatMap(function ($person) {
900
+ return $person['hobbies'];
901
+ });
902
+ $this->assertEquals(['programming', 'basketball', 'music', 'powerlifting'], $data->all());
903
+ }
904
+
905
+ public function testMapWithKeys()
906
+ {
907
+ $data = new Collection([
908
+ ['name' => 'Blastoise', 'type' => 'Water', 'idx' => 9],
909
+ ['name' => 'Charmander', 'type' => 'Fire', 'idx' => 4],
910
+ ['name' => 'Dragonair', 'type' => 'Dragon', 'idx' => 148],
911
+ ]);
912
+ $data = $data->mapWithKeys(function ($pokemon) {
913
+ return [$pokemon['name'] => $pokemon['type']];
914
+ });
915
+ $this->assertEquals(
916
+ ['Blastoise' => 'Water', 'Charmander' => 'Fire', 'Dragonair' => 'Dragon'],
917
+ $data->all()
918
+ );
919
+ }
920
+
921
+ public function testTransform()
922
+ {
923
+ $data = new Collection(['first' => 'taylor', 'last' => 'otwell']);
924
+ $data->transform(function ($item, $key) {
925
+ return $key.'-'.strrev($item);
926
+ });
927
+ $this->assertEquals(['first' => 'first-rolyat', 'last' => 'last-llewto'], $data->all());
928
+ }
929
+
930
+ public function testFirstWithCallback()
931
+ {
932
+ $data = new Collection(['foo', 'bar', 'baz']);
933
+ $result = $data->first(function ($value) {
934
+ return $value === 'bar';
935
+ });
936
+ $this->assertEquals('bar', $result);
937
+ }
938
+
939
+ public function testFirstWithCallbackAndDefault()
940
+ {
941
+ $data = new Collection(['foo', 'bar']);
942
+ $result = $data->first(function ($value) {
943
+ return $value === 'baz';
944
+ }, 'default');
945
+ $this->assertEquals('default', $result);
946
+ }
947
+
948
+ public function testFirstWithDefaultAndWithoutCallback()
949
+ {
950
+ $data = new Collection;
951
+ $result = $data->first(null, 'default');
952
+ $this->assertEquals('default', $result);
953
+ }
954
+
955
+ public function testGroupByAttribute()
956
+ {
957
+ $data = new Collection([['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1'], ['rating' => 2, 'url' => '2']]);
958
+
959
+ $result = $data->groupBy('rating');
960
+ $this->assertEquals([1 => [['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1']], 2 => [['rating' => 2, 'url' => '2']]], $result->toArray());
961
+
962
+ $result = $data->groupBy('url');
963
+ $this->assertEquals([1 => [['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1']], 2 => [['rating' => 2, 'url' => '2']]], $result->toArray());
964
+ }
965
+
966
+ public function testGroupByAttributePreservingKeys()
967
+ {
968
+ $data = new Collection([10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1'], 30 => ['rating' => 2, 'url' => '2']]);
969
+
970
+ $result = $data->groupBy('rating', true);
971
+
972
+ $expected_result = [
973
+ 1 => [10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1']],
974
+ 2 => [30 => ['rating' => 2, 'url' => '2']],
975
+ ];
976
+
977
+ $this->assertEquals($expected_result, $result->toArray());
978
+ }
979
+
980
+ public function testGroupByClosureWhereItemsHaveSingleGroup()
981
+ {
982
+ $data = new Collection([['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1'], ['rating' => 2, 'url' => '2']]);
983
+
984
+ $result = $data->groupBy(function ($item) {
985
+ return $item['rating'];
986
+ });
987
+
988
+ $this->assertEquals([1 => [['rating' => 1, 'url' => '1'], ['rating' => 1, 'url' => '1']], 2 => [['rating' => 2, 'url' => '2']]], $result->toArray());
989
+ }
990
+
991
+ public function testGroupByClosureWhereItemsHaveSingleGroupPreservingKeys()
992
+ {
993
+ $data = new Collection([10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1'], 30 => ['rating' => 2, 'url' => '2']]);
994
+
995
+ $result = $data->groupBy(function ($item) {
996
+ return $item['rating'];
997
+ }, true);
998
+
999
+ $expected_result = [
1000
+ 1 => [10 => ['rating' => 1, 'url' => '1'], 20 => ['rating' => 1, 'url' => '1']],
1001
+ 2 => [30 => ['rating' => 2, 'url' => '2']],
1002
+ ];
1003
+
1004
+ $this->assertEquals($expected_result, $result->toArray());
1005
+ }
1006
+
1007
+ public function testGroupByClosureWhereItemsHaveMultipleGroups()
1008
+ {
1009
+ $data = new Collection([
1010
+ ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1011
+ ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1012
+ ['user' => 3, 'roles' => ['Role_1']],
1013
+ ]);
1014
+
1015
+ $result = $data->groupBy(function ($item) {
1016
+ return $item['roles'];
1017
+ });
1018
+
1019
+ $expected_result = [
1020
+ 'Role_1' => [
1021
+ ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1022
+ ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1023
+ ['user' => 3, 'roles' => ['Role_1']],
1024
+ ],
1025
+ 'Role_2' => [
1026
+ ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1027
+ ],
1028
+ 'Role_3' => [
1029
+ ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1030
+ ],
1031
+ ];
1032
+
1033
+ $this->assertEquals($expected_result, $result->toArray());
1034
+ }
1035
+
1036
+ public function testGroupByClosureWhereItemsHaveMultipleGroupsPreservingKeys()
1037
+ {
1038
+ $data = new Collection([
1039
+ 10 => ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1040
+ 20 => ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1041
+ 30 => ['user' => 3, 'roles' => ['Role_1']],
1042
+ ]);
1043
+
1044
+ $result = $data->groupBy(function ($item) {
1045
+ return $item['roles'];
1046
+ }, true);
1047
+
1048
+ $expected_result = [
1049
+ 'Role_1' => [
1050
+ 10 => ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1051
+ 20 => ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1052
+ 30 => ['user' => 3, 'roles' => ['Role_1']],
1053
+ ],
1054
+ 'Role_2' => [
1055
+ 20 => ['user' => 2, 'roles' => ['Role_1', 'Role_2']],
1056
+ ],
1057
+ 'Role_3' => [
1058
+ 10 => ['user' => 1, 'roles' => ['Role_1', 'Role_3']],
1059
+ ],
1060
+ ];
1061
+
1062
+ $this->assertEquals($expected_result, $result->toArray());
1063
+ }
1064
+
1065
+ public function testKeyByAttribute()
1066
+ {
1067
+ $data = new Collection([['rating' => 1, 'name' => '1'], ['rating' => 2, 'name' => '2'], ['rating' => 3, 'name' => '3']]);
1068
+
1069
+ $result = $data->keyBy('rating');
1070
+ $this->assertEquals([1 => ['rating' => 1, 'name' => '1'], 2 => ['rating' => 2, 'name' => '2'], 3 => ['rating' => 3, 'name' => '3']], $result->all());
1071
+
1072
+ $result = $data->keyBy(function ($item) {
1073
+ return $item['rating'] * 2;
1074
+ });
1075
+ $this->assertEquals([2 => ['rating' => 1, 'name' => '1'], 4 => ['rating' => 2, 'name' => '2'], 6 => ['rating' => 3, 'name' => '3']], $result->all());
1076
+ }
1077
+
1078
+ public function testKeyByClosure()
1079
+ {
1080
+ $data = new Collection([
1081
+ ['firstname' => 'Taylor', 'lastname' => 'Otwell', 'locale' => 'US'],
1082
+ ['firstname' => 'Lucas', 'lastname' => 'Michot', 'locale' => 'FR'],
1083
+ ]);
1084
+ $result = $data->keyBy(function ($item, $key) {
1085
+ return strtolower($key.'-'.$item['firstname'].$item['lastname']);
1086
+ });
1087
+ $this->assertEquals([
1088
+ '0-taylorotwell' => ['firstname' => 'Taylor', 'lastname' => 'Otwell', 'locale' => 'US'],
1089
+ '1-lucasmichot' => ['firstname' => 'Lucas', 'lastname' => 'Michot', 'locale' => 'FR'],
1090
+ ], $result->all());
1091
+ }
1092
+
1093
+ public function testContains()
1094
+ {
1095
+ $c = new Collection([1, 3, 5]);
1096
+
1097
+ $this->assertTrue($c->contains(1));
1098
+ $this->assertFalse($c->contains(2));
1099
+ $this->assertTrue($c->contains(function ($value) {
1100
+ return $value < 5;
1101
+ }));
1102
+ $this->assertFalse($c->contains(function ($value) {
1103
+ return $value > 5;
1104
+ }));
1105
+
1106
+ $c = new Collection([['v' => 1], ['v' => 3], ['v' => 5]]);
1107
+
1108
+ $this->assertTrue($c->contains('v', 1));
1109
+ $this->assertFalse($c->contains('v', 2));
1110
+
1111
+ $c = new Collection(['date', 'class', (object) ['foo' => 50]]);
1112
+
1113
+ $this->assertTrue($c->contains('date'));
1114
+ $this->assertTrue($c->contains('class'));
1115
+ $this->assertFalse($c->contains('foo'));
1116
+ }
1117
+
1118
+ public function testContainsStrict()
1119
+ {
1120
+ $c = new Collection([1, 3, 5, '02']);
1121
+
1122
+ $this->assertTrue($c->containsStrict(1));
1123
+ $this->assertFalse($c->containsStrict(2));
1124
+ $this->assertTrue($c->containsStrict('02'));
1125
+ $this->assertTrue($c->containsStrict(function ($value) {
1126
+ return $value < 5;
1127
+ }));
1128
+ $this->assertFalse($c->containsStrict(function ($value) {
1129
+ return $value > 5;
1130
+ }));
1131
+
1132
+ $c = new Collection([['v' => 1], ['v' => 3], ['v' => '04'], ['v' => 5]]);
1133
+
1134
+ $this->assertTrue($c->containsStrict('v', 1));
1135
+ $this->assertFalse($c->containsStrict('v', 2));
1136
+ $this->assertFalse($c->containsStrict('v', 4));
1137
+ $this->assertTrue($c->containsStrict('v', '04'));
1138
+
1139
+ $c = new Collection(['date', 'class', (object) ['foo' => 50], '']);
1140
+
1141
+ $this->assertTrue($c->containsStrict('date'));
1142
+ $this->assertTrue($c->containsStrict('class'));
1143
+ $this->assertFalse($c->containsStrict('foo'));
1144
+ $this->assertFalse($c->containsStrict(null));
1145
+ $this->assertTrue($c->containsStrict(''));
1146
+ }
1147
+
1148
+ public function testGettingSumFromCollection()
1149
+ {
1150
+ $c = new Collection([(object) ['foo' => 50], (object) ['foo' => 50]]);
1151
+ $this->assertEquals(100, $c->sum('foo'));
1152
+
1153
+ $c = new Collection([(object) ['foo' => 50], (object) ['foo' => 50]]);
1154
+ $this->assertEquals(100, $c->sum(function ($i) {
1155
+ return $i->foo;
1156
+ }));
1157
+ }
1158
+
1159
+ public function testCanSumValuesWithoutACallback()
1160
+ {
1161
+ $c = new Collection([1, 2, 3, 4, 5]);
1162
+ $this->assertEquals(15, $c->sum());
1163
+ }
1164
+
1165
+ public function testGettingSumFromEmptyCollection()
1166
+ {
1167
+ $c = new Collection();
1168
+ $this->assertEquals(0, $c->sum('foo'));
1169
+ }
1170
+
1171
+ public function testValueRetrieverAcceptsDotNotation()
1172
+ {
1173
+ $c = new Collection([
1174
+ (object) ['id' => 1, 'foo' => ['bar' => 'B']], (object) ['id' => 2, 'foo' => ['bar' => 'A']],
1175
+ ]);
1176
+
1177
+ $c = $c->sortBy('foo.bar');
1178
+ $this->assertEquals([2, 1], $c->pluck('id')->all());
1179
+ }
1180
+
1181
+ public function testPullRetrievesItemFromCollection()
1182
+ {
1183
+ $c = new Collection(['foo', 'bar']);
1184
+
1185
+ $this->assertEquals('foo', $c->pull(0));
1186
+ }
1187
+
1188
+ public function testPullRemovesItemFromCollection()
1189
+ {
1190
+ $c = new Collection(['foo', 'bar']);
1191
+ $c->pull(0);
1192
+ $this->assertEquals([1 => 'bar'], $c->all());
1193
+ }
1194
+
1195
+ public function testPullReturnsDefault()
1196
+ {
1197
+ $c = new Collection([]);
1198
+ $value = $c->pull(0, 'foo');
1199
+ $this->assertEquals('foo', $value);
1200
+ }
1201
+
1202
+ public function testRejectRemovesElementsPassingTruthTest()
1203
+ {
1204
+ $c = new Collection(['foo', 'bar']);
1205
+ $this->assertEquals(['foo'], $c->reject('bar')->values()->all());
1206
+
1207
+ $c = new Collection(['foo', 'bar']);
1208
+ $this->assertEquals(['foo'], $c->reject(function ($v) {
1209
+ return $v == 'bar';
1210
+ })->values()->all());
1211
+
1212
+ $c = new Collection(['foo', null]);
1213
+ $this->assertEquals(['foo'], $c->reject(null)->values()->all());
1214
+
1215
+ $c = new Collection(['foo', 'bar']);
1216
+ $this->assertEquals(['foo', 'bar'], $c->reject('baz')->values()->all());
1217
+
1218
+ $c = new Collection(['foo', 'bar']);
1219
+ $this->assertEquals(['foo', 'bar'], $c->reject(function ($v) {
1220
+ return $v == 'baz';
1221
+ })->values()->all());
1222
+
1223
+ $c = new Collection(['id' => 1, 'primary' => 'foo', 'secondary' => 'bar']);
1224
+ $this->assertEquals(['primary' => 'foo', 'secondary' => 'bar'], $c->reject(function ($item, $key) {
1225
+ return $key == 'id';
1226
+ })->all());
1227
+ }
1228
+
1229
+ public function testSearchReturnsIndexOfFirstFoundItem()
1230
+ {
1231
+ $c = new Collection([1, 2, 3, 4, 5, 2, 5, 'foo' => 'bar']);
1232
+
1233
+ $this->assertEquals(1, $c->search(2));
1234
+ $this->assertEquals('foo', $c->search('bar'));
1235
+ $this->assertEquals(4, $c->search(function ($value) {
1236
+ return $value > 4;
1237
+ }));
1238
+ $this->assertEquals('foo', $c->search(function ($value) {
1239
+ return ! is_numeric($value);
1240
+ }));
1241
+ }
1242
+
1243
+ public function testSearchReturnsFalseWhenItemIsNotFound()
1244
+ {
1245
+ $c = new Collection([1, 2, 3, 4, 5, 'foo' => 'bar']);
1246
+
1247
+ $this->assertFalse($c->search(6));
1248
+ $this->assertFalse($c->search('foo'));
1249
+ $this->assertFalse($c->search(function ($value) {
1250
+ return $value < 1 && is_numeric($value);
1251
+ }));
1252
+ $this->assertFalse($c->search(function ($value) {
1253
+ return $value == 'nope';
1254
+ }));
1255
+ }
1256
+
1257
+ public function testKeys()
1258
+ {
1259
+ $c = new Collection(['name' => 'taylor', 'framework' => 'laravel']);
1260
+ $this->assertEquals(['name', 'framework'], $c->keys()->all());
1261
+ }
1262
+
1263
+ public function testPaginate()
1264
+ {
1265
+ $c = new Collection(['one', 'two', 'three', 'four']);
1266
+ $this->assertEquals(['one', 'two'], $c->forPage(1, 2)->all());
1267
+ $this->assertEquals([2 => 'three', 3 => 'four'], $c->forPage(2, 2)->all());
1268
+ $this->assertEquals([], $c->forPage(3, 2)->all());
1269
+ }
1270
+
1271
+ public function testPrepend()
1272
+ {
1273
+ $c = new Collection(['one', 'two', 'three', 'four']);
1274
+ $this->assertEquals(['zero', 'one', 'two', 'three', 'four'], $c->prepend('zero')->all());
1275
+
1276
+ $c = new Collection(['one' => 1, 'two' => 2]);
1277
+ $this->assertEquals(['zero' => 0, 'one' => 1, 'two' => 2], $c->prepend(0, 'zero')->all());
1278
+ }
1279
+
1280
+ public function testZip()
1281
+ {
1282
+ $c = new Collection([1, 2, 3]);
1283
+ $c = $c->zip(new Collection([4, 5, 6]));
1284
+ $this->assertInstanceOf(Collection::class, $c);
1285
+ $this->assertInstanceOf(Collection::class, $c[0]);
1286
+ $this->assertInstanceOf(Collection::class, $c[1]);
1287
+ $this->assertInstanceOf(Collection::class, $c[2]);
1288
+ $this->assertCount(3, $c);
1289
+ $this->assertEquals([1, 4], $c[0]->all());
1290
+ $this->assertEquals([2, 5], $c[1]->all());
1291
+ $this->assertEquals([3, 6], $c[2]->all());
1292
+
1293
+ $c = new Collection([1, 2, 3]);
1294
+ $c = $c->zip([4, 5, 6], [7, 8, 9]);
1295
+ $this->assertCount(3, $c);
1296
+ $this->assertEquals([1, 4, 7], $c[0]->all());
1297
+ $this->assertEquals([2, 5, 8], $c[1]->all());
1298
+ $this->assertEquals([3, 6, 9], $c[2]->all());
1299
+
1300
+ $c = new Collection([1, 2, 3]);
1301
+ $c = $c->zip([4, 5, 6], [7]);
1302
+ $this->assertCount(3, $c);
1303
+ $this->assertEquals([1, 4, 7], $c[0]->all());
1304
+ $this->assertEquals([2, 5, null], $c[1]->all());
1305
+ $this->assertEquals([3, 6, null], $c[2]->all());
1306
+ }
1307
+
1308
+ public function testGettingMaxItemsFromCollection()
1309
+ {
1310
+ $c = new Collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
1311
+ $this->assertEquals(20, $c->max(function ($item) {
1312
+ return $item->foo;
1313
+ }));
1314
+ $this->assertEquals(20, $c->max('foo'));
1315
+
1316
+ $c = new Collection([['foo' => 10], ['foo' => 20]]);
1317
+ $this->assertEquals(20, $c->max('foo'));
1318
+
1319
+ $c = new Collection([1, 2, 3, 4, 5]);
1320
+ $this->assertEquals(5, $c->max());
1321
+
1322
+ $c = new Collection();
1323
+ $this->assertNull($c->max());
1324
+ }
1325
+
1326
+ public function testGettingMinItemsFromCollection()
1327
+ {
1328
+ $c = new Collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
1329
+ $this->assertEquals(10, $c->min(function ($item) {
1330
+ return $item->foo;
1331
+ }));
1332
+ $this->assertEquals(10, $c->min('foo'));
1333
+
1334
+ $c = new Collection([['foo' => 10], ['foo' => 20]]);
1335
+ $this->assertEquals(10, $c->min('foo'));
1336
+
1337
+ $c = new Collection([1, 2, 3, 4, 5]);
1338
+ $this->assertEquals(1, $c->min());
1339
+
1340
+ $c = new Collection();
1341
+ $this->assertNull($c->min());
1342
+ }
1343
+
1344
+ public function testOnly()
1345
+ {
1346
+ $data = new Collection(['first' => 'Taylor', 'last' => 'Otwell', 'email' => 'taylorotwell@gmail.com']);
1347
+
1348
+ $this->assertEquals($data->all(), $data->only(null)->all());
1349
+ $this->assertEquals(['first' => 'Taylor'], $data->only(['first', 'missing'])->all());
1350
+ $this->assertEquals(['first' => 'Taylor'], $data->only('first', 'missing')->all());
1351
+
1352
+ $this->assertEquals(['first' => 'Taylor', 'email' => 'taylorotwell@gmail.com'], $data->only(['first', 'email'])->all());
1353
+ $this->assertEquals(['first' => 'Taylor', 'email' => 'taylorotwell@gmail.com'], $data->only('first', 'email')->all());
1354
+ }
1355
+
1356
+ public function testGettingAvgItemsFromCollection()
1357
+ {
1358
+ $c = new Collection([(object) ['foo' => 10], (object) ['foo' => 20]]);
1359
+ $this->assertEquals(15, $c->avg(function ($item) {
1360
+ return $item->foo;
1361
+ }));
1362
+ $this->assertEquals(15, $c->avg('foo'));
1363
+
1364
+ $c = new Collection([['foo' => 10], ['foo' => 20]]);
1365
+ $this->assertEquals(15, $c->avg('foo'));
1366
+
1367
+ $c = new Collection([1, 2, 3, 4, 5]);
1368
+ $this->assertEquals(3, $c->avg());
1369
+
1370
+ $c = new Collection();
1371
+ $this->assertNull($c->avg());
1372
+ }
1373
+
1374
+ public function testJsonSerialize()
1375
+ {
1376
+ $c = new Collection([
1377
+ new TestArrayableObject(),
1378
+ new TestJsonableObject(),
1379
+ new TestJsonSerializeObject(),
1380
+ 'baz',
1381
+ ]);
1382
+
1383
+ $this->assertSame([
1384
+ ['foo' => 'bar'],
1385
+ ['foo' => 'bar'],
1386
+ ['foo' => 'bar'],
1387
+ 'baz',
1388
+ ], $c->jsonSerialize());
1389
+ }
1390
+
1391
+ public function testCombineWithArray()
1392
+ {
1393
+ $expected = [
1394
+ 1 => 4,
1395
+ 2 => 5,
1396
+ 3 => 6,
1397
+ ];
1398
+
1399
+ $c = new Collection(array_keys($expected));
1400
+ $actual = $c->combine(array_values($expected))->toArray();
1401
+
1402
+ $this->assertSame($expected, $actual);
1403
+ }
1404
+
1405
+ public function testCombineWithCollection()
1406
+ {
1407
+ $expected = [
1408
+ 1 => 4,
1409
+ 2 => 5,
1410
+ 3 => 6,
1411
+ ];
1412
+
1413
+ $keyCollection = new Collection(array_keys($expected));
1414
+ $valueCollection = new Collection(array_values($expected));
1415
+ $actual = $keyCollection->combine($valueCollection)->toArray();
1416
+
1417
+ $this->assertSame($expected, $actual);
1418
+ }
1419
+
1420
+ public function testReduce()
1421
+ {
1422
+ $data = new Collection([1, 2, 3]);
1423
+ $this->assertEquals(6, $data->reduce(function ($carry, $element) {
1424
+ return $carry += $element;
1425
+ }));
1426
+ }
1427
+
1428
+ /**
1429
+ * @expectedException InvalidArgumentException
1430
+ */
1431
+ public function testRandomThrowsAnExceptionUsingAmountBiggerThanCollectionSize()
1432
+ {
1433
+ $data = new Collection([1, 2, 3]);
1434
+ $data->random(4);
1435
+ }
1436
+
1437
+ public function testPipe()
1438
+ {
1439
+ $collection = new Collection([1, 2, 3]);
1440
+
1441
+ $this->assertEquals(6, $collection->pipe(function ($collection) {
1442
+ return $collection->sum();
1443
+ }));
1444
+ }
1445
+
1446
+ public function testMedianValueWithArrayCollection()
1447
+ {
1448
+ $collection = new Collection([1, 2, 2, 4]);
1449
+
1450
+ $this->assertEquals(2, $collection->median());
1451
+ }
1452
+
1453
+ public function testMedianValueByKey()
1454
+ {
1455
+ $collection = new Collection([
1456
+ (object) ['foo' => 1],
1457
+ (object) ['foo' => 2],
1458
+ (object) ['foo' => 2],
1459
+ (object) ['foo' => 4],
1460
+ ]);
1461
+ $this->assertEquals(2, $collection->median('foo'));
1462
+ }
1463
+
1464
+ public function testEvenMedianCollection()
1465
+ {
1466
+ $collection = new Collection([
1467
+ (object) ['foo' => 0],
1468
+ (object) ['foo' => 3],
1469
+ ]);
1470
+ $this->assertEquals(1.5, $collection->median('foo'));
1471
+ }
1472
+
1473
+ public function testMedianOutOfOrderCollection()
1474
+ {
1475
+ $collection = new Collection([
1476
+ (object) ['foo' => 0],
1477
+ (object) ['foo' => 5],
1478
+ (object) ['foo' => 3],
1479
+ ]);
1480
+ $this->assertEquals(3, $collection->median('foo'));
1481
+ }
1482
+
1483
+ public function testMedianOnEmptyCollectionReturnsNull()
1484
+ {
1485
+ $collection = new Collection();
1486
+ $this->assertNull($collection->median());
1487
+ }
1488
+
1489
+ public function testModeOnNullCollection()
1490
+ {
1491
+ $collection = new Collection();
1492
+ $this->assertNull($collection->mode());
1493
+ }
1494
+
1495
+ public function testMode()
1496
+ {
1497
+ $collection = new Collection([1, 2, 3, 4, 4, 5]);
1498
+ $this->assertEquals([4], $collection->mode());
1499
+ }
1500
+
1501
+ public function testModeValueByKey()
1502
+ {
1503
+ $collection = new Collection([
1504
+ (object) ['foo' => 1],
1505
+ (object) ['foo' => 1],
1506
+ (object) ['foo' => 2],
1507
+ (object) ['foo' => 4],
1508
+ ]);
1509
+ $this->assertEquals([1], $collection->mode('foo'));
1510
+ }
1511
+
1512
+ public function testWithMultipleModeValues()
1513
+ {
1514
+ $collection = new Collection([1, 2, 2, 1]);
1515
+ $this->assertEquals([1, 2], $collection->mode());
1516
+ }
1517
+
1518
+ public function testSliceOffset()
1519
+ {
1520
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1521
+ $this->assertEquals([4, 5, 6, 7, 8], $collection->slice(3)->values()->toArray());
1522
+ }
1523
+
1524
+ public function testSliceNegativeOffset()
1525
+ {
1526
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1527
+ $this->assertEquals([6, 7, 8], $collection->slice(-3)->values()->toArray());
1528
+ }
1529
+
1530
+ public function testSliceOffsetAndLength()
1531
+ {
1532
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1533
+ $this->assertEquals([4, 5, 6], $collection->slice(3, 3)->values()->toArray());
1534
+ }
1535
+
1536
+ public function testSliceOffsetAndNegativeLength()
1537
+ {
1538
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1539
+ $this->assertEquals([4, 5, 6, 7], $collection->slice(3, -1)->values()->toArray());
1540
+ }
1541
+
1542
+ public function testSliceNegativeOffsetAndLength()
1543
+ {
1544
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1545
+ $this->assertEquals([4, 5, 6], $collection->slice(-5, 3)->values()->toArray());
1546
+ }
1547
+
1548
+ public function testSliceNegativeOffsetAndNegativeLength()
1549
+ {
1550
+ $collection = new Collection([1, 2, 3, 4, 5, 6, 7, 8]);
1551
+ $this->assertEquals([3, 4, 5, 6], $collection->slice(-6, -2)->values()->toArray());
1552
+ }
1553
+
1554
+ public function testCollectonFromTraversable()
1555
+ {
1556
+ $collection = new Collection(new \ArrayObject([1, 2, 3]));
1557
+ $this->assertEquals([1, 2, 3], $collection->toArray());
1558
+ }
1559
+
1560
+ public function testCollectonFromTraversableWithKeys()
1561
+ {
1562
+ $collection = new Collection(new \ArrayObject(['foo' => 1, 'bar' => 2, 'baz' => 3]));
1563
+ $this->assertEquals(['foo' => 1, 'bar' => 2, 'baz' => 3], $collection->toArray());
1564
+ }
1565
+
1566
+ public function testSplitCollectionWithADivisableCount()
1567
+ {
1568
+ $collection = new Collection(['a', 'b', 'c', 'd']);
1569
+
1570
+ $this->assertEquals(
1571
+ [['a', 'b'], ['c', 'd']],
1572
+ $collection->split(2)->map(function (Collection $chunk) {
1573
+ return $chunk->values()->toArray();
1574
+ })->toArray()
1575
+ );
1576
+ }
1577
+
1578
+ public function testSplitCollectionWithAnUndivisableCount()
1579
+ {
1580
+ $collection = new Collection(['a', 'b', 'c']);
1581
+
1582
+ $this->assertEquals(
1583
+ [['a', 'b'], ['c']],
1584
+ $collection->split(2)->map(function (Collection $chunk) {
1585
+ return $chunk->values()->toArray();
1586
+ })->toArray()
1587
+ );
1588
+ }
1589
+
1590
+ public function testSplitCollectionWithCountLessThenDivisor()
1591
+ {
1592
+ $collection = new Collection(['a']);
1593
+
1594
+ $this->assertEquals(
1595
+ [['a']],
1596
+ $collection->split(2)->map(function (Collection $chunk) {
1597
+ return $chunk->values()->toArray();
1598
+ })->toArray()
1599
+ );
1600
+ }
1601
+
1602
+ public function testSplitEmptyCollection()
1603
+ {
1604
+ $collection = new Collection();
1605
+
1606
+ $this->assertEquals(
1607
+ [],
1608
+ $collection->split(2)->map(function (Collection $chunk) {
1609
+ return $chunk->values()->toArray();
1610
+ })->toArray()
1611
+ );
1612
+ }
1613
+
1614
+ public function testPrioritize() {
1615
+ $collection = new Collection( [ 1, 2, 3, 4, 5 ] );
1616
+
1617
+ $filter = function( $item ) { return $item > 3; };
1618
+
1619
+ $this->assertEquals(
1620
+ [ 4, 5, 1, 2, 3 ],
1621
+ $collection->prioritize( $filter )->toArray()
1622
+ );
1623
+
1624
+ $collection = new Collection( [ 'first', 'second', 'third' ] );
1625
+
1626
+ $filter = function( $item ) { return $item === 'second'; };
1627
+
1628
+ $this->assertEquals(
1629
+ [ 'second', 'first', 'third' ],
1630
+ $collection->prioritize( $filter )->toArray()
1631
+ );
1632
+ }
1633
+
1634
+ public function testAssocToPair() {
1635
+ $collection = new Collection ( [ 'name' => 'wpml', 'type' => 'plugin' ] );
1636
+
1637
+ $this->assertEquals(
1638
+ [ [ 'name', 'wpml' ], [ 'type', 'plugin' ] ],
1639
+ $collection->assocToPair()->toArray()
1640
+ );
1641
+ }
1642
+
1643
+ public function testPairToAssoc() {
1644
+ $collection = new Collection ( [ [ 'name', 'wpml' ], [ 'type', 'plugin' ] ] );
1645
+
1646
+ $this->assertEquals(
1647
+ [ 'name' => 'wpml', 'type' => 'plugin' ],
1648
+ $collection->pairToAssoc()->toArray()
1649
+ );
1650
+ }
1651
+
1652
+ public function testEachWithTimeout() {
1653
+ $timeout = 10;
1654
+
1655
+ $c = new Collection( $original = [ 1, 2, 'bar', 'baz' ] );
1656
+
1657
+ $result = [];
1658
+ $unProcessed = $c->eachWithTimeout( function ( $item ) use ( &$result ) {
1659
+ $result[] = $item;
1660
+ }, $timeout );
1661
+ $this->assertEquals( $original, $result );
1662
+ $this->assertTrue( $unProcessed->isEmpty() );
1663
+
1664
+ $timeout = - 1; // force a timeout
1665
+ $result = [];
1666
+ $unProcessed = $c->eachWithTimeout( function ( $item ) use ( &$result ) {
1667
+ $result[] = $item;
1668
+ }, $timeout );
1669
+ $this->assertCount( 0, $result );
1670
+ $this->assertEquals( $original, $unProcessed->toArray() );
1671
+ }
1672
+
1673
+ }
1674
+
1675
+ class TestAccessorEloquentTestStub
1676
+ {
1677
+ protected $attributes = [];
1678
+
1679
+ public function __construct($attributes)
1680
+ {
1681
+ $this->attributes = $attributes;
1682
+ }
1683
+
1684
+ public function __get($attribute)
1685
+ {
1686
+ $accessor = 'get'.lcfirst($attribute).'Attribute';
1687
+ if (method_exists($this, $accessor)) {
1688
+ return $this->$accessor();
1689
+ }
1690
+
1691
+ return $this->$attribute;
1692
+ }
1693
+
1694
+ public function __isset($attribute)
1695
+ {
1696
+ $accessor = 'get'.lcfirst($attribute).'Attribute';
1697
+
1698
+ if (method_exists($this, $accessor)) {
1699
+ return ! is_null($this->$accessor());
1700
+ }
1701
+
1702
+ return isset($this->$attribute);
1703
+ }
1704
+
1705
+ public function getSomeAttribute()
1706
+ {
1707
+ return $this->attributes['some'];
1708
+ }
1709
+ }
1710
+
1711
+ class TestArrayAccessImplementation implements ArrayAccess
1712
+ {
1713
+ private $arr;
1714
+
1715
+ public function __construct($arr)
1716
+ {
1717
+ $this->arr = $arr;
1718
+ }
1719
+
1720
+ public function offsetExists($offset)
1721
+ {
1722
+ return isset($this->arr[$offset]);
1723
+ }
1724
+
1725
+ public function offsetGet($offset)
1726
+ {
1727
+ return $this->arr[$offset];
1728
+ }
1729
+
1730
+ public function offsetSet($offset, $value)
1731
+ {
1732
+ $this->arr[$offset] = $value;
1733
+ }
1734
+
1735
+ public function offsetUnset($offset)
1736
+ {
1737
+ unset($this->arr[$offset]);
1738
+ }
1739
+ }
1740
+
1741
+ class TestArrayableObject implements Arrayable
1742
+ {
1743
+ public function toArray()
1744
+ {
1745
+ return ['foo' => 'bar'];
1746
+ }
1747
+ }
1748
+
1749
+ class TestJsonableObject implements Jsonable
1750
+ {
1751
+ public function toJson($options = 0)
1752
+ {
1753
+ return '{"foo":"bar"}';
1754
+ }
1755
+ }
1756
+
1757
+ class TestJsonSerializeObject implements JsonSerializable
1758
+ {
1759
+ public function jsonSerialize()
1760
+ {
1761
+ return ['foo' => 'bar'];
1762
+ }
1763
+ }
addons/vendor/wpml/collect/tests/bootstrap.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ require __DIR__.'/../vendor/autoload.php';
4
+
5
+ date_default_timezone_set('UTC');
addons/vendor/wpml/core-api ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit 369cfd53dba15e4dceb55e0e0458c16a5a142eab
addons/vendor/wpml/fp ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit 5f233620422988ca47f3180d2fc1c2aa18191bee
addons/vendor/wpml/wp ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit dc2fbeb965133f5e569f51009b919a585a5fc1a9
addons/vendor/wpml/wpml-dependencies ADDED
@@ -0,0 +1 @@
 
1
+ Subproject commit bd11271851a380365a6d97c5920c4cd089a07427
classes/AdminDashboard/Hooks.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  namespace WCML\AdminDashboard;
4
 
5
- use SitePress;
6
  use wpdb;
7
  use IWPML_DIC_Action;
8
  use IWPML_Backend_Action;
@@ -15,7 +15,7 @@ class Hooks implements IWPML_Backend_Action, IWPML_DIC_Action {
15
  /** @var wpdb $wpdb */
16
  private $wpdb;
17
 
18
- public function __construct( SitePress $sitepress, wpdb $wpdb ) {
19
  $this->sitepress = $sitepress;
20
  $this->wpdb = $wpdb;
21
  }
2
 
3
  namespace WCML\AdminDashboard;
4
 
5
+ use WPML\Core\ISitePress;
6
  use wpdb;
7
  use IWPML_DIC_Action;
8
  use IWPML_Backend_Action;
15
  /** @var wpdb $wpdb */
16
  private $wpdb;
17
 
18
+ public function __construct( ISitePress $sitepress, wpdb $wpdb ) {
19
  $this->sitepress = $sitepress;
20
  $this->wpdb = $wpdb;
21
  }
classes/AdminNotices/CachePlugins.php CHANGED
@@ -30,8 +30,8 @@ class CachePlugins implements \IWPML_Backend_Action, \IWPML_DIC_Action {
30
  }
31
 
32
  public function addNotice() {
33
- $text = '<h2>' . __( 'WooCommerce Multilingual detected an active cache plugin on your site.', 'woocommerce-multilingual' ) . '</h2>';
34
- $text .= '<p>' . __( 'Caching may cause currency display issues for your customers if you are using the multi-currency feature.', 'woocommerce-multilingual' ) . '</p>';
35
  $text .= '<p>' . __( 'To avoid this, set your cache plugin to not cache pages for visitors that have a cookie set in their browser.', 'woocommerce-multilingual' ) . '</p>';
36
 
37
  $notice = $this->notices->create_notice( self::NOTICE_ID, $text );
@@ -46,6 +46,10 @@ class CachePlugins implements \IWPML_Backend_Action, \IWPML_DIC_Action {
46
  * @return bool
47
  */
48
  private static function hasActiveCachePlugin() {
 
 
 
 
49
  // $isActive :: ( array, string ) -> bool
50
  $isActive = pipe(
51
  Fns::nthArg( 1 ), // array index
30
  }
31
 
32
  public function addNotice() {
33
+ $text = '<h2>' . __( 'WooCommerce Multilingual & Multicurrency detected an active cache plugin on your site.', 'woocommerce-multilingual' ) . '</h2>';
34
+ $text .= '<p>' . __( 'Caching may cause currency display issues for your customers if you are using the multicurrency feature.', 'woocommerce-multilingual' ) . '</p>';
35
  $text .= '<p>' . __( 'To avoid this, set your cache plugin to not cache pages for visitors that have a cookie set in their browser.', 'woocommerce-multilingual' ) . '</p>';
36
 
37
  $notice = $this->notices->create_notice( self::NOTICE_ID, $text );
46
  * @return bool
47
  */
48
  private static function hasActiveCachePlugin() {
49
+ if ( ! function_exists( 'is_plugin_active' ) ) {
50
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
51
+ }
52
+
53
  // $isActive :: ( array, string ) -> bool
54
  $isActive = pipe(
55
  Fns::nthArg( 1 ), // array index
classes/AdminNotices/MultiCurrencyMissing.php CHANGED
@@ -43,8 +43,8 @@ class MultiCurrencyMissing implements \IWPML_Backend_Action, \IWPML_DIC_Action {
43
  */
44
  public function addNotice() {
45
  $text = '<h2>' . __( "You haven't added any secondary currencies", 'woocommerce-multilingual' ) . '</h2>';
46
- $text .= '<p>' . __( "Please add another currency to fully utilize multi-currency mode. If you do not need multiple currencies, you can disable this setting to improve your site's performance.", 'woocommerce-multilingual' ) . '</p>';
47
- $text .= '<a href="' . admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' ) . '">' . __( 'Configure multi-currency mode', 'woocommerce-multilingual' ) . '</a>';
48
 
49
  $notice = $this->notices->create_notice( self::NOTICE_ID, $text );
50
  $notice->set_css_class_types( 'notice-warning' );
43
  */
44
  public function addNotice() {
45
  $text = '<h2>' . __( "You haven't added any secondary currencies", 'woocommerce-multilingual' ) . '</h2>';
46
+ $text .= '<p>' . __( "Please add another currency to fully utilize multicurrency mode. If you do not need multiple currencies, you can disable this setting to improve your site's performance.", 'woocommerce-multilingual' ) . '</p>';
47
+ $text .= '<a href="' . admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' ) . '">' . __( 'Configure multicurrency mode', 'woocommerce-multilingual' ) . '</a>';
48
 
49
  $notice = $this->notices->create_notice( self::NOTICE_ID, $text );
50
  $notice->set_css_class_types( 'notice-warning' );
classes/AdminNotices/Review.php CHANGED
@@ -2,14 +2,15 @@
2
 
3
  namespace WCML\AdminNotices;
4
 
 
5
  use WPML_Notices;
6
  use IWPML_Backend_Action;
7
  use IWPML_Frontend_Action;
8
  use IWPML_DIC_Action;
9
  use wpdb;
10
- use SitePress;
11
 
12
- class Review implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action {
13
 
14
  const OPTION_NAME = 'wcml-rate-notice';
15
 
@@ -29,7 +30,7 @@ class Review implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_A
29
  * @param wpdb $wpdb
30
  * @param SitePress $sitepress
31
  */
32
- public function __construct( WPML_Notices $wpmlNotices, wpdb $wpdb, SitePress $sitepress ) {
33
  $this->wpmlNotices = $wpmlNotices;
34
  $this->wpdb = $wpdb;
35
  $this->sitepress = $sitepress;
@@ -60,7 +61,7 @@ class Review implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_A
60
  $notice->set_dismissible( true );
61
 
62
  $reviewLink = 'https://wordpress.org/support/plugin/woocommerce-multilingual/reviews/?filter=5#new-post';
63
- $reviewButton = $this->wpmlNotices->get_new_notice_action( __( 'Review WooCommerce Multilingual', 'woocommerce-multilingual' ), $reviewLink, false, false, true );
64
  $notice->add_action( $reviewButton );
65
 
66
  $notice->set_restrict_to_screen_ids( RestrictedScreens::get() );
@@ -76,7 +77,7 @@ class Review implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_A
76
  */
77
  private function getNoticeText() {
78
  $text = '<h2>';
79
- $text .= __( 'Congrats! You\'ve just earned some money using WooCommerce Multilingual.', 'woocommerce-multilingual' );
80
  $text .= '</h2>';
81
 
82
  $text .= '<p>';
2
 
3
  namespace WCML\AdminNotices;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
  use WPML_Notices;
7
  use IWPML_Backend_Action;
8
  use IWPML_Frontend_Action;
9
  use IWPML_DIC_Action;
10
  use wpdb;
11
+ use WPML\Core\ISitePress;
12
 
13
+ class Review implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action, IStandAloneAction {
14
 
15
  const OPTION_NAME = 'wcml-rate-notice';
16
 
30
  * @param wpdb $wpdb
31
  * @param SitePress $sitepress
32
  */
33
+ public function __construct( WPML_Notices $wpmlNotices, wpdb $wpdb, ISitePress $sitepress ) {
34
  $this->wpmlNotices = $wpmlNotices;
35
  $this->wpdb = $wpdb;
36
  $this->sitepress = $sitepress;
61
  $notice->set_dismissible( true );
62
 
63
  $reviewLink = 'https://wordpress.org/support/plugin/woocommerce-multilingual/reviews/?filter=5#new-post';
64
+ $reviewButton = $this->wpmlNotices->get_new_notice_action( __( 'Review WooCommerce Multilingual & Multicurrency', 'woocommerce-multilingual' ), $reviewLink, false, false, true );
65
  $notice->add_action( $reviewButton );
66
 
67
  $notice->set_restrict_to_screen_ids( RestrictedScreens::get() );
77
  */
78
  private function getNoticeText() {
79
  $text = '<h2>';
80
+ $text .= __( 'Congrats! You\'ve just earned some money using WooCommerce Multilingual & Multicurrency.', 'woocommerce-multilingual' );
81
  $text .= '</h2>';
82
 
83
  $text .= '<p>';
classes/Attributes/LookupFilters.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Attributes;
4
+
5
+ class LookupFilters implements \IWPML_Action {
6
+
7
+ /** @var \SitePress $sitepress */
8
+ private $sitepress;
9
+
10
+ /** @var \wpdb $wpdb */
11
+ private $wpdb;
12
+
13
+ public function __construct( \SitePress $sitepress, \wpdb $wpdb ) {
14
+ $this->sitepress = $sitepress;
15
+ $this->wpdb = $wpdb;
16
+ }
17
+
18
+ public function add_hooks() {
19
+ add_filter( 'woocommerce_get_filtered_term_product_counts_query', [ $this, 'adjustAttributeWidgetCount' ] );
20
+ }
21
+
22
+ /**
23
+ * @param array $query
24
+ *
25
+ * @return array
26
+ */
27
+ public function adjustAttributeWidgetCount( $query ) {
28
+
29
+ $query['join'] .= " INNER JOIN {$this->wpdb->prefix}icl_translations AS icl_t ON {$this->wpdb->posts}.ID = icl_t.element_id
30
+ AND icl_t.element_type = 'post_product'";
31
+
32
+ $query['where'] .= $this->wpdb->prepare(" AND icl_t.language_code = %s", $this->sitepress->get_current_language() );
33
+
34
+ return $query;
35
+ }
36
+ }
classes/Attributes/LookupFiltersFactory.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Attributes;
4
+
5
+ class LookupFiltersFactory implements \IWPML_Frontend_Action_Loader {
6
+
7
+ /**
8
+ * @return \IWPML_Action|null
9
+ */
10
+ public function create() {
11
+ /**
12
+ * @var \SitePress $sitepress
13
+ * @var \wpdb $wpdb
14
+ */
15
+ global $sitepress, $wpdb;
16
+
17
+ if ( self::isEnabled() ) {
18
+ return new LookupFilters( $sitepress, $wpdb );
19
+ }
20
+
21
+ return null;
22
+ }
23
+
24
+ /**
25
+ * @return bool
26
+ */
27
+ public static function isEnabled() {
28
+ return 'yes' === get_option( 'woocommerce_attribute_lookup_enabled' );
29
+ }
30
+
31
+ }
classes/Attributes/LookupTable.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Attributes;
4
+
5
+ use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore as ProductAttributesLookupDataStore;
6
+ use WPML\FP\Obj;
7
+ use WPML\LIB\WP\Hooks;
8
+ use function WPML\FP\spreadArgs;
9
+ use WPML\FP\Fns;
10
+
11
+ class LookupTable implements \IWPML_Action {
12
+
13
+ /** @var \SitePress $sitepress */
14
+ private $sitepress;
15
+
16
+ /**
17
+ * @param \SitePress $sitepress
18
+ */
19
+ public function __construct( \SitePress $sitepress ) {
20
+ $this->sitepress = $sitepress;
21
+ }
22
+
23
+ public function add_hooks() {
24
+ Hooks::onAction( 'save_post' )
25
+ ->then( spreadArgs( [ $this, 'triggerUpdateForTranslations' ] ) );
26
+
27
+ // For defered updates, we adjust terms filter just before the action scheduler.
28
+ Hooks::onAction( 'woocommerce_run_product_attribute_lookup_update_callback', 5 )
29
+ ->then( [ $this, 'adjustTermsFilters' ] );
30
+
31
+ // When regenerating the table we need all products and all terms.
32
+ Hooks::onFilter( 'woocommerce_attribute_lookup_regeneration_step_size' )
33
+ ->then( spreadArgs( Fns::tap( [ $this, 'regenerateTable' ] ) ) );
34
+ }
35
+
36
+ /**
37
+ * @param int $productId
38
+ */
39
+ public function triggerUpdateForTranslations( $productId ) {
40
+ if (
41
+ 'product' === get_post_type( $productId )
42
+ && 'publish' === get_post_status( $productId )
43
+ && ! $this->sitepress->is_original_content_filter( false, $productId, 'post_product' )
44
+ ) {
45
+ Hooks::onAction( 'shutdown' )
46
+ ->then( function() use ( $productId ) {
47
+ // For direct updates, we adjust terms filters just before triggering the update.
48
+ $hasTermsClausesFilter = $this->adjustTermsFilters();
49
+
50
+ wc_get_container()->get( ProductAttributesLookupDataStore::class )->on_product_changed( $productId );
51
+
52
+ $this->restoreTermsFilters( $hasTermsClausesFilter );
53
+ } );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @return bool
59
+ */
60
+ public function adjustTermsFilters() {
61
+ add_filter( 'woocommerce_product_get_attributes', [ $this, 'translateAttributeOptions' ], 10, 2 );
62
+
63
+ return remove_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ] );
64
+ }
65
+
66
+ /**
67
+ * @param bool $hasTermsClausesFilter
68
+ */
69
+ private function restoreTermsFilters( $hasTermsClausesFilter ) {
70
+ if ( $hasTermsClausesFilter ) {
71
+ add_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ], 10, 3 );
72
+ }
73
+
74
+ remove_filter( 'woocommerce_product_get_attributes', [ $this, 'translateAttributeOptions' ] );
75
+ }
76
+
77
+ /**
78
+ * @param WC_Product_Attribute[] $attrs
79
+ * @param WC_Product $product
80
+ *
81
+ * @return WC_Product_Attribute[]
82
+ */
83
+ public function translateAttributeOptions( $attrs, $product ) {
84
+ $language = $this->sitepress->get_language_for_element(
85
+ $product->get_id(),
86
+ 'post_product'
87
+ );
88
+
89
+ if ( $language && is_array( $attrs ) ) {
90
+ foreach ( $attrs as $taxonomy => $attr ) {
91
+ $options = $attr->get_options();
92
+ foreach ( $options as $index => $option ) {
93
+ $options[ $index ] = $this->sitepress->get_object_id( $option, $taxonomy, false, $language );
94
+ }
95
+ $attr->set_options( $options );
96
+ }
97
+ }
98
+
99
+ return $attrs;
100
+ }
101
+
102
+ public function regenerateTable() {
103
+ $this->adjustTermsFilters();
104
+
105
+ add_filter( 'woocommerce_product_object_query_args', Obj::assoc( 'suppress_filters', true ) );
106
+ }
107
+
108
+ }
classes/Attributes/LookupTableFactory.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Attributes;
4
+
5
+ class LookupTableFactory implements \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader {
6
+
7
+ const MIN_WC_VERSION = '6.3';
8
+
9
+ /**
10
+ * @return \IWPML_Action|null
11
+ */
12
+ public function create() {
13
+ /** @var \SitePress $sitepress */
14
+ global $sitepress;
15
+
16
+ if ( self::hasFeature() ) {
17
+ return new LookupTable( $sitepress );
18
+ }
19
+
20
+ return null;
21
+ }
22
+
23
+ /**
24
+ * @return bool
25
+ */
26
+ public static function hasFeature() {
27
+ return defined( 'WC_VERSION' ) && version_compare( WC_VERSION, self::MIN_WC_VERSION, '>=' );
28
+ }
29
+
30
+ }
classes/Block/Convert/Hooks.php CHANGED
@@ -4,7 +4,7 @@ namespace WCML\Block\Convert;
4
 
5
  use IWPML_DIC_Action;
6
  use IWPML_Frontend_Action;
7
- use SitePress;
8
  use WCML\Rest\Frontend\Language;
9
  use WPML\FP\Just;
10
  use WPML\FP\Str;
@@ -17,7 +17,7 @@ class Hooks implements IWPML_Frontend_Action, IWPML_DIC_Action {
17
  /** @var Language $frontendRestLang */
18
  private $frontendRestLang;
19
 
20
- public function __construct( SitePress $sitepress, Language $frontendRestLang ) {
21
  $this->sitepress = $sitepress;
22
  $this->frontendRestLang = $frontendRestLang;
23
  }
4
 
5
  use IWPML_DIC_Action;
6
  use IWPML_Frontend_Action;
7
+ use WPML\Core\ISitePress;
8
  use WCML\Rest\Frontend\Language;
9
  use WPML\FP\Just;
10
  use WPML\FP\Str;
17
  /** @var Language $frontendRestLang */
18
  private $frontendRestLang;
19
 
20
+ public function __construct( ISitePress $sitepress, Language $frontendRestLang ) {
21
  $this->sitepress = $sitepress;
22
  $this->frontendRestLang = $frontendRestLang;
23
  }
classes/Container/Config.php CHANGED
@@ -14,8 +14,32 @@ class Config {
14
 
15
  public static function getSharedClasses() {
16
  return [
17
- \WCML_Multi_Currency::class,
18
  \WCML_Currencies_Payment_Gateways::class,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  ];
20
  }
21
  }
14
 
15
  public static function getSharedClasses() {
16
  return [
 
17
  \WCML_Currencies_Payment_Gateways::class,
18
+ \WCML_Dependencies::class,
19
+ \WCML_Exchange_Rates::class,
20
+ \WCML_Multi_Currency::class,
21
+ ];
22
+ }
23
+
24
+ /**
25
+ * Replaces global $sitepress with null object.
26
+ *
27
+ * @return array
28
+ */
29
+ public static function getAliases() {
30
+ return [
31
+ \WPML\Core\ISitePress::class => \WCML\functions\isStandAlone()
32
+ ? \WCML\StandAlone\NullSitePress::class
33
+ : \SitePress::class,
34
+ ];
35
+ }
36
+
37
+ /**
38
+ * @return array
39
+ */
40
+ public static function getDelegated() {
41
+ return [
42
+ \WCML_Exchange_Rates::class => [ \WCML_Exchange_Rates::class, 'create' ],
43
  ];
44
  }
45
  }
classes/Email/Settings/Hooks.php CHANGED
@@ -4,7 +4,7 @@ namespace WCML\Email\Settings;
4
 
5
  use IWPML_Backend_Action;
6
  use IWPML_DIC_Action;
7
- use SitePress;
8
  use WCML_WC_Strings;
9
  use WPML_Simple_Language_Selector;
10
 
@@ -18,7 +18,7 @@ class Hooks implements IWPML_Backend_Action, IWPML_DIC_Action {
18
  /** @var WCML_WC_Strings */
19
  private $wcmlStrings;
20
 
21
- public function __construct( SitePress $sitepress, WCML_WC_Strings $wcmlStrings ) {
22
  $this->sitepress = $sitepress;
23
  $this->wcmlStrings = $wcmlStrings;
24
  }
4
 
5
  use IWPML_Backend_Action;
6
  use IWPML_DIC_Action;
7
+ use WPML\Core\ISitePress;
8
  use WCML_WC_Strings;
9
  use WPML_Simple_Language_Selector;
10
 
18
  /** @var WCML_WC_Strings */
19
  private $wcmlStrings;
20
 
21
+ public function __construct( ISitePress $sitepress, WCML_WC_Strings $wcmlStrings ) {
22
  $this->sitepress = $sitepress;
23
  $this->wcmlStrings = $wcmlStrings;
24
  }
classes/HomeScreen/Factory.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\HomeScreen;
4
+
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ class Factory implements \IWPML_Backend_Action_Loader, IStandAloneAction {
8
+
9
+ /**
10
+ * @return \IWPML_Action|null
11
+ */
12
+ public function create() {
13
+ if ( wcml_is_multi_currency_on() ) {
14
+ return new Hooks();
15
+ }
16
+ }
17
+
18
+ }
classes/HomeScreen/Hooks.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\HomeScreen;
4
+
5
+ use WCML\Utilities\Resources;
6
+ use WCML\Utilities\WcAdminPages;
7
+ use WCML\StandAlone\IStandAloneAction;
8
+
9
+ class Hooks implements \IWPML_Action, IStandAloneAction {
10
+
11
+ public function add_hooks() {
12
+ if ( WcAdminPages::isHomeScreen() ) {
13
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueueAssets' ] );
14
+ }
15
+ }
16
+
17
+ public function enqueueAssets() {
18
+ $enqueue = Resources::enqueueApp( 'homeScreen' );
19
+ $enqueue( [
20
+ 'name' => 'wcmlHomeScreen',
21
+ 'data' => [],
22
+ ] );
23
+
24
+ }
25
+
26
+ }
classes/Multicurrency/Analytics/Factory.php CHANGED
@@ -2,7 +2,9 @@
2
 
3
  namespace WCML\Multicurrency\Analytics;
4
 
5
- class Factory implements \IWPML_Backend_Action_Loader, \IWPML_REST_Action_Loader, \IWPML_Deferred_Action_Loader {
 
 
6
 
7
  /**
8
  * @return string
2
 
3
  namespace WCML\Multicurrency\Analytics;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ class Factory implements \IWPML_Backend_Action_Loader, \IWPML_REST_Action_Loader, \IWPML_Deferred_Action_Loader, IStandAloneAction {
8
 
9
  /**
10
  * @return string
classes/Multicurrency/Analytics/Hooks.php CHANGED
@@ -4,10 +4,12 @@ namespace WCML\Multicurrency\Analytics;
4
 
5
  use WCML\Utilities\Resources;
6
  use WCML\Rest\Functions;
 
7
  use WPML\FP\Obj;
8
  use WPML\FP\Fns;
 
9
 
10
- class Hooks implements \IWPML_Action {
11
 
12
  /** @var \woocommerce_wpml $woocommerce_wpml */
13
  private $woocommerce_wpml;
@@ -181,11 +183,13 @@ class Hooks implements \IWPML_Action {
181
  }
182
 
183
  private function getCurrency() {
184
- // phpcs:disable WordPress.Security.NonceVerification.Recommended
185
- return isset( $_GET['currency'] )
186
- ? sanitize_text_field( wp_unslash( $_GET['currency'] ) )
 
 
 
187
  : wcml_get_woocommerce_currency_option();
188
- // phpcs:enable WordPress.Security.NonceVerification.Recommended
189
  }
190
 
191
  }
4
 
5
  use WCML\Utilities\Resources;
6
  use WCML\Rest\Functions;
7
+ use WCML\StandAlone\IStandAloneAction;
8
  use WPML\FP\Obj;
9
  use WPML\FP\Fns;
10
+ use WCML\Utilities\WpAdminPages;
11
 
12
+ class Hooks implements \IWPML_Action, IStandAloneAction {
13
 
14
  /** @var \woocommerce_wpml $woocommerce_wpml */
15
  private $woocommerce_wpml;
183
  }
184
 
185
  private function getCurrency() {
186
+ $rawCurrency = WpAdminPages::isDashboard()
187
+ ? Obj::prop( '_wcml_dashboard_currency', $_COOKIE )
188
+ : Obj::prop( 'currency', $_GET );
189
+
190
+ return $rawCurrency
191
+ ? sanitize_text_field( wp_unslash( $rawCurrency ) )
192
  : wcml_get_woocommerce_currency_option();
 
193
  }
194
 
195
  }
classes/Multicurrency/Resolver/ComposedResolver.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WPML\FP\Fns;
6
+ use WPML\FP\Logic;
7
+ use WPML\FP\Lst;
8
+
9
+ class ComposedResolver implements Resolver {
10
+
11
+ /**
12
+ * @var callable
13
+ */
14
+ private $get;
15
+
16
+ /**
17
+ * @param Resolver[] $resolvers
18
+ */
19
+ public function __construct( array $resolvers ) {
20
+ $this->get = Logic::firstSatisfying(
21
+ Logic::isNotNull(),
22
+ Fns::map( Lst::makePair( Fns::__, 'getClientCurrency' ), $resolvers )
23
+ );
24
+ }
25
+
26
+ /**
27
+ * @return string
28
+ */
29
+ public function getClientCurrency() {
30
+ return call_user_func( $this->get, null );
31
+ }
32
+ }
classes/Multicurrency/Resolver/Factory.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Settings;
6
+
7
+ class Factory {
8
+
9
+ /**
10
+ * @return Resolver
11
+ */
12
+ public static function create() {
13
+ // $getOriginalProductLang :: int|string -> string|null
14
+ $getOriginalProductLang = function( $productId ) {
15
+ /** @var \woocommerce_wpml $woocommerce_wpml */
16
+ global $woocommerce_wpml;
17
+
18
+ return $woocommerce_wpml->products->get_original_product_language( $productId );
19
+ };
20
+
21
+ return new ComposedResolver( [
22
+ new ResolverForContext( $getOriginalProductLang ),
23
+ Settings::isModeByLocation() ? new ResolverForModeLocation() : new ResolverForModeLanguage(),
24
+ new ResolverForDefault(),
25
+ ] );
26
+ }
27
+ }
classes/Multicurrency/Resolver/HelperByLanguage.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Geolocation;
6
+ use WCML\MultiCurrency\Settings;
7
+ use WPML\FP\Fns;
8
+ use function WCML\functions\getSitePress;
9
+
10
+ class HelperByLanguage {
11
+
12
+ /** @var null|callable $getCurrency */
13
+ private static $getCurrency;
14
+
15
+ /**
16
+ * @param string $currentLang
17
+ *
18
+ * @return string|null
19
+ */
20
+ public static function getCurrencyByUserCountry( $currentLang ) {
21
+ if ( ! self::$getCurrency ) {
22
+ self::$getCurrency = Fns::memorize( function() use ( $currentLang ) {
23
+ $clientCountry = Geolocation::getUserCountry();
24
+ $currency = Geolocation::getOfficialCurrencyCodeByCountry( $clientCountry );
25
+
26
+ if ( ! Settings::isValidCurrencyForLang( $currency, $currentLang ) ) {
27
+ $currency = Settings::getFirstAvailableCurrencyForLang( $currentLang );
28
+ }
29
+
30
+ return $currency ?: null;
31
+ } );
32
+ }
33
+
34
+ return call_user_func( self::$getCurrency );
35
+ }
36
+
37
+
38
+ /**
39
+ * @return string|null
40
+ */
41
+ public static function getCurrentLanguage() {
42
+ /** @var string|null $currentLang */
43
+ $currentLang = getSitePress()->get_current_language();
44
+
45
+ return in_array( $currentLang, [ 'all', null ], true )
46
+ ? getSitePress()->get_default_language()
47
+ : $currentLang;
48
+ }
49
+ }
classes/Multicurrency/Resolver/HelperByLocation.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Geolocation;
6
+ use WCML\MultiCurrency\Settings;
7
+ use WPML\FP\Fns;
8
+
9
+ class HelperByLocation {
10
+
11
+ /** @var null|callable $getCurrency */
12
+ private static $getCurrency;
13
+
14
+ /**
15
+ * @return string|null
16
+ */
17
+ public static function getCurrencyByUserCountry() {
18
+ if ( ! self::$getCurrency ) {
19
+ self::$getCurrency = Fns::memorize( function() {
20
+ $clientCountry = Geolocation::getUserCountry();
21
+ $currency = Geolocation::getOfficialCurrencyCodeByCountry( $clientCountry );
22
+
23
+ if ( ! Settings::isValidCurrencyByCountry( $currency, $clientCountry ) ) {
24
+ $currency = Settings::getFirstAvailableCurrencyByCountry( $clientCountry );
25
+ }
26
+
27
+ return $currency ?: null;
28
+ } );
29
+ }
30
+
31
+ return call_user_func( self::$getCurrency );
32
+ }
33
+ }
classes/Multicurrency/Resolver/Resolver.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ interface Resolver {
6
+
7
+ /**
8
+ * @return string|null
9
+ */
10
+ public function getClientCurrency();
11
+ }
classes/Multicurrency/Resolver/ResolverForContext.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Settings;
6
+ use WPML\FP\Logic;
7
+ use WPML\FP\Obj;
8
+ use WPML\FP\Relation;
9
+
10
+ class ResolverForContext implements Resolver {
11
+
12
+ /** @var callable $getOriginalProductLanguage */
13
+ private $getOriginalProductLanguage;
14
+
15
+ public function __construct( callable $getOriginalProductLanguage ) {
16
+ $this->getOriginalProductLanguage = $getOriginalProductLanguage;
17
+ }
18
+
19
+ /**
20
+ * @inheritDoc
21
+ */
22
+ public function getClientCurrency() {
23
+ $getOnWoocommerceQuickEdit = function() {
24
+ if ( ! empty( $_REQUEST['woocommerce_quick_edit'] ) ) {
25
+ return wcml_get_woocommerce_currency_option();
26
+ }
27
+
28
+ return null;
29
+ };
30
+
31
+ $getIfMissingCustomPrice = function() {
32
+ if ( Settings::isDisplayOnlyCustomPrices() && is_product() ) {
33
+ $product = wc_get_product();
34
+ $originalProductLanguage = call_user_func( $this->getOriginalProductLanguage, $product->get_id() );
35
+
36
+ // $isMissingCustomPrice :: int -> bool
37
+ $isMissingCustomPrice = function( $productOrVariationId ) use ( $originalProductLanguage ) {
38
+ return ! get_post_meta(
39
+ apply_filters( 'wpml_object_id', $productOrVariationId, get_post_type( $productOrVariationId ), true, $originalProductLanguage ),
40
+ '_wcml_custom_prices_status',
41
+ true
42
+ );
43
+ };
44
+
45
+ if ( $product->get_type() === 'variable' ) {
46
+ foreach ( $product->get_children() as $child ) {
47
+ if ( $isMissingCustomPrice( $child ) ) {
48
+ return wcml_get_woocommerce_currency_option();
49
+ }
50
+ }
51
+ } elseif ( $isMissingCustomPrice( $product->get_id() ) ) {
52
+ return wcml_get_woocommerce_currency_option();
53
+ }
54
+ }
55
+
56
+ return null;
57
+ };
58
+
59
+ $getOnPayForOrder = function() {
60
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
61
+ if ( isset( $_GET['pay_for_order'], $_GET['key'] ) && $_GET['pay_for_order'] ) {
62
+ $cacheGroup = 'wcml_client_currency';
63
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
64
+ $cacheKey = 'order' . sanitize_text_field( $_GET['key'] );
65
+ $orderCurrency = wp_cache_get( $cacheKey, $cacheGroup );
66
+
67
+ if ( $orderCurrency ) {
68
+ return $orderCurrency;
69
+ } else {
70
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
71
+ $orderId = wc_get_order_id_by_order_key( wc_clean( wp_unslash( $_GET['key'] ) ) );
72
+ if ( $orderId ) {
73
+ $clientCurrency = get_post_meta( $orderId, '_order_currency', true );
74
+ wp_cache_set( $cacheKey, $clientCurrency, $cacheGroup );
75
+ return $clientCurrency;
76
+ }
77
+ }
78
+ }
79
+
80
+ return null;
81
+ };
82
+
83
+ $getOnSearchProductsFromOrderCurrencyCookie = function() {
84
+ if ( Relation::propEq( 'action', 'woocommerce_json_search_products_and_variations', $_GET ) ) {
85
+ return Obj::prop( '_wcml_order_currency', $_COOKIE );
86
+ }
87
+
88
+ return null;
89
+ };
90
+
91
+ $getFromHttpRefererShopOrderCurrency = function() {
92
+ $refererUrl = Obj::prop( 'HTTP_REFERER', $_SERVER );
93
+
94
+ if ( $refererUrl ) {
95
+ $query = parse_url( $refererUrl, PHP_URL_QUERY );
96
+
97
+ if ( $query ) {
98
+ parse_str( $query, $queryArgs );
99
+ $postId = Obj::prop( 'post', $queryArgs );
100
+
101
+ if ( $postId && get_post_type( $postId ) === 'shop_order' ) {
102
+ return get_post_meta( $postId, '_order_currency', true );
103
+ }
104
+ }
105
+ }
106
+
107
+ return null;
108
+ };
109
+
110
+ $resolve = Logic::firstSatisfying(
111
+ Logic::isTruthy(),
112
+ [
113
+ $getOnWoocommerceQuickEdit,
114
+ $getIfMissingCustomPrice,
115
+ $getOnPayForOrder,
116
+ $getOnSearchProductsFromOrderCurrencyCookie,
117
+ $getFromHttpRefererShopOrderCurrency,
118
+ ]
119
+ );
120
+
121
+ return $resolve( null );
122
+ }
123
+ }
classes/Multicurrency/Resolver/ResolverForDefault.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ class ResolverForDefault implements Resolver {
6
+
7
+ /**
8
+ * We consider that we should always be able to resolve a currency
9
+ * for any customer.
10
+ *
11
+ * If no currency could be found in the previous steps, we'll
12
+ * fall back to the default WC currency.
13
+ *
14
+ * @inheritDoc
15
+ */
16
+ public function getClientCurrency() {
17
+ return wcml_get_woocommerce_currency_option();
18
+ }
19
+ }
classes/Multicurrency/Resolver/ResolverForModeLanguage.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Settings;
6
+ use WCML_Multi_Currency;
7
+ use WPML\FP\Logic;
8
+
9
+ class ResolverForModeLanguage implements Resolver {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function getClientCurrency() {
15
+ /** @var string $currentLang */
16
+ $currentLang = HelperByLanguage::getCurrentLanguage();
17
+ $storedLang = wcml_user_store_get( WCML_Multi_Currency::CURRENCY_LANGUAGE_STORAGE_KEY );
18
+ $storedCurrency = wcml_user_store_get( WCML_Multi_Currency::CURRENCY_STORAGE_KEY );
19
+
20
+ $getInitialCurrencyForLang = function() use ( $currentLang ) {
21
+ return Settings::isDefaultCurrencyByLocationForLang( $currentLang )
22
+ ? HelperByLanguage::getCurrencyByUserCountry( $currentLang )
23
+ : Settings::getDefaultCurrencyForLang( $currentLang );
24
+ };
25
+
26
+ $reInitCurrencyIfLangHasChanged = function() use ( $currentLang, $storedLang, $storedCurrency, $getInitialCurrencyForLang ) {
27
+ $hasChangedLang = $storedLang && $currentLang !== $storedLang;
28
+
29
+ if ( $hasChangedLang ) {
30
+ $initialCurrencyForLang = $getInitialCurrencyForLang();
31
+
32
+ if ( $initialCurrencyForLang ) {
33
+ $preventSwitching = apply_filters( 'wcml_switch_currency_exception', false, $storedCurrency, $initialCurrencyForLang, true );
34
+
35
+ if ( ! array_key_exists( 'force_switch', $_POST ) && $preventSwitching ) {
36
+ do_action( 'wcml_multi_currency_set_switching_currency_html', $preventSwitching['prevent_switching'] );
37
+ }
38
+
39
+ return $initialCurrencyForLang;
40
+ }
41
+ }
42
+
43
+ return null;
44
+ };
45
+
46
+ $getStoredCurrencyIfValid = function() use ( $currentLang, $storedCurrency ) {
47
+ return Settings::isValidCurrencyForLang( $storedCurrency, $currentLang )
48
+ ? $storedCurrency
49
+ : null;
50
+ };
51
+
52
+ $getDefaultCurrencyIfValid = function() use ( $currentLang ) {
53
+ $defaultCurrency = wcml_get_woocommerce_currency_option();
54
+
55
+ return Settings::isValidCurrencyForLang( $defaultCurrency, $currentLang )
56
+ ? $defaultCurrency
57
+ : null;
58
+ };
59
+
60
+ $getFirstAvailableCurrencyForLang = function() use ( $currentLang ) {
61
+ return Settings::getFirstAvailableCurrencyForLang( $currentLang );
62
+ };
63
+
64
+ $resolve = Logic::firstSatisfying(
65
+ Logic::isTruthy(),
66
+ [
67
+ $reInitCurrencyIfLangHasChanged,
68
+ $getStoredCurrencyIfValid,
69
+ $getInitialCurrencyForLang,
70
+ $getDefaultCurrencyIfValid,
71
+ $getFirstAvailableCurrencyForLang,
72
+ ]
73
+ );
74
+
75
+ return $resolve( null );
76
+ }
77
+ }
classes/Multicurrency/Resolver/ResolverForModeLocation.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\Resolver;
4
+
5
+ use WCML\MultiCurrency\Geolocation;
6
+ use WCML\MultiCurrency\Settings;
7
+ use WCML_Multi_Currency;
8
+
9
+ class ResolverForModeLocation implements Resolver {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function getClientCurrency() {
15
+ $storedCurrency = wcml_user_store_get( WCML_Multi_Currency::CURRENCY_STORAGE_KEY );
16
+
17
+ // $isCurrencyInvalidInCountry :: string -> bool
18
+ $isCurrencyInvalidInCountry = function( $currency ) {
19
+ return ! Settings::isValidCurrencyByCountry( $currency, Geolocation::getUserCountry() );
20
+ };
21
+
22
+ if ( ! $storedCurrency ) {
23
+ return HelperByLocation::getCurrencyByUserCountry();
24
+ } elseif ( $isCurrencyInvalidInCountry( $storedCurrency ) ) {
25
+ return HelperByLocation::getCurrencyByUserCountry();
26
+ }
27
+
28
+ return $storedCurrency;
29
+ }
30
+ }
classes/Multicurrency/Settings.php ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency;
4
+
5
+ use WPML\FP\Fns;
6
+ use WPML\FP\Lst;
7
+ use WPML\FP\Obj;
8
+ use WPML\FP\Relation;
9
+ use function WCML\functions\getSetting;
10
+ use function WCML\functions\isStandAlone;
11
+ use function WCML\functions\updateSetting;
12
+
13
+ class Settings {
14
+
15
+ const MODE_BY_LANGUAGE = 'by_language';
16
+ const MODE_BY_LOCATION = 'by_location';
17
+
18
+ /**
19
+ * @return string|null
20
+ */
21
+ public static function getMode() {
22
+ $persistedMode = getSetting( 'currency_mode' );
23
+
24
+ // Force location mode at runtime in standalone
25
+ // to preserve settings in case of temporary change.
26
+ if ( self::MODE_BY_LANGUAGE === $persistedMode && isStandAlone() ) {
27
+ return self::MODE_BY_LOCATION;
28
+ }
29
+
30
+ return $persistedMode;
31
+ }
32
+
33
+ /**
34
+ * @return bool
35
+ */
36
+ public static function isModeByLanguage() {
37
+ return self::getMode() === self::MODE_BY_LANGUAGE;
38
+ }
39
+
40
+ /**
41
+ * @return bool
42
+ */
43
+ public static function isModeByLocation() {
44
+ return self::getMode() === self::MODE_BY_LOCATION;
45
+ }
46
+
47
+ /**
48
+ * @param string $mode
49
+ *
50
+ * @return void
51
+ */
52
+ public static function setMode( $mode ) {
53
+ updateSetting( 'currency_mode', $mode );
54
+ }
55
+
56
+ /**
57
+ * @return bool
58
+ */
59
+ public static function isDisplayOnlyCustomPrices() {
60
+ return (bool) getSetting( 'display_custom_prices' );
61
+ }
62
+
63
+ /**
64
+ * @param string $code
65
+ *
66
+ * @return bool
67
+ */
68
+ public static function isActiveCurrency( $code ) {
69
+ return Lst::includes( $code, self::getActiveCurrencyCodes() );
70
+ }
71
+
72
+ /**
73
+ * @return array
74
+ */
75
+ public static function getActiveCurrencyCodes() {
76
+ return Obj::keys( self::getCurrenciesOptions() );
77
+ }
78
+
79
+ /**
80
+ * @return array
81
+ */
82
+ public static function getCurrenciesOptions() {
83
+ return (array) getSetting( 'currency_options' );
84
+ }
85
+
86
+ /**
87
+ * @param string|array $keyOrPath
88
+ * @param mixed|null $default
89
+ *
90
+ * @return mixed
91
+ */
92
+ public static function getCurrenciesOption( $keyOrPath, $default = null ) {
93
+ return Obj::pathOr( $default, (array) $keyOrPath, self::getCurrenciesOptions() );
94
+ }
95
+
96
+ /**
97
+ * @param string $currency
98
+ * @param string $clientCountry
99
+ *
100
+ * @return bool
101
+ */
102
+ public static function isValidCurrencyByCountry( $currency, $clientCountry ) {
103
+ $currencySettings = self::getCurrenciesOption( $currency );
104
+
105
+ // $isLocationMode :: string -> bool
106
+ $isLocationMode = Relation::propEq( 'location_mode', Fns::__, $currencySettings );
107
+
108
+ // $containsCountry :: string -> bool
109
+ $containsCountry = Lst::includes( Fns::__, (array) Obj::prop( 'countries', $currencySettings ) );
110
+
111
+ if ( $isLocationMode( 'all' ) ) {
112
+ return true;
113
+ } elseif ( $isLocationMode( 'include' ) && $containsCountry( $clientCountry ) ) {
114
+ return true;
115
+ } elseif ( $isLocationMode( 'exclude' ) && ! $containsCountry( $clientCountry ) ) {
116
+ return true;
117
+ }
118
+
119
+ return false;
120
+ }
121
+
122
+ /**
123
+ * @param string $country
124
+ *
125
+ * @return string|null
126
+ */
127
+ public static function getFirstAvailableCurrencyByCountry( $country ) {
128
+ // $isValidCurrency :: string -> bool
129
+ $isValidCurrency = function( $currency ) use ( $country ) {
130
+ return self::isValidCurrencyByCountry( $currency, $country );
131
+ };
132
+
133
+ return wpml_collect( self::getActiveCurrencyCodes() )->first( $isValidCurrency );
134
+ }
135
+
136
+ /**
137
+ * @return array
138
+ */
139
+ public static function getDefaultCurrencies() {
140
+ return (array) getSetting( 'default_currencies' );
141
+ }
142
+
143
+ /**
144
+ * @return array
145
+ */
146
+ public static function getOrderedCurrencyCodes() {
147
+ return (array) getSetting( 'currencies_order' ) ?: self::getActiveCurrencyCodes();
148
+ }
149
+
150
+ /**
151
+ * @param string $lang
152
+ *
153
+ * @return bool
154
+ */
155
+ public static function isDefaultCurrencyByLocationForLang( $lang ) {
156
+ return 'location' === self::getDefaultCurrencyForLang( $lang );
157
+ }
158
+
159
+ /**
160
+ * @param string $lang
161
+ *
162
+ * @return string A real currency (e.g. "USD") or "location" or a falsy string for "keep" (default).
163
+ */
164
+ public static function getDefaultCurrencyForLang( $lang ) {
165
+ return (string) Obj::propOr( '', $lang, self::getDefaultCurrencies() );
166
+ }
167
+
168
+ /**
169
+ * @param string $currency
170
+ * @param string $lang
171
+ *
172
+ * @return bool
173
+ */
174
+ public static function isValidCurrencyForLang( $currency, $lang ) {
175
+ return (bool) self::getCurrenciesOption( [ $currency, 'languages', $lang ] );
176
+ }
177
+
178
+ /**
179
+ * @param string $lang
180
+ *
181
+ * @return string|null
182
+ */
183
+ public static function getFirstAvailableCurrencyForLang( $lang ) {
184
+ return (string) wpml_collect( self::getCurrenciesOptions() )
185
+ ->filter( Obj::path( [ 'languages', $lang ] ) )
186
+ ->keys()
187
+ ->first();
188
+ }
189
+
190
+ /**
191
+ * @return bool
192
+ */
193
+ public static function isAutomaticRateEnabled() {
194
+ return (bool) Obj::prop( 'automatic', self::getAutomaticRateSettings() );
195
+ }
196
+
197
+ /**
198
+ * @return array
199
+ */
200
+ private static function getAutomaticRateSettings() {
201
+ return Obj::propOr( [], 'exchange_rates', getSetting( 'multi_currency', [] ) );
202
+ }
203
+ }
classes/Multicurrency/Shipping/AdminHooks.php CHANGED
@@ -3,9 +3,10 @@
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
  use IWPML_Action;
 
6
  use WCML_Multi_Currency;
7
 
8
- class AdminHooks implements IWPML_Action {
9
  const WCML_SHIPPING_COSTS = 'wcml_shipping_costs';
10
 
11
  /** @var WCML_Multi_Currency */
@@ -70,7 +71,7 @@ class AdminHooks implements IWPML_Action {
70
  'title' => __( 'Costs and values in custom currencies', 'woocommerce-multilingual' ),
71
  'type' => 'title',
72
  'default' => '',
73
- 'description' => __( 'Woocommerce Multilingual by default will multiply all your costs and values defined above by currency exchange rates. If you don\'t want this and you prefer static values instead, you can define them here.', 'woocommerce-multilingual' ),
74
  ];
75
  return $field;
76
  }
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
  use IWPML_Action;
6
+ use WCML\StandAlone\IStandAloneAction;
7
  use WCML_Multi_Currency;
8
 
9
+ class AdminHooks implements IWPML_Action, IStandAloneAction {
10
  const WCML_SHIPPING_COSTS = 'wcml_shipping_costs';
11
 
12
  /** @var WCML_Multi_Currency */
71
  'title' => __( 'Costs and values in custom currencies', 'woocommerce-multilingual' ),
72
  'type' => 'title',
73
  'default' => '',
74
+ 'description' => __( 'WooCommerce Multilingual & Multicurrency by default will multiply all your costs and values defined above by currency exchange rates. If you don\'t want this and you prefer static values instead, you can define them here.', 'woocommerce-multilingual' ),
75
  ];
76
  return $field;
77
  }
classes/Multicurrency/Shipping/FreeShipping.php CHANGED
@@ -10,6 +10,8 @@ class FreeShipping implements ShippingMode {
10
  if ( ! is_string( $currencyCode ) ) {
11
  $currencyCode = '';
12
  }
 
 
13
  return sprintf( esc_html_x( 'Minimal order amount in %s',
14
  'The label for the field with minimal order amount in additional currency. The currency symbol will be added in place of %s specifier.',
15
  'woocommerce-multilingual' ), $currencyCode );
@@ -19,6 +21,8 @@ class FreeShipping implements ShippingMode {
19
  if ( ! is_string( $currencyCode ) ) {
20
  $currencyCode = '';
21
  }
 
 
22
  return sprintf( esc_html_x( 'The minimal order amount if customer choose %s as a purchase currency.',
23
  'The description for the field with minimal order amount in additional currency. The currency symbol will be added in place of %s specifier.',
24
  'woocommerce-multilingual' ), $currencyCode );
10
  if ( ! is_string( $currencyCode ) ) {
11
  $currencyCode = '';
12
  }
13
+
14
+ /* translators: %s is the currency code */
15
  return sprintf( esc_html_x( 'Minimal order amount in %s',
16
  'The label for the field with minimal order amount in additional currency. The currency symbol will be added in place of %s specifier.',
17
  'woocommerce-multilingual' ), $currencyCode );
21
  if ( ! is_string( $currencyCode ) ) {
22
  $currencyCode = '';
23
  }
24
+
25
+ /* translators: %s is the currency code */
26
  return sprintf( esc_html_x( 'The minimal order amount if customer choose %s as a purchase currency.',
27
  'The description for the field with minimal order amount in additional currency. The currency symbol will be added in place of %s specifier.',
28
  'woocommerce-multilingual' ), $currencyCode );
classes/Multicurrency/Shipping/FrontEndHooks.php CHANGED
@@ -3,8 +3,9 @@
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
  use IWPML_Action;
 
6
 
7
- class FrontEndHooks implements IWPML_Action {
8
 
9
  private $multiCurrency;
10
 
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
  use IWPML_Action;
6
+ use WCML\StandAlone\IStandAloneAction;
7
 
8
+ class FrontEndHooks implements IWPML_Action, IStandAloneAction {
9
 
10
  private $multiCurrency;
11
 
classes/Multicurrency/Shipping/ShippingClasses.php CHANGED
@@ -59,7 +59,8 @@ class ShippingClasses {
59
  protected static function askToSwitchLanguage( $field, $shippingClass, $classSourceLanguageCode ) {
60
  $field[ 'wcml_ask_to_switch_language_' . $shippingClass->term_id ] = [
61
  'title' => '',
62
- 'description' => sprintf( __( 'Your shipping class %s has been created in %s language. Please switch your language if you want to provide shipping costs in different currencies for this class.', 'woocommerce-multilingual' ),
 
63
  $shippingClass->name,
64
  $classSourceLanguageCode),
65
  'type' => 'title'
@@ -69,7 +70,8 @@ class ShippingClasses {
69
 
70
  protected static function addShippingClassField( $field, $shippingClass, $currencyCode ) {
71
  $field[ 'class_cost_' . $shippingClass->term_id . '_' . $currencyCode ] = [
72
- 'title' => sprintf( __( '"%s" shipping class cost in %s', 'woocommerce-multilingual' ), esc_html( $shippingClass->name ), esc_html( $currencyCode ) ),
 
73
  'type' => 'text',
74
  'placeholder' => __( 'N/A', 'woocommerce-multilingual' ),
75
  'class' => 'wcml-shipping-cost-currency'
@@ -79,6 +81,7 @@ class ShippingClasses {
79
 
80
  protected static function addNoShippingClassField( $field, $currencyCode ) {
81
  $field[ 'no_class_cost_' . $currencyCode ] = [
 
82
  'title' => sprintf( __( 'No shipping class cost in %s', 'woocommerce-multilingual' ), esc_html( $currencyCode ) ),
83
  'type' => 'text',
84
  'placeholder' => __( 'N/A', 'woocommerce-multilingual' ),
59
  protected static function askToSwitchLanguage( $field, $shippingClass, $classSourceLanguageCode ) {
60
  $field[ 'wcml_ask_to_switch_language_' . $shippingClass->term_id ] = [
61
  'title' => '',
62
+ /* translators: %1$s is a shipping class name and %2$s is a language code */
63
+ 'description' => sprintf( __( 'Your shipping class %1$s has been created in %2$s language. Please switch your language if you want to provide shipping costs in different currencies for this class.', 'woocommerce-multilingual' ),
64
  $shippingClass->name,
65
  $classSourceLanguageCode),
66
  'type' => 'title'
70
 
71
  protected static function addShippingClassField( $field, $shippingClass, $currencyCode ) {
72
  $field[ 'class_cost_' . $shippingClass->term_id . '_' . $currencyCode ] = [
73
+ /* translators: %1$s is a shipping class name and %2$s is a currency code */
74
+ 'title' => sprintf( __( '"%1$s" shipping class cost in %2$s', 'woocommerce-multilingual' ), esc_html( $shippingClass->name ), esc_html( $currencyCode ) ),
75
  'type' => 'text',
76
  'placeholder' => __( 'N/A', 'woocommerce-multilingual' ),
77
  'class' => 'wcml-shipping-cost-currency'
81
 
82
  protected static function addNoShippingClassField( $field, $currencyCode ) {
83
  $field[ 'no_class_cost_' . $currencyCode ] = [
84
+ /* translators: %s is a currency code */
85
  'title' => sprintf( __( 'No shipping class cost in %s', 'woocommerce-multilingual' ), esc_html( $currencyCode ) ),
86
  'type' => 'text',
87
  'placeholder' => __( 'N/A', 'woocommerce-multilingual' ),
classes/Multicurrency/Shipping/ShippingHooksFactory.php CHANGED
@@ -2,7 +2,9 @@
2
 
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
- class ShippingHooksFactory implements \IWPML_Deferred_Action_Loader, \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader {
 
 
6
 
7
  public function get_load_action() {
8
  return 'init';
2
 
3
  namespace WCML\Multicurrency\Shipping;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ class ShippingHooksFactory implements \IWPML_Deferred_Action_Loader, \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader, IStandAloneAction {
8
 
9
  public function get_load_action() {
10
  return 'init';
classes/Multicurrency/Shipping/VariableCost.php CHANGED
@@ -13,6 +13,7 @@ trait VariableCost {
13
  * return string
14
  */
15
  public function getFieldTitle( $currencyCode ) {
 
16
  return sprintf( esc_html_x( 'Cost in %s',
17
  'The label for the field with shipping cost in additional currency. The currency symbol will be added in place of %s specifier.',
18
  'woocommerce-multilingual' ), $currencyCode );
@@ -26,6 +27,7 @@ trait VariableCost {
26
  * @return string
27
  */
28
  public function getFieldDescription( $currencyCode ) {
 
29
  return sprintf( esc_html_x( 'The shipping cost if customer choose %s as a purchase currency.',
30
  'The description for the field with shipping cost in additional currency. The currency symbol will be added in place of %s specifier.',
31
  'woocommerce-multilingual' ), $currencyCode );
13
  * return string
14
  */
15
  public function getFieldTitle( $currencyCode ) {
16
+ /* translators: %s is a currency code */
17
  return sprintf( esc_html_x( 'Cost in %s',
18
  'The label for the field with shipping cost in additional currency. The currency symbol will be added in place of %s specifier.',
19
  'woocommerce-multilingual' ), $currencyCode );
27
  * @return string
28
  */
29
  public function getFieldDescription( $currencyCode ) {
30
+ /* translators: %s is a currency code */
31
  return sprintf( esc_html_x( 'The shipping cost if customer choose %s as a purchase currency.',
32
  'The description for the field with shipping cost in additional currency. The currency symbol will be added in place of %s specifier.',
33
  'woocommerce-multilingual' ), $currencyCode );
classes/Multicurrency/Transient/Hooks.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Multicurrency\Transient;
4
+
5
+ use WCML\MultiCurrency\Settings as McSettings;
6
+ use WPML\FP\Fns;
7
+ use WPML\FP\Str;
8
+ use WPML\LIB\WP\Hooks as WpHooks;
9
+ use function WCML\functions\getClientCurrency;
10
+ use function WPML\FP\spreadArgs;
11
+
12
+ class Hooks {
13
+
14
+ /**
15
+ * @param string $key
16
+ */
17
+ public static function addHooks( $key ) {
18
+ $getKeyWithCurrency = Str::concat( $key . '_' );
19
+ $getKeyWithClientCurrency = function() use ( $getKeyWithCurrency ) {
20
+ return $getKeyWithCurrency( getClientCurrency() );
21
+ };
22
+
23
+ $getTransient = function() use ( $getKeyWithClientCurrency ) {
24
+ return get_transient( $getKeyWithClientCurrency() );
25
+ };
26
+
27
+ $setTransient = function( $value ) use ( $key, $getKeyWithClientCurrency ) {
28
+ delete_transient( $key );
29
+ return set_transient( $getKeyWithClientCurrency(), $value );
30
+ };
31
+
32
+ $deleteTransient = function() use ( $getKeyWithCurrency ) {
33
+ foreach ( McSettings::getActiveCurrencyCodes() as $code ) {
34
+ delete_transient( $getKeyWithCurrency( $code ) );
35
+ }
36
+ };
37
+
38
+ $withLock = Fns::withNamedLock( __CLASS__ . "_$key", Fns::identity() );
39
+
40
+ WpHooks::onFilter( 'pre_transient_' . $key )
41
+ ->then( $getTransient );
42
+
43
+ WpHooks::onAction( 'set_transient_' . $key )
44
+ ->then( spreadArgs( $withLock( $setTransient ) ) );
45
+
46
+ WpHooks::onAction( 'delete_transient_' . $key )
47
+ ->then( $withLock( $deleteTransient ) );
48
+ }
49
+
50
+ }
classes/Multicurrency/UI/Factory.php CHANGED
@@ -2,9 +2,12 @@
2
 
3
  namespace WCML\Multicurrency\UI;
4
 
 
 
 
5
  use function WPML\Container\make;
6
 
7
- class Factory implements \IWPML_Backend_Action_Loader, \IWPML_Deferred_Action_Loader {
8
 
9
  public function get_load_action() {
10
  return 'init';
@@ -17,7 +20,7 @@ class Factory implements \IWPML_Backend_Action_Loader, \IWPML_Deferred_Action_Lo
17
  /** @var \woocommerce_wpml $woocommerce_wpml */
18
  global $woocommerce_wpml;
19
 
20
- if ( self::isMultiCurrencySettings() ) {
21
  return make(
22
  Hooks::class,
23
  [
@@ -28,13 +31,4 @@ class Factory implements \IWPML_Backend_Action_Loader, \IWPML_Deferred_Action_Lo
28
 
29
  return null;
30
  }
31
-
32
- /**
33
- * @return bool
34
- */
35
- public static function isMultiCurrencySettings() {
36
- return isset( $_GET['page'], $_GET['tab'] )
37
- && 'wpml-wcml' === $_GET['page']
38
- && 'multi-currency' === $_GET['tab'];
39
- }
40
- }
2
 
3
  namespace WCML\Multicurrency\UI;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ use WCML\Utilities\AdminPages;
8
  use function WPML\Container\make;
9
 
10
+ class Factory implements \IWPML_Backend_Action_Loader, \IWPML_Deferred_Action_Loader, IStandAloneAction {
11
 
12
  public function get_load_action() {
13
  return 'init';
20
  /** @var \woocommerce_wpml $woocommerce_wpml */
21
  global $woocommerce_wpml;
22
 
23
+ if ( AdminPages::isMultiCurrency() && make( \WCML_Dependencies::class )->check() ) {
24
  return make(
25
  Hooks::class,
26
  [
31
 
32
  return null;
33
  }
34
+ }
 
 
 
 
 
 
 
 
 
classes/Multicurrency/UI/Hooks.php CHANGED
@@ -2,14 +2,16 @@
2
 
3
  namespace WCML\Multicurrency\UI;
4
 
5
- use WCML\MultiCurrency\Geolocation;
 
6
  use WCML\Utilities\Resources;
7
  use WPML\Collect\Support\Collection;
8
  use WPML\FP\Fns;
9
  use WPML\FP\Obj;
 
10
  use function WPML\FP\curryN;
11
 
12
- class Hooks implements \IWPML_Action {
13
 
14
  const HANDLE = 'wcml-multicurrency-options';
15
 
@@ -28,7 +30,7 @@ class Hooks implements \IWPML_Action {
28
  public function __construct(
29
  \WCML_Multi_Currency $multiCurrency,
30
  \WCML_Currencies_Payment_Gateways $currenciesPaymentGateways,
31
- \SitePress $sitepress,
32
  array $wcmlSettings
33
  ) {
34
  $this->multiCurrency = $multiCurrency;
@@ -48,15 +50,17 @@ class Hooks implements \IWPML_Action {
48
  $enqueue( [
49
  'name' => 'wcmlMultiCurrency',
50
  'data' => [
51
- 'endpoint' => self::HANDLE,
52
- 'activeCurrencies' => $this->getActiveCurrencies( $gateways ),
53
- 'allCurrencies' => $this->getAllCurrencies(),
54
- 'allCountries' => $this->getAllCountries(),
55
- 'languages' => $this->getLanguages(),
56
- 'gateways' => $gateways->toArray(),
57
- 'strings' => $this->getStrings(),
58
- 'mode' => $this->getMode(),
59
- 'maxMindKeyExist' => $this->checkMaxMindKeyExist(),
 
 
60
  ],
61
  ] );
62
  }
@@ -181,14 +185,18 @@ class Hooks implements \IWPML_Action {
181
  'labelKeep' => __( 'Keep', 'woocommerce-multilingual' ),
182
  'labelDelete' => __( 'Delete', 'woocommerce-multilingual' ),
183
  'labelCurrenciesToDisplay' => __( 'Currencies to display for each language', 'woocommerce-multilingual' ),
 
184
  'placeholderEnableFor' => __( 'Enable %1$s for %2$s', 'woocommerce-multilingual' ),
 
185
  'placeholderDisableFor' => __( 'Disable %1$s for %2$s', 'woocommerce-multilingual' ),
186
  'labelSettings' => __( 'Settings', 'woocommerce-multilingual' ),
187
  'labelAddNewCurrency' => __( 'Add new currency', 'woocommerce-multilingual' ),
 
188
  'placeholderCurrencySettingsFor' => __( 'Currency settings for %s', 'woocommerce-multilingual' ),
189
  'labelSelectCurrency' => __( 'Select currency', 'woocommerce-multilingual' ),
190
  'labelExchangeRate' => __( 'Exchange Rate', 'woocommerce-multilingual' ),
191
  'labelOnlyNumeric' => __( 'Only numeric', 'woocommerce-multilingual' ),
 
192
  'placeholderPreviousRate' => __( '(previous value: %s)', 'woocommerce-multilingual' ),
193
  'labelCurrencyPreview' => __( 'Currency Preview', 'woocommerce-multilingual' ),
194
  'labelPosition' => __( 'Currency Position', 'woocommerce-multilingual' ),
@@ -206,15 +214,18 @@ class Hooks implements \IWPML_Action {
206
  'optionDown' => __( 'Down', 'woocommerce-multilingual' ),
207
  'optionNearest' => __( 'Nearest', 'woocommerce-multilingual' ),
208
  'labelIncrement' => __( 'Increment for nearest integer', 'woocommerce-multilingual' ),
 
209
  'tooltipIncrement' => sprintf( __( 'The resulting price will be an increment of this value after initial rounding.%se.g.:', 'woocommerce-multilingual' ), '<br>' ) . '<br />' .
210
  __( '1454.07 &raquo; 1454 when set to 1', 'woocommerce-multilingual' ) . '<br />' .
211
  __( '1454.07 &raquo; 1450 when set to 10', 'woocommerce-multilingual' ) . '<br />' .
212
  __( '1454.07 &raquo; 1500 when set to 100', 'woocommerce-multilingual' ) . '<br />',
 
213
  'tooltipRounding' => sprintf( __( 'Round the converted price to the closest integer. %se.g. 15.78 becomes 16.00', 'woocommerce-multilingual' ), '<br />' ),
214
  'tooltipAutosubtract' => __( 'The value to be subtracted from the amount obtained previously.', 'woocommerce-multilingual' ) . '<br /><br />' .
215
  __( 'For 1454.07, when the increment for the nearest integer is 100 and the auto-subtract amount is 1, the resulting amount is 1499.', 'woocommerce-multilingual' ),
216
  'labelAutosubtract' => __( 'Autosubtract amount', 'woocommerce-multilingual' ),
217
  'labelPaymentGateways' => __( 'Payment Gateways', 'woocommerce-multilingual' ),
 
218
  'placeholderCustomSettings' => __( 'Custom settings for %s', 'woocommerce-multilingual' ),
219
  'linkUrlLearn' => $trackingLink->getWcmlMultiCurrencyDoc( '#payment-gateways-settings' ),
220
  'linkLabelLearn' => __( 'Learn more', 'woocommerce-multilingual' ),
@@ -227,19 +238,20 @@ class Hooks implements \IWPML_Action {
227
  'labelAllCountriesExceptDots' => __( 'All countries except...', 'woocommerce-multilingual' ),
228
  'labelSpecificCountries' => __( 'Specific countries', 'woocommerce-multilingual' ),
229
  'labelModeSelect' => __( 'Show currencies based on', 'woocommerce-multilingual' ),
230
- 'labelChooseOption' => __( 'Choose Option', 'woocommerce-multilingual' ),
 
231
  'labelSiteLanguage' => __( 'Site Language', 'woocommerce-multilingual' ),
232
  'labelClientLocation' => __( 'Client Location', 'woocommerce-multilingual' ),
233
  'labelLocationBased' => __( 'Location based', 'woocommerce-multilingual' ),
234
- 'maxMindDescription' => __( 'WooCommerce uses integration with MaxMind Geolocation in order to determine the correct location for the customer. You need to generate a free MaxMind Geolocation licence key.', 'woocommerce-multilingual' ),
235
  'maxMindSuccess' => __( 'Great! Now you can use Geolocation to determine default currency for chosen languages. You can edit that key in ', 'woocommerce-multilingual' ),
236
  'maxMindSettingLink' => admin_url( 'admin.php?page=wc-settings&tab=integration' ),
237
  'maxMindSettingLinkText' => __( 'WooCommerce settings page.', 'woocommerce-multilingual' ),
238
  'maxMindLabel' => __( 'MaxMind Licence Key', 'woocommerce-multilingual' ),
239
  'apply' => __( 'Apply', 'woocommerce-multilingual' ),
240
- 'maxMindDoc' => __( 'You can read how to generate one in ', 'woocommerce-multilingual' ),
241
  'maxMindDocLink' => 'https://docs.woocommerce.com/document/maxmind-geolocation-integration/',
242
- 'maxMindDocLinkText' => __( 'MaxMind Geolocation Integration documentation.', 'woocommerce-multilingual' ),
243
  ];
244
  }
245
 
@@ -258,13 +270,6 @@ class Hooks implements \IWPML_Action {
258
  return wpml_collect( WC()->countries->get_countries() )->map( $buildCountry )->values()->toArray();
259
  }
260
 
261
- /**
262
- * @return string
263
- */
264
- private function getMode(){
265
- return isset( $this->wcmlSettings['currency_mode'] ) ? $this->wcmlSettings['currency_mode'] : '';
266
- }
267
-
268
  /**
269
  * @return bool
270
  */
@@ -282,6 +287,7 @@ class Hooks implements \IWPML_Action {
282
  public static function formatLastRateUpdate( $lastRateUpdate ) {
283
  return $lastRateUpdate
284
  ? sprintf(
 
285
  __( 'Set on %s', 'woocommerce-multilingual' ),
286
  date( 'F j, Y g:i a', strtotime( $lastRateUpdate ) )
287
  )
2
 
3
  namespace WCML\Multicurrency\UI;
4
 
5
+ use WCML\MultiCurrency\Settings;
6
+ use WCML\StandAlone\IStandAloneAction;
7
  use WCML\Utilities\Resources;
8
  use WPML\Collect\Support\Collection;
9
  use WPML\FP\Fns;
10
  use WPML\FP\Obj;
11
+ use function WCML\functions\isStandAlone;
12
  use function WPML\FP\curryN;
13
 
14
+ class Hooks implements \IWPML_Action, IStandAloneAction {
15
 
16
  const HANDLE = 'wcml-multicurrency-options';
17
 
30
  public function __construct(
31
  \WCML_Multi_Currency $multiCurrency,
32
  \WCML_Currencies_Payment_Gateways $currenciesPaymentGateways,
33
+ \WPML\Core\ISitePress $sitepress,
34
  array $wcmlSettings
35
  ) {
36
  $this->multiCurrency = $multiCurrency;
50
  $enqueue( [
51
  'name' => 'wcmlMultiCurrency',
52
  'data' => [
53
+ 'endpoint' => self::HANDLE,
54
+ 'activeCurrencies' => $this->getActiveCurrencies( $gateways ),
55
+ 'allCurrencies' => $this->getAllCurrencies(),
56
+ 'allCountries' => $this->getAllCountries(),
57
+ 'languages' => $this->getLanguages(),
58
+ 'gateways' => $gateways->toArray(),
59
+ 'strings' => $this->getStrings(),
60
+ 'mode' => Settings::getMode(),
61
+ 'maxMindKeyExist' => $this->checkMaxMindKeyExist(),
62
+ 'isStandalone' => isStandAlone(),
63
+ 'isAutoRateEnabled' => Settings::isAutomaticRateEnabled(),
64
  ],
65
  ] );
66
  }
185
  'labelKeep' => __( 'Keep', 'woocommerce-multilingual' ),
186
  'labelDelete' => __( 'Delete', 'woocommerce-multilingual' ),
187
  'labelCurrenciesToDisplay' => __( 'Currencies to display for each language', 'woocommerce-multilingual' ),
188
+ /* translators: %1$s is for language name and %2$s for currency name */
189
  'placeholderEnableFor' => __( 'Enable %1$s for %2$s', 'woocommerce-multilingual' ),
190
+ /* translators: %1$s is for language name and %2$s for currency name */
191
  'placeholderDisableFor' => __( 'Disable %1$s for %2$s', 'woocommerce-multilingual' ),
192
  'labelSettings' => __( 'Settings', 'woocommerce-multilingual' ),
193
  'labelAddNewCurrency' => __( 'Add new currency', 'woocommerce-multilingual' ),
194
+ /* translators: %s for currency label */
195
  'placeholderCurrencySettingsFor' => __( 'Currency settings for %s', 'woocommerce-multilingual' ),
196
  'labelSelectCurrency' => __( 'Select currency', 'woocommerce-multilingual' ),
197
  'labelExchangeRate' => __( 'Exchange Rate', 'woocommerce-multilingual' ),
198
  'labelOnlyNumeric' => __( 'Only numeric', 'woocommerce-multilingual' ),
199
+ /* translators: %s for currency exchange rate value */
200
  'placeholderPreviousRate' => __( '(previous value: %s)', 'woocommerce-multilingual' ),
201
  'labelCurrencyPreview' => __( 'Currency Preview', 'woocommerce-multilingual' ),
202
  'labelPosition' => __( 'Currency Position', 'woocommerce-multilingual' ),
214
  'optionDown' => __( 'Down', 'woocommerce-multilingual' ),
215
  'optionNearest' => __( 'Nearest', 'woocommerce-multilingual' ),
216
  'labelIncrement' => __( 'Increment for nearest integer', 'woocommerce-multilingual' ),
217
+ /* translators: %s is an HTML break line */
218
  'tooltipIncrement' => sprintf( __( 'The resulting price will be an increment of this value after initial rounding.%se.g.:', 'woocommerce-multilingual' ), '<br>' ) . '<br />' .
219
  __( '1454.07 &raquo; 1454 when set to 1', 'woocommerce-multilingual' ) . '<br />' .
220
  __( '1454.07 &raquo; 1450 when set to 10', 'woocommerce-multilingual' ) . '<br />' .
221
  __( '1454.07 &raquo; 1500 when set to 100', 'woocommerce-multilingual' ) . '<br />',
222
+ /* translators: %s is an HTML break line */
223
  'tooltipRounding' => sprintf( __( 'Round the converted price to the closest integer. %se.g. 15.78 becomes 16.00', 'woocommerce-multilingual' ), '<br />' ),
224
  'tooltipAutosubtract' => __( 'The value to be subtracted from the amount obtained previously.', 'woocommerce-multilingual' ) . '<br /><br />' .
225
  __( 'For 1454.07, when the increment for the nearest integer is 100 and the auto-subtract amount is 1, the resulting amount is 1499.', 'woocommerce-multilingual' ),
226
  'labelAutosubtract' => __( 'Autosubtract amount', 'woocommerce-multilingual' ),
227
  'labelPaymentGateways' => __( 'Payment Gateways', 'woocommerce-multilingual' ),
228
+ /* translators: %s is a currency code */
229
  'placeholderCustomSettings' => __( 'Custom settings for %s', 'woocommerce-multilingual' ),
230
  'linkUrlLearn' => $trackingLink->getWcmlMultiCurrencyDoc( '#payment-gateways-settings' ),
231
  'linkLabelLearn' => __( 'Learn more', 'woocommerce-multilingual' ),
238
  'labelAllCountriesExceptDots' => __( 'All countries except...', 'woocommerce-multilingual' ),
239
  'labelSpecificCountries' => __( 'Specific countries', 'woocommerce-multilingual' ),
240
  'labelModeSelect' => __( 'Show currencies based on', 'woocommerce-multilingual' ),
241
+ 'labelSiteLanguageTooltip' => esc_html__( "You need the WPML plugin to make your store multilingual and display currencies based on site language. Don't have it yet?", 'woocommerce-multilingual' ) . '<br />' .
242
+ '<a href="' . \WCML_Tracking_Link::getWpmlPurchase( true ) . '" class="wpml-external-link" target="_blank">' . esc_html__( 'Purchase WPML now', 'woocommerce-multilingual' ) . '</a>',
243
  'labelSiteLanguage' => __( 'Site Language', 'woocommerce-multilingual' ),
244
  'labelClientLocation' => __( 'Client Location', 'woocommerce-multilingual' ),
245
  'labelLocationBased' => __( 'Location based', 'woocommerce-multilingual' ),
246
+ 'maxMindDescription' => __( 'WooCommerce integrates with MaxMind Geolocation to reliably determine the location of your customers.', 'woocommerce-multilingual' ),
247
  'maxMindSuccess' => __( 'Great! Now you can use Geolocation to determine default currency for chosen languages. You can edit that key in ', 'woocommerce-multilingual' ),
248
  'maxMindSettingLink' => admin_url( 'admin.php?page=wc-settings&tab=integration' ),
249
  'maxMindSettingLinkText' => __( 'WooCommerce settings page.', 'woocommerce-multilingual' ),
250
  'maxMindLabel' => __( 'MaxMind Licence Key', 'woocommerce-multilingual' ),
251
  'apply' => __( 'Apply', 'woocommerce-multilingual' ),
252
+ 'maxMindNote' => __( 'Please note: without a free MaxMind key, your geolocation calls will be limited and your site performance may be impacted.', 'woocommerce-multilingual' ),
253
  'maxMindDocLink' => 'https://docs.woocommerce.com/document/maxmind-geolocation-integration/',
254
+ 'maxMindDocLinkText' => __( 'Learn how to generate a free license key', 'woocommerce-multilingual' ),
255
  ];
256
  }
257
 
270
  return wpml_collect( WC()->countries->get_countries() )->map( $buildCountry )->values()->toArray();
271
  }
272
 
 
 
 
 
 
 
 
273
  /**
274
  * @return bool
275
  */
287
  public static function formatLastRateUpdate( $lastRateUpdate ) {
288
  return $lastRateUpdate
289
  ? sprintf(
290
+ /* translators: %s is a date */
291
  __( 'Set on %s', 'woocommerce-multilingual' ),
292
  date( 'F j, Y g:i a', strtotime( $lastRateUpdate ) )
293
  )
classes/Options/WPML.php CHANGED
@@ -22,4 +22,12 @@ class WPML {
22
  Automatic::set( $postType, $state );
23
  }
24
  }
 
 
 
 
 
 
 
 
25
  }
22
  Automatic::set( $postType, $state );
23
  }
24
  }
25
+
26
+ /**
27
+ * @return bool
28
+ */
29
+ public static function useAte() {
30
+ return method_exists( \WPML_TM_ATE_Status::class, 'is_enabled_and_activated' )
31
+ && \WPML_TM_ATE_Status::is_enabled_and_activated();
32
+ }
33
  }
classes/PaymentGateways/Hooks.php CHANGED
@@ -6,13 +6,14 @@ use IWPML_Backend_Action;
6
  use IWPML_Frontend_Action;
7
  use IWPML_DIC_Action;
8
  use WCML\MultiCurrency\Geolocation;
 
9
  use WCML\Utilities\Resources;
10
  use WPML\FP\Maybe;
11
  use WPML\FP\Obj;
12
  use WPML\FP\Relation;
13
 
14
 
15
- class Hooks implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action {
16
 
17
  const OPTION_KEY = 'wcml_payment_gateways';
18
  /* took this priority from wcgcl but we could not recall the reason of this number.*/
@@ -153,7 +154,7 @@ class Hooks implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Ac
153
 
154
  $text = '<div id="message" class="updated error">';
155
  $text .= '<p>';
156
- $text .= __( 'We noticed that you\'re using WooCommerce Gateways Country Limiter plugin which is now integrated into WooCommerce Multilingual. Please remove it!', 'woocommerce-multilingual' );
157
  $text .= '</p>';
158
  $text .= '</div>';
159
 
6
  use IWPML_Frontend_Action;
7
  use IWPML_DIC_Action;
8
  use WCML\MultiCurrency\Geolocation;
9
+ use WCML\StandAlone\IStandAloneAction;
10
  use WCML\Utilities\Resources;
11
  use WPML\FP\Maybe;
12
  use WPML\FP\Obj;
13
  use WPML\FP\Relation;
14
 
15
 
16
+ class Hooks implements IWPML_Backend_Action, IWPML_Frontend_Action, IWPML_DIC_Action, IStandAloneAction {
17
 
18
  const OPTION_KEY = 'wcml_payment_gateways';
19
  /* took this priority from wcgcl but we could not recall the reason of this number.*/
154
 
155
  $text = '<div id="message" class="updated error">';
156
  $text .= '<p>';
157
+ $text .= __( 'We noticed that you\'re using WooCommerce Gateways Country Limiter plugin which is now integrated into WooCommerce Multilingual & Multicurrency. Please remove it!', 'woocommerce-multilingual' );
158
  $text .= '</p>';
159
  $text .= '</div>';
160
 
classes/Reports/Orders/Factory.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
-
3
- namespace WCML\Reports\Orders;
4
-
5
- class Factory implements \IWPML_Backend_Action_Loader, \IWPML_REST_Action_Loader, \IWPML_Deferred_Action_Loader {
6
-
7
- /**
8
- * @return string
9
- */
10
- public function get_load_action() {
11
- return 'init';
12
- }
13
-
14
- /**
15
- * @return \IWPML_Action|null
16
- */
17
- public function create() {
18
- /**
19
- * @global \wpdb $GLOBALS['wpdb']
20
- * @name $wpdb
21
- */
22
- global $wpdb;
23
-
24
- if ( wcml_is_multi_currency_on() ) {
25
- return new Hooks( $wpdb );
26
- }
27
- }
28
-
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/Reports/Orders/Hooks.php CHANGED
@@ -4,10 +4,8 @@ namespace WCML\Reports\Orders;
4
 
5
  use WCML\Utilities\Resources;
6
  use WCML\Rest\Functions;
7
- use WPML\FP\Obj;
8
- use WPML\FP\Fns;
9
 
10
- class Hooks implements \IWPML_Action {
11
 
12
  /** @var \wpdb $wpdb */
13
  private $wpdb;
4
 
5
  use WCML\Utilities\Resources;
6
  use WCML\Rest\Functions;
 
 
7
 
8
+ class Hooks implements \IWPML_Backend_Action, \IWPML_REST_Action, \IWPML_DIC_Action {
9
 
10
  /** @var \wpdb $wpdb */
11
  private $wpdb;
classes/Reports/Products/Query.php CHANGED
@@ -15,6 +15,8 @@ class Query implements \IWPML_REST_Action {
15
  if ( Functions::isAnalyticsRestRequest() ) {
16
  add_filter( 'woocommerce_analytics_products_select_query', [ $this, 'joinProductTranslations' ] );
17
  add_filter( 'woocommerce_analytics_products_select_query', [ $this, 'translateProductTitles' ] );
 
 
18
  }
19
  }
20
 
@@ -177,10 +179,12 @@ class Query implements \IWPML_REST_Action {
177
  if ( $product ) {
178
  $row['extended_info']['name'] = $product->get_title();
179
  }
180
- $row['extended_info']['category_ids'] = wpml_collect( $row['extended_info']['category_ids'] )
181
- ->map( function( $id ) {
182
- return apply_filters( 'wpml_object_id', $id, 'product_cat', true );
183
- } )->toArray();
 
 
184
  }
185
  return $row;
186
  } )->toArray();
15
  if ( Functions::isAnalyticsRestRequest() ) {
16
  add_filter( 'woocommerce_analytics_products_select_query', [ $this, 'joinProductTranslations' ] );
17
  add_filter( 'woocommerce_analytics_products_select_query', [ $this, 'translateProductTitles' ] );
18
+ add_filter( 'woocommerce_analytics_variations_select_query', [ $this, 'joinProductTranslations' ] );
19
+ add_filter( 'woocommerce_analytics_variations_select_query', [ $this, 'translateProductTitles' ] );
20
  }
21
  }
22
 
179
  if ( $product ) {
180
  $row['extended_info']['name'] = $product->get_title();
181
  }
182
+ if ( isset( $row['extended_info']['category_ids'] ) ) {
183
+ $row['extended_info']['category_ids'] = wpml_collect( $row['extended_info']['category_ids'] )
184
+ ->map( function( $id ) {
185
+ return apply_filters( 'wpml_object_id', $id, 'product_cat', true );
186
+ } )->toArray();
187
+ }
188
  }
189
  return $row;
190
  } )->toArray();
classes/Rest/Exceptions/InvalidCurrency.php CHANGED
@@ -12,6 +12,7 @@ class InvalidCurrency extends WC_REST_Exception {
12
  public function __construct( $currency_code ) {
13
  parent::__construct(
14
  422,
 
15
  sprintf( __( 'Invalid currency parameter: "%s"', 'woocommerce-multilingual' ),
16
  $currency_code ),
17
  422
12
  public function __construct( $currency_code ) {
13
  parent::__construct(
14
  422,
15
+ /* translators: $s is a currency code */
16
  sprintf( __( 'Invalid currency parameter: "%s"', 'woocommerce-multilingual' ),
17
  $currency_code ),
18
  422
classes/Rest/Exceptions/InvalidLanguage.php CHANGED
@@ -12,6 +12,7 @@ class InvalidLanguage extends WC_REST_Exception {
12
  public function __construct( $language_code ) {
13
  parent::__construct(
14
  422,
 
15
  sprintf( __( 'Invalid language parameter: "%s"', 'woocommerce-multilingual' ),
16
  $language_code ),
17
  422
12
  public function __construct( $language_code ) {
13
  parent::__construct(
14
  422,
15
+ /* translators: $s is a language code */
16
  sprintf( __( 'Invalid language parameter: "%s"', 'woocommerce-multilingual' ),
17
  $language_code ),
18
  422
classes/Rest/Exceptions/InvalidProduct.php CHANGED
@@ -12,6 +12,7 @@ class InvalidProduct extends WC_REST_Exception {
12
  public function __construct( $product_id ) {
13
  parent::__construct(
14
  422,
 
15
  sprintf( __( 'Product not found: %d', 'woocommerce-multilingual' ),
16
  $product_id ),
17
  422
12
  public function __construct( $product_id ) {
13
  parent::__construct(
14
  422,
15
+ /* translators: $s is a product ID */
16
  sprintf( __( 'Product not found: %d', 'woocommerce-multilingual' ),
17
  $product_id ),
18
  422
classes/Rest/Exceptions/InvalidTerm.php CHANGED
@@ -12,6 +12,7 @@ class InvalidTerm extends WC_REST_Exception {
12
  public function __construct( $term_id ) {
13
  parent::__construct(
14
  422,
 
15
  sprintf( __( 'Term not found: %d', 'woocommerce-multilingual' ),
16
  $term_id ),
17
  422
12
  public function __construct( $term_id ) {
13
  parent::__construct(
14
  422,
15
+ /* translators: $s is a term ID */
16
  sprintf( __( 'Term not found: %d', 'woocommerce-multilingual' ),
17
  $term_id ),
18
  422
classes/Rest/Functions.php CHANGED
@@ -71,11 +71,4 @@ class Functions {
71
  return ( false !== stripos( $_SERVER['REQUEST_URI'], $rest_prefix . $endpoint ) );
72
  }
73
 
74
- /**
75
- * Use url without the language parameter. Needed for the signature match.
76
- */
77
- public static function removeWpmlGlobalUrlFilters() {
78
- global $wpml_url_filters;
79
- remove_filter( 'home_url', [ $wpml_url_filters, 'home_url_filter' ], - 10 );
80
- }
81
  }
71
  return ( false !== stripos( $_SERVER['REQUEST_URI'], $rest_prefix . $endpoint ) );
72
  }
73
 
 
 
 
 
 
 
 
74
  }
classes/Rest/Generic.php CHANGED
@@ -2,6 +2,8 @@
2
 
3
  namespace WCML\Rest;
4
 
 
 
5
  class Generic {
6
 
7
  /**
@@ -19,7 +21,7 @@ class Generic {
19
  }
20
 
21
  /**
22
- * @param WP_Query $wp_query
23
  */
24
  public static function autoAdjustIncludedIds( \WP_Query $wp_query ) {
25
  $lang = $wp_query->get( 'lang' );
@@ -33,4 +35,22 @@ class Generic {
33
  }
34
  }
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
2
 
3
  namespace WCML\Rest;
4
 
5
+ use WPML\FP\Fns;
6
+
7
  class Generic {
8
 
9
  /**
21
  }
22
 
23
  /**
24
+ * @param \WP_Query $wp_query
25
  */
26
  public static function autoAdjustIncludedIds( \WP_Query $wp_query ) {
27
  $lang = $wp_query->get( 'lang' );
35
  }
36
  }
37
 
38
+ /**
39
+ * We need an unfiltered 'home_url' so that the REST signature matches.
40
+ *
41
+ * Note that WPML already does this, but fails to recognize a REST
42
+ * request when we get a 'relative' home_url.
43
+ */
44
+ public static function removeHomeUrlFilterOnRestAuthentication() {
45
+ $returnTrue = Fns::always( true );
46
+
47
+ add_filter( 'determine_current_user', Fns::tap( function() use ( $returnTrue ) {
48
+ add_filter( 'wpml_skip_convert_url_string', $returnTrue );
49
+ } ), 10 );
50
+
51
+ add_filter( 'determine_current_user', Fns::tap( function() use ( $returnTrue ) {
52
+ remove_filter( 'wpml_skip_convert_url_string', $returnTrue );
53
+ } ), 20 );
54
+ }
55
+
56
  }
classes/Rest/ProductSaveActions.php CHANGED
@@ -22,7 +22,7 @@ class ProductSaveActions extends \WPML_Post_Translation {
22
  public function __construct(
23
  array $settings,
24
  \wpdb $wpdb,
25
- \SitePress $sitepress,
26
  \WCML_Synchronize_Product_Data $productDataSync
27
  ) {
28
  parent::__construct( $settings, $wpdb );
22
  public function __construct(
23
  array $settings,
24
  \wpdb $wpdb,
25
+ \WPML\Core\ISitePress $sitepress,
26
  \WCML_Synchronize_Product_Data $productDataSync
27
  ) {
28
  parent::__construct( $settings, $wpdb );
classes/Rest/Wrapper/ProductTerms.php CHANGED
@@ -18,7 +18,7 @@ class ProductTerms extends Handler {
18
  private $wcmlTerms;
19
 
20
  public function __construct(
21
- \SitePress $sitepress,
22
  \WPML_Term_Translation $wpmlTermTranslations,
23
  \WCML_Terms $wcmlTerms
24
  ) {
18
  private $wcmlTerms;
19
 
20
  public function __construct(
21
+ \WPML\Core\ISitePress $sitepress,
22
  \WPML_Term_Translation $wpmlTermTranslations,
23
  \WCML_Terms $wcmlTerms
24
  ) {
classes/Rest/Wrapper/Products/Products.php CHANGED
@@ -22,7 +22,7 @@ class Products extends Handler {
22
  private $productSaveActions;
23
 
24
  public function __construct(
25
- \Sitepress $sitepress,
26
  \WPML_Post_Translation $wpmlPostTranslations,
27
  \WPML_Query_Filter $wpmlQueryFilter,
28
  ProductSaveActions $productSaveActions
22
  private $productSaveActions;
23
 
24
  public function __construct(
25
+ \WPML\Core\ISitePress $sitepress,
26
  \WPML_Post_Translation $wpmlPostTranslations,
27
  \WPML_Query_Filter $wpmlQueryFilter,
28
  ProductSaveActions $productSaveActions
classes/Rest/Wrapper/Reports/ProductsCount.php CHANGED
@@ -14,7 +14,7 @@ class ProductsCount extends Handler {
14
  private $wpdb;
15
 
16
  public function __construct(
17
- \SitePress $sitepress,
18
  \wpdb $wpdb
19
  ) {
20
  $this->sitepress = $sitepress;
14
  private $wpdb;
15
 
16
  public function __construct(
17
+ \WPML\Core\ISitePress $sitepress,
18
  \wpdb $wpdb
19
  ) {
20
  $this->sitepress = $sitepress;
classes/Rest/Wrapper/Reports/TopSeller.php CHANGED
@@ -12,7 +12,7 @@ class TopSeller extends Handler {
12
  private $sitepress;
13
 
14
  public function __construct(
15
- \SitePress $sitepress
16
  ) {
17
  $this->sitepress = $sitepress;
18
  }
12
  private $sitepress;
13
 
14
  public function __construct(
15
+ \WPML\Core\ISitePress $sitepress
16
  ) {
17
  $this->sitepress = $sitepress;
18
  }
classes/Reviews/Translations/Factory.php CHANGED
@@ -4,7 +4,7 @@ namespace WCML\Reviews\Translations;
4
 
5
  use function WPML\Container\make;
6
 
7
- class Factory implements \IWPML_Deferred_Action_Loader, \IWPML_Frontend_Action_Loader {
8
 
9
 
10
  public function create() {
4
 
5
  use function WPML\Container\make;
6
 
7
+ class Factory implements \IWPML_Deferred_Action_Loader, \IWPML_Frontend_Action_Loader, \IWPML_AJAX_Action_Loader {
8
 
9
 
10
  public function create() {
classes/RewriteRules/Hooks.php CHANGED
@@ -7,7 +7,7 @@ class Hooks implements \IWPML_Backend_Action, \IWPML_Frontend_Action, \IWPML_DIC
7
  /** @var \SitePress $sitepress */
8
  private $sitepress;
9
 
10
- public function __construct( \SitePress $sitepress ) {
11
  $this->sitepress = $sitepress;
12
  }
13
 
7
  /** @var \SitePress $sitepress */
8
  private $sitepress;
9
 
10
+ public function __construct( \WPML\Core\ISitePress $sitepress ) {
11
  $this->sitepress = $sitepress;
12
  }
13
 
classes/StandAlone/ActionFilterLoader.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone;
4
+
5
+ use WPML_Action_Filter_Loader;
6
+
7
+ use function WCML\functions\isStandAlone;
8
+
9
+ class ActionFilterLoader {
10
+
11
+ /**
12
+ * @var WPML_Action_Filter_Loader
13
+ */
14
+ private $loader;
15
+
16
+ public function __construct( WPML_Action_Filter_Loader $loader = null ) {
17
+ $this->loader = null === $loader ? new WPML_Action_Filter_Loader() : $loader;
18
+ }
19
+
20
+ /**
21
+ * Load action filter limiting the loaders processed depending on whether WPML is installed
22
+ *
23
+ * @param string[] $loaders Action loaders.
24
+ */
25
+ public function load( $loaders ) {
26
+ $this->loader->load( $this->mayBeFilterLoaders( $loaders ) );
27
+ }
28
+
29
+ /**
30
+ * Only pass through IStandAloneAction loaders if WPML is not available.
31
+ *
32
+ * @param string[] $loaders Action loaders.
33
+ * @return string[] $loaders.
34
+ */
35
+ private function mayBeFilterLoaders( $loaders ) {
36
+ if ( isStandAlone() ) {
37
+ $filtered_loaders = [];
38
+ foreach ( $loaders as $loader ) {
39
+ if ( is_subclass_of( $loader, IStandAloneAction::class ) ) {
40
+ $filtered_loaders[] = $loader;
41
+ }
42
+ }
43
+ return $filtered_loaders;
44
+ }
45
+ return $loaders;
46
+ }
47
+ }
classes/StandAlone/Container/Config.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone\Container;
4
+
5
+ class Config {
6
+
7
+ /**
8
+ * @return array
9
+ */
10
+ public static function getSharedInstances() {
11
+ global $wpdb;
12
+
13
+ return [
14
+ $wpdb
15
+ ];
16
+ }
17
+
18
+ /**
19
+ * @return array
20
+ */
21
+ public static function getAliases() {
22
+ global $wpdb;
23
+
24
+ $aliases = [];
25
+
26
+ $wpdb_class = get_class( $wpdb );
27
+
28
+ if ( 'wpdb' !== $wpdb_class ) {
29
+ $aliases['wpdb'] = $wpdb_class;
30
+ }
31
+
32
+ return $aliases;
33
+ }
34
+
35
+ /**
36
+ * @return array
37
+ */
38
+ public static function getSharedClasses() {
39
+ return [
40
+ \WPML\Core\ISitePress::class,
41
+ \WPML_Notices::class,
42
+ ];
43
+ }
44
+
45
+ /**
46
+ * @return array
47
+ */
48
+ public static function getDelegated() {
49
+ return [
50
+ \WPML_Notices::class => 'wcml_wpml_get_admin_notices',
51
+ ];
52
+ }
53
+ }
classes/StandAlone/DependencyAssets.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone;
4
+
5
+ use WCML\Utilities\AdminPages;
6
+
7
+ class DependencyAssets {
8
+
9
+ /** @var string $dependencyBaseUrl */
10
+ private $dependencyBaseUrl;
11
+
12
+ /**
13
+ * @param string $dependencyBaseUrl
14
+ */
15
+ public function __construct( $dependencyBaseUrl ) {
16
+ $this->dependencyBaseUrl = $dependencyBaseUrl;
17
+ }
18
+
19
+ public function add_hooks() {
20
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
21
+ }
22
+
23
+ public function enqueue() {
24
+ wp_register_script( 'wpml-scripts', $this->dependencyBaseUrl . '/res/js/scripts.js', [], WCML_VERSION );
25
+ wp_register_style( 'wpml-styles', $this->dependencyBaseUrl . '/res/css/styles.css', [], WCML_VERSION );
26
+ wp_register_style( 'otgs-dialogs', $this->dependencyBaseUrl . '/res/css/otgs-dialogs.css', [ 'wp-jquery-ui-dialog' ], WCML_VERSION );
27
+ wp_register_style( 'wpml-dialog', $this->dependencyBaseUrl . '/res/css/dialog.css', [ 'otgs-dialogs' ], WCML_VERSION );
28
+ wp_register_style( 'otgs-ico', $this->dependencyBaseUrl . '/res/css/otgs-ico.css', [], WCML_VERSION );
29
+
30
+ if ( AdminPages::isMultiCurrency() || AdminPages::isTab( 'multilingual' ) ) {
31
+ wp_enqueue_script( 'wpml-scripts' );
32
+
33
+ wp_enqueue_style( 'wpml-styles' );
34
+ wp_enqueue_style( 'wpml-dialog' );
35
+
36
+ wp_enqueue_style( \OTGS_Assets_Handles::SWITCHER );
37
+ wp_enqueue_script( \OTGS_Assets_Handles::SWITCHER );
38
+ wp_enqueue_style( \OTGS_Assets_Handles::POPOVER_TOOLTIP );
39
+ wp_enqueue_script( \OTGS_Assets_Handles::POPOVER_TOOLTIP );
40
+
41
+ wp_enqueue_style( \OTGS_ASSETS_ICONS_STYLES );
42
+ wp_enqueue_style( 'otgs-ico' );
43
+ }
44
+ }
45
+ }
classes/StandAlone/IStandAloneAction.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone;
4
+
5
+ interface IStandAloneAction {}
classes/StandAlone/NullSitePress.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone;
4
+
5
+ use WPML\Core\ISitePress;
6
+ use WPML_WP_API;
7
+
8
+ class NullSitePress implements ISitePress {
9
+
10
+ /** @var WPML_WP_API */
11
+ private $wp_api;
12
+
13
+ /**
14
+ * @param bool $refresh
15
+ * @param bool $major_first
16
+ * @param string $order_by
17
+ * @return array
18
+ */
19
+ public function get_active_languages( $refresh = false, $major_first = false, $order_by = 'english_name' ) {
20
+ $code = $this->get_current_language();
21
+ return [
22
+ $code => [
23
+ 'id' => 1,
24
+ 'code' => $code,
25
+ 'major' => 1,
26
+ 'active' => 1,
27
+ 'default_locale' => get_locale(),
28
+ 'encode_url' => 0,
29
+ 'tag' => $code,
30
+ 'english_name' => $code,
31
+ 'native_name' => $code,
32
+ 'display_name' => $code,
33
+ ],
34
+ ];
35
+ }
36
+
37
+ /** @return bool|mixed|null|string */
38
+ public function get_admin_language() {
39
+ return $this->get_current_language();
40
+ }
41
+
42
+ /** @return string */
43
+ public function get_current_language() {
44
+ return preg_replace( '/_.+/', '', get_locale() );
45
+ }
46
+
47
+ /** @return string|false */
48
+ public function get_default_language() {
49
+ return $this->get_current_language();
50
+ }
51
+
52
+ /**
53
+ * @param int $trid
54
+ * @param string|null $el_type Use comment, post, page, {custom post time name}, nav_menu, nav_menu_item, category, post_tag, etc. (prefixed with 'post_', 'tax_', or nothing for 'comment').
55
+ * @param bool|null $skip_empty
56
+ * @param bool|null $all_statuses
57
+ * @param bool|null $skip_cache
58
+ * @param bool|null $skip_recursions
59
+ * @param bool|null $skipPrivilegeChecking
60
+ *
61
+ * @return array<string,\stdClass>
62
+ */
63
+ public function get_element_translations(
64
+ $trid,
65
+ $el_type = 'post_post',
66
+ $skip_empty = false,
67
+ $all_statuses = false,
68
+ $skip_cache = false,
69
+ $skip_recursions = false,
70
+ $skipPrivilegeChecking = false
71
+ ) {
72
+ return [];
73
+ }
74
+
75
+ /**
76
+ * @param string $code
77
+ * @return string
78
+ */
79
+ public function get_flag_url( $code ) {
80
+ return '';
81
+ }
82
+
83
+ /**
84
+ * Find language of document based on given permalink
85
+ *
86
+ * @param string $url Local url in permalink form.
87
+ * @return string language code
88
+ */
89
+ public function get_language_from_url( $url ) {
90
+ return $this->get_current_language();
91
+ }
92
+
93
+ /**
94
+ * Filter to add language field to WordPress search form
95
+ *
96
+ * @param string $form HTML code of search for before filtering.
97
+ *
98
+ * @return string HTML code of search form
99
+ */
100
+ public function get_search_form_filter( $form ) {
101
+ return $form;
102
+ }
103
+
104
+ /**
105
+ * @param string $key
106
+ * @param mixed|bool $default
107
+ * @return bool|mixed
108
+ * @since 3.1
109
+ */
110
+ public function get_setting( $key, $default = false ) {
111
+ return $default;
112
+ }
113
+
114
+ /** @return array */
115
+ public function get_settings() {
116
+ return [];
117
+ }
118
+
119
+ /** @return \WPML_WP_API */
120
+ public function get_wp_api() {
121
+ $this->wp_api = $this->wp_api ? $this->wp_api : new WPML_WP_API();
122
+ return $this->wp_api;
123
+ }
124
+
125
+ /**
126
+ * @param string|bool|null $lang
127
+ * @return bool
128
+ */
129
+ public function is_rtl( $lang = false ) {
130
+ return is_rtl();
131
+ }
132
+
133
+ /**
134
+ * @param int $element_id Use term_taxonomy_id for taxonomies, post_id for posts.
135
+ * @param string $element_type Use comment, post, page, {custom post time name}, nav_menu, nav_menu_item, category,
136
+ * post_tag, etc. (prefixed with 'post_', 'tax_', or nothing for 'comment').
137
+ *
138
+ * @return null|string
139
+ */
140
+ public function get_language_for_element( $element_id, $element_type ) {
141
+ return $this->get_current_language();
142
+ }
143
+ }
classes/StandAlone/UI/AdminMenu.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\StandAlone\UI;
4
+
5
+ use WCML\Utilities\AdminPages;
6
+ use WCML_Admin_Menus;
7
+ use WCML_Multi_Currency_UI;
8
+ use WPML\FP\Str;
9
+
10
+ class AdminMenu extends \WCML_Menu_Wrap_Base {
11
+
12
+ /** @var \SitePress|\WCML\StandAlone\NullSitePress */
13
+ private $sitepress;
14
+
15
+ /**
16
+ * WCML_Menus_Wrap constructor.
17
+ *
18
+ * @param \SitePress|\WCML\StandAlone\NullSitePress $sitepress
19
+ * @param \woocommerce_wpml $woocommerce_wpml
20
+ */
21
+ public function __construct( \WPML\Core\ISitePress $sitepress, $woocommerce_wpml ) {
22
+ parent::__construct( $woocommerce_wpml );
23
+
24
+ $this->sitepress = $sitepress;
25
+ }
26
+
27
+ /**
28
+ * @return array
29
+ */
30
+ protected function get_child_model() {
31
+ $current_tab = AdminPages::getTabToDisplay();
32
+
33
+ $model = [
34
+ 'strings' => [
35
+ 'title' => WCML_Admin_Menus::getWcmlLabel(),
36
+ ],
37
+ 'is_standalone' => true,
38
+ 'menu' => [
39
+ 'multilingual' => [
40
+ 'title' => __( 'Multilingual', 'woocommerce-multilingual' ),
41
+ 'active' => 'multilingual' === $current_tab ? 'nav-tab-active' : '',
42
+ 'url' => admin_url( 'admin.php?page=wpml-wcml&tab=multilingual' ),
43
+ ],
44
+ 'multi_currency' => [
45
+ 'name' => __( 'Multicurrency', 'woocommerce-multilingual' ),
46
+ 'active' => 'multi-currency' === $current_tab ? 'nav-tab-active' : '',
47
+ 'url' => admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' ),
48
+ ],
49
+ ],
50
+ 'content' => $this->get_current_menu_content( $current_tab ),
51
+ ];
52
+
53
+ return $model;
54
+ }
55
+
56
+ protected function get_current_menu_content( $current_tab ) {
57
+ $content = '';
58
+ switch ( $current_tab ) {
59
+ case 'multilingual':
60
+ $inP = Str::wrap( '<p>', '</p>' );
61
+ $inWrapper = Str::wrap( '<div class="wcml-banner">', '</div>' );
62
+
63
+ $wrapLink = function( $text, $url, $isExternal = true ) {
64
+ $attrs = $isExternal ? ' target="_blank" class="wpml-external-link" ' : '';
65
+ return sprintf( $text, '<a href="' . $url . '"' . $attrs . '">', '</a>' );
66
+ };
67
+
68
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
69
+ $content .= $inP( $wrapLink( esc_html__( 'To run your store in multiple languages, you need to use the %1$sWPML plugin%2$s.', 'woocommerce-multilingual' ), \WCML_Tracking_Link::getWpmlHome( true ) ) );
70
+
71
+ $content .= $inP(
72
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
73
+ $wrapLink( esc_html__( 'If you have it already, install and activate it. Otherwise, %1$sbuy WPML%2$s.', 'woocommerce-multilingual' ), \WCML_Tracking_Link::getWpmlPurchase( true ) )
74
+ . ' ' . esc_html__( 'You will need either the Multilingual CMS or Multilingual Agency package to use WPML with WooCommerce.', 'woocommerce-multilingual' )
75
+ );
76
+
77
+ $content .= $inP(
78
+ $wrapLink(
79
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
80
+ esc_html__( 'You can still use the %1$smulticurrency features%2$s without buying anything.', 'woocommerce-multilingual' ),
81
+ admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' ),
82
+ false
83
+ )
84
+ );
85
+
86
+ $content = $inWrapper( $content );
87
+ break;
88
+
89
+ case 'multi-currency':
90
+ default:
91
+ if ( current_user_can( 'wpml_operate_woocommerce_multilingual' ) ) {
92
+ $wcml_mc_ui = new WCML_Multi_Currency_UI( $this->woocommerce_wpml, $this->sitepress );
93
+ $content = $wcml_mc_ui->get_view();
94
+ }
95
+
96
+ break;
97
+ }
98
+
99
+ return $content;
100
+
101
+ }
102
+
103
+ }
classes/Utilities/AdminPages.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Utilities;
4
+
5
+ use WCML_Admin_Menus;
6
+ use WCML_Capabilities;
7
+ use WPML\FP\Lst;
8
+ use WPML\FP\Obj;
9
+ use WPML\FP\Relation;
10
+ use function sanitize_key;
11
+ use function WCML\functions\isStandAlone;
12
+
13
+ class AdminPages {
14
+
15
+ const TAB_MULTICURRENCY = 'multi-currency';
16
+ const TAB_PRODUCTS = 'products';
17
+
18
+ /**
19
+ * @return string
20
+ */
21
+ public static function getDefaultTab() {
22
+ return isStandAlone() ? self::TAB_MULTICURRENCY : self::TAB_PRODUCTS;
23
+ }
24
+
25
+ /**
26
+ * @param null|string $fallback
27
+ *
28
+ * @return string|null
29
+ */
30
+ public static function getCurrentTab( $fallback = null ) {
31
+ return sanitize_key( Obj::prop( 'tab', $_GET ) ) ?: $fallback;
32
+ }
33
+
34
+ /**
35
+ * @return string
36
+ */
37
+ public static function getTabToDisplay() {
38
+ return WCML_Capabilities::canAccessAllWcmlTabs()
39
+ ? self::getCurrentTab( self::getDefaultTab() )
40
+ : self::getDefaultTab();
41
+ }
42
+
43
+ /**
44
+ * @param string|array $tabs A single tab (string) or one of multiple tabs (array).
45
+ *
46
+ * @return bool
47
+ */
48
+ public static function isTab( $tabs ) {
49
+ return Lst::includes( self::getCurrentTab(), (array) $tabs );
50
+ }
51
+
52
+ /**
53
+ * @param string $page
54
+ *
55
+ * @return bool
56
+ */
57
+ public static function isPage( $page ) {
58
+ return Relation::propEq( 'page', $page, $_GET );
59
+ }
60
+
61
+ /**
62
+ * @return bool
63
+ */
64
+ public static function isWcmlSettings() {
65
+ return self::isPage( WCML_Admin_Menus::SLUG );
66
+ }
67
+
68
+ /**
69
+ * @return bool
70
+ */
71
+ public static function isMultiCurrency() {
72
+ $tabs = [ self::TAB_MULTICURRENCY ];
73
+
74
+ if ( isStandAlone() ) {
75
+ $tabs[] = null; // Also the default tab in Standalone mode.
76
+ }
77
+
78
+ return self::isWcmlSettings() && self::isTab( $tabs );
79
+ }
80
+
81
+ /**
82
+ * @return bool
83
+ */
84
+ public static function isTranslationQueue() {
85
+ return ! isStandAlone() && self::isTmPage( '/menu/translations-queue.php' );
86
+ }
87
+
88
+ /**
89
+ * @return bool
90
+ */
91
+ public static function isTranslationsDashboard() {
92
+ return ! isStandAlone() && self::isTmPage( '/menu/main.php' );
93
+ }
94
+
95
+ /**
96
+ * @param string $path Path after the TM folder (e.g. '/menu/main.php')
97
+ *
98
+ * @return bool
99
+ */
100
+ private static function isTmPage( $path ) {
101
+ return defined( 'WPML_TM_FOLDER' ) && self::isPage( WPML_TM_FOLDER . $path );
102
+ }
103
+ }
classes/Utilities/DB.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Utilities;
4
+
5
+ use wpdb;
6
+
7
+ class DB {
8
+
9
+ /**
10
+ * Changes array of items into string of items, separated by comma and sql-escaped
11
+ *
12
+ * @see https://coderwall.com/p/zepnaw
13
+ * @see wpml_prepare_in
14
+ *
15
+ * @global wpdb $wpdb
16
+ *
17
+ * @param mixed|array $items item(s) to be joined into string
18
+ * @param string $format %s or %d
19
+ *
20
+ * @return string Items separated by comma and sql-escaped
21
+ */
22
+ public static function prepareIn( $items, $format = '%s') {
23
+ /** @var wpdb $wpdb */
24
+ global $wpdb;
25
+
26
+ $items = (array) $items;
27
+ $how_many = count( $items );
28
+ if ( $how_many > 0 ) {
29
+ $placeholders = array_fill( 0, $how_many, $format );
30
+ $prepared_format = implode( ',', $placeholders );
31
+ $prepared_in = $wpdb->prepare( $prepared_format, $items );
32
+ } else {
33
+ $prepared_in = '';
34
+ }
35
+
36
+ return $prepared_in;
37
+ }
38
+ }
classes/Utilities/WcAdminPages.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Utilities;
4
+
5
+ use WPML\FP\Lst;
6
+ use WPML\FP\Obj;
7
+
8
+ class WcAdminPages {
9
+
10
+ const SECTION_BACS = 'bacs';
11
+
12
+ /**
13
+ * @param string|array $sections A single section (string) or one of multiple sections (array).
14
+ *
15
+ * @return bool
16
+ */
17
+ public static function isSection( $sections ) {
18
+ return Lst::includes( Obj::prop( 'section', $_GET ), (array) $sections );
19
+ }
20
+
21
+ /**
22
+ * @return bool
23
+ */
24
+ private static function isSettingsPage() {
25
+ return self::isAdminPhpPage( 'wc-settings' );
26
+ }
27
+
28
+ /**
29
+ * @return bool
30
+ */
31
+ public static function isHomeScreen() {
32
+ return self::isAdminPhpPage( 'wc-admin' );
33
+ }
34
+
35
+ /**
36
+ * @return bool
37
+ */
38
+ public static function isPaymentSettings() {
39
+ return self::isSettingsPage() && AdminPages::isTab( 'checkout' );
40
+ }
41
+
42
+ /**
43
+ * @param string $page
44
+ *
45
+ * @return bool
46
+ */
47
+ private static function isAdminPhpPage( $page ) {
48
+ global $pagenow;
49
+
50
+ return is_admin() && 'admin.php' === $pagenow && AdminPages::isPage( $page );
51
+ }
52
+
53
+ }
classes/Utilities/WpAdminPages.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Utilities;
4
+
5
+ class WpAdminPages {
6
+
7
+ /**
8
+ * @return bool
9
+ */
10
+ public static function isDashboard() {
11
+ global $pagenow;
12
+
13
+ return is_admin() && 'index.php' === $pagenow;
14
+ }
15
+ }
classes/class-wcml-tracking-link.php CHANGED
@@ -4,6 +4,7 @@ class WCML_Tracking_Link {
4
 
5
  // WPML general links
6
  const WPML_HOME = 'https://wpml.org/';
 
7
  const WPML_SUPPORT = 'https://wpml.org/forums/forum/english-support/';
8
  const WPML_ACCOUNT = 'https://wpml.org/shop/account/';
9
  const WPML_AUTO_TRANSLATION_DOC = 'https://wpml.org/documentation/automatic-translation/';
@@ -28,12 +29,12 @@ class WCML_Tracking_Link {
28
  *
29
  * @return string
30
  */
31
- public static function generate( $link, $id = false ) {
32
- $params = [
33
  'utm_source' => 'plugin',
34
  'utm_medium' => 'gui',
35
  'utm_campaign' => 'wcml',
36
- ];
37
 
38
  $link = add_query_arg( $params, $link );
39
 
@@ -45,10 +46,30 @@ class WCML_Tracking_Link {
45
  }
46
 
47
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  * @return string
49
  */
50
- public static function getWpmlHome() {
51
- return self::generate( self::WPML_HOME );
52
  }
53
 
54
  /**
4
 
5
  // WPML general links
6
  const WPML_HOME = 'https://wpml.org/';
7
+ const WPML_PURCHASE = 'https://wpml.org/purchase/';
8
  const WPML_SUPPORT = 'https://wpml.org/forums/forum/english-support/';
9
  const WPML_ACCOUNT = 'https://wpml.org/shop/account/';
10
  const WPML_AUTO_TRANSLATION_DOC = 'https://wpml.org/documentation/automatic-translation/';
29
  *
30
  * @return string
31
  */
32
+ public static function generate( $link, $id = false, $params = [] ) {
33
+ $params = array_merge( [
34
  'utm_source' => 'plugin',
35
  'utm_medium' => 'gui',
36
  'utm_campaign' => 'wcml',
37
+ ], $params );
38
 
39
  $link = add_query_arg( $params, $link );
40
 
46
  }
47
 
48
  /**
49
+ * @param bool $isStandalone
50
+ *
51
+ * @return array
52
+ */
53
+ private static function getStandaloneParams( $isStandalone ) {
54
+ return $isStandalone ? [ 'utm_campaign' => 'wcml-standalone' ] : [];
55
+ }
56
+
57
+ /**
58
+ * @param bool $isStandalone
59
+ *
60
+ * @return string
61
+ */
62
+ public static function getWpmlHome( $isStandalone = false ) {
63
+ return self::generate( self::WPML_HOME, false, self::getStandaloneParams( $isStandalone ) );
64
+ }
65
+
66
+ /**
67
+ * @param bool $isStandalone
68
+ *
69
  * @return string
70
  */
71
+ public static function getWpmlPurchase( $isStandalone = false ) {
72
+ return self::generate( self::WPML_PURCHASE, false, self::getStandaloneParams( $isStandalone ) );
73
  }
74
 
75
  /**
classes/class-woocommerce-wpml.php CHANGED
@@ -1,5 +1,8 @@
1
  <?php
2
 
 
 
 
3
  use function WPML\Container\make;
4
 
5
  /**
@@ -57,10 +60,21 @@ class woocommerce_wpml {
57
  public $comments;
58
  /** @var WCML_Translation_Editor */
59
  public $translation_editor;
60
- /** @var WCML_Dependencies */
 
 
 
 
 
61
  public $dependencies;
62
- /** @var bool|int */
 
 
 
 
 
63
  public $dependencies_are_ok;
 
64
  /** @var WCML_Cart */
65
  public $cart;
66
  /** @var WCML_Cart_Sync_Warnings */
@@ -86,7 +100,7 @@ class woocommerce_wpml {
86
  private $wcml_products_screen;
87
 
88
  public function __construct() {
89
- global $sitepress;
90
 
91
  $this->settings = $this->get_settings();
92
  $this->currencies = new WCML_Currencies( $this );
@@ -95,20 +109,20 @@ class woocommerce_wpml {
95
 
96
  add_action( 'init', [ $this, 'init' ], 2 );
97
 
98
- if ( defined( 'ICL_SITEPRESS_VERSION' ) && ! ICL_PLUGIN_INACTIVE && class_exists( 'SitePress' ) ) {
99
- $this->cs_properties = new WCML_Currency_Switcher_Properties();
100
- $wpml_wp_api = $sitepress->get_wp_api();
101
- $this->cs_templates = new WCML_Currency_Switcher_Templates( $this, $wpml_wp_api, new WPML_File( $wpml_wp_api ) );
102
- $this->cs_templates->init_hooks();
103
 
104
- $wc_shortccode_product_category = new WCML_WC_Shortcode_Product_Category( $sitepress );
105
- $wc_shortccode_product_category->add_hooks();
106
- }
 
 
107
 
108
  }
109
 
110
  private function load_rest_api() {
111
- global $sitepress;
112
 
113
  if ( class_exists( 'WooCommerce' ) && defined( 'WC_VERSION' ) && ! is_null( $sitepress ) && WCML\Rest\Functions::isRestApiRequest() ) {
114
  WCML\Rest\Hooks::addHooks();
@@ -130,16 +144,17 @@ class woocommerce_wpml {
130
  * @return bool
131
  */
132
  public function init() {
133
- global $sitepress, $wpdb, $woocommerce, $wpml_url_converter, $wpml_post_translations, $wpml_term_translations;
134
 
135
- $this->dependencies = new WCML_Dependencies();
 
 
136
  $this->dependencies_are_ok = $this->dependencies->check();
137
 
138
  WCML_Admin_Menus::set_up_menus( $this, $sitepress, $wpdb );
139
 
140
  if ( ! $this->dependencies_are_ok ) {
141
- $is_dashboard_page = isset( $_GET['page'] ) && 'wpml-wcml' === $_GET['page'];
142
- if ( is_admin() && $is_dashboard_page ) {
143
  WCML_Capabilities::set_up_capabilities();
144
 
145
  wp_register_style( 'otgs-ico', WCML_PLUGIN_URL . '/res/css/otgs-ico.css', null, WCML_VERSION );
@@ -148,13 +163,12 @@ class woocommerce_wpml {
148
  WCML_Resources::load_management_css();
149
  WCML_Resources::load_tooltip_resources();
150
  }
 
151
  return false;
152
  }
153
 
154
  new WCML_Upgrade();
155
 
156
- $this->compatibility = new WCML_Compatibility( $sitepress, $this, $wpdb, new WPML_Element_Translation_Package(), $wpml_post_translations );
157
-
158
  $actions_that_need_mc = [
159
  'save-mc-options',
160
  'wcml_save_currency',
@@ -172,17 +186,31 @@ class woocommerce_wpml {
172
 
173
  $this->cart = new WCML_Cart( $this, $sitepress, $woocommerce );
174
 
 
175
  if ( WCML_MULTI_CURRENCIES_INDEPENDENT === (int) $this->settings['enable_multi_currency']
176
- || ( isset( $_GET['page'] ) && 'wpml-wcml' === $_GET['page'] && isset( $_GET['tab'] ) && 'multi-currency' === $_GET['tab'] )
177
- || ( isset( $_POST['action'] ) && in_array( $_POST['action'], $actions_that_need_mc, true ) )
178
  ) {
179
  $this->get_multi_currency();
180
- $wcml_price_filters = new WCML_Price_Filter( $this );
181
  $wcml_price_filters->add_hooks();
182
  } else {
183
  add_shortcode( 'currency_switcher', '__return_empty_string' );
184
  }
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  $this->currencies = new WCML_Currencies( $this );
187
  $this->currencies->add_hooks();
188
 
@@ -214,7 +242,7 @@ class woocommerce_wpml {
214
  $this->store->add_hooks();
215
  $this->strings = new WCML_WC_Strings( $this, $sitepress, $wpdb );
216
  $this->strings->add_hooks();
217
- // do not pass mailer instance instead of $woocommerce
218
  $this->emails = new WCML_Emails( $this->strings, $sitepress, $woocommerce, $wpdb );
219
  $this->emails->add_hooks();
220
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
@@ -273,6 +301,31 @@ class woocommerce_wpml {
273
  return true;
274
  }
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  /**
277
  * Get settings
278
  *
@@ -470,7 +523,7 @@ class woocommerce_wpml {
470
  * @return bool
471
  */
472
  public function is_wpml_prior_4_2() {
473
- global $sitepress;
474
 
475
  return $sitepress->get_wp_api()->version_compare( $this->get_constant( 'ICL_SITEPRESS_VERSION' ), '4.2.0', '<' ) ||
476
  $sitepress->get_wp_api()->version_compare( $this->get_constant( 'WPML_TM_VERSION' ), '2.8.0', '<' );
@@ -482,8 +535,6 @@ class woocommerce_wpml {
482
  * @return int|string
483
  */
484
  private function get_constant( $name ) {
485
- global $sitepress;
486
-
487
- return $sitepress->get_wp_api()->constant( $name );
488
  }
489
  }
1
  <?php
2
 
3
+ use WCML\Utilities\AdminPages;
4
+ use function WCML\functions\getSitePress;
5
+ use function WCML\functions\isStandAlone;
6
  use function WPML\Container\make;
7
 
8
  /**
60
  public $comments;
61
  /** @var WCML_Translation_Editor */
62
  public $translation_editor;
63
+
64
+ /**
65
+ * @depreacted Use `make( WCML_Dependencies::class )` instead.
66
+ *
67
+ * @var WCML_Dependencies
68
+ */
69
  public $dependencies;
70
+
71
+ /**
72
+ * @depreacted Use `make( WCML_Dependencies::class )->check()` instead.
73
+ *
74
+ * @var bool|int
75
+ */
76
  public $dependencies_are_ok;
77
+
78
  /** @var WCML_Cart */
79
  public $cart;
80
  /** @var WCML_Cart_Sync_Warnings */
100
  private $wcml_products_screen;
101
 
102
  public function __construct() {
103
+ $sitepress = getSitePress();
104
 
105
  $this->settings = $this->get_settings();
106
  $this->currencies = new WCML_Currencies( $this );
109
 
110
  add_action( 'init', [ $this, 'init' ], 2 );
111
 
112
+ $this->cs_properties = new WCML_Currency_Switcher_Properties();
113
+ $wpml_wp_api = $sitepress->get_wp_api();
114
+ $wpml_wp_api->get_wp_filesystem_direct();
 
 
115
 
116
+ $this->cs_templates = new WCML_Currency_Switcher_Templates( $this, $wpml_wp_api, make( WPML_File::class ) );
117
+ $this->cs_templates->init_hooks();
118
+
119
+ $wc_shortccode_product_category = new WCML_WC_Shortcode_Product_Category( $sitepress );
120
+ $wc_shortccode_product_category->add_hooks();
121
 
122
  }
123
 
124
  private function load_rest_api() {
125
+ $sitepress = getSitePress();
126
 
127
  if ( class_exists( 'WooCommerce' ) && defined( 'WC_VERSION' ) && ! is_null( $sitepress ) && WCML\Rest\Functions::isRestApiRequest() ) {
128
  WCML\Rest\Hooks::addHooks();
144
  * @return bool
145
  */
146
  public function init() {
147
+ global $wpdb, $woocommerce, $wpml_url_converter, $wpml_post_translations, $wpml_term_translations;
148
 
149
+ $sitepress = getSitePress();
150
+
151
+ $this->dependencies = make( WCML_Dependencies::class );
152
  $this->dependencies_are_ok = $this->dependencies->check();
153
 
154
  WCML_Admin_Menus::set_up_menus( $this, $sitepress, $wpdb );
155
 
156
  if ( ! $this->dependencies_are_ok ) {
157
+ if ( is_admin() && AdminPages::isWcmlSettings() ) {
 
158
  WCML_Capabilities::set_up_capabilities();
159
 
160
  wp_register_style( 'otgs-ico', WCML_PLUGIN_URL . '/res/css/otgs-ico.css', null, WCML_VERSION );
163
  WCML_Resources::load_management_css();
164
  WCML_Resources::load_tooltip_resources();
165
  }
166
+
167
  return false;
168
  }
169
 
170
  new WCML_Upgrade();
171
 
 
 
172
  $actions_that_need_mc = [
173
  'save-mc-options',
174
  'wcml_save_currency',
186
 
187
  $this->cart = new WCML_Cart( $this, $sitepress, $woocommerce );
188
 
189
+ $action = filter_input( INPUT_POST, 'action' );
190
  if ( WCML_MULTI_CURRENCIES_INDEPENDENT === (int) $this->settings['enable_multi_currency']
191
+ || AdminPages::isMultiCurrency()
192
+ || ( in_array( $action, $actions_that_need_mc, true ) )
193
  ) {
194
  $this->get_multi_currency();
195
+ $wcml_price_filters = new WCML_Price_Filter( $this );
196
  $wcml_price_filters->add_hooks();
197
  } else {
198
  add_shortcode( 'currency_switcher', '__return_empty_string' );
199
  }
200
 
201
+ if ( $this->dependencies_are_ok ) {
202
+ $this->compatibility = new WCML_Compatibility();
203
+ $this->compatibility->init();
204
+
205
+ if ( isStandAlone() ) {
206
+ return $this->init_standalone( $sitepress, $wpdb );
207
+ } else {
208
+ return $this->init_full( $sitepress, $wpdb, $woocommerce, $wpml_url_converter, $wpml_post_translations, $wpml_term_translations );
209
+ }
210
+ }
211
+ }
212
+
213
+ private function init_full( $sitepress, $wpdb, $woocommerce, $wpml_url_converter, $wpml_post_translations, $wpml_term_translations ) {
214
  $this->currencies = new WCML_Currencies( $this );
215
  $this->currencies->add_hooks();
216
 
242
  $this->store->add_hooks();
243
  $this->strings = new WCML_WC_Strings( $this, $sitepress, $wpdb );
244
  $this->strings->add_hooks();
245
+ // do not pass mailer instance instead of $woocommerce.
246
  $this->emails = new WCML_Emails( $this->strings, $sitepress, $woocommerce, $wpdb );
247
  $this->emails->add_hooks();
248
  $this->terms = new WCML_Terms( $this, $sitepress, $wpdb );
301
  return true;
302
  }
303
 
304
+ private function init_standalone( $sitepress, $wpdb ) {
305
+ $this->currencies = new WCML_Currencies( $this );
306
+ $this->currencies->add_hooks();
307
+
308
+ if ( is_admin() ) {
309
+ ( new WCML_Pointers() )->add_hooks();
310
+ }
311
+
312
+ $this->products = new WCML_Products( $this, $sitepress, null, $wpdb );
313
+ $this->products->add_hooks();
314
+ $this->gateways = new WCML_WC_Gateways( $this, $sitepress );
315
+ $this->gateways->add_hooks();
316
+ $this->cart->add_hooks(); // object is instantiated before.
317
+
318
+ WCML_Locale::load_locale();
319
+ WCML_Install::initialize( $this, $sitepress );
320
+
321
+ WCML_Resources::set_up_resources( $this, $sitepress );
322
+ WCML_Resources::add_hooks();
323
+
324
+ add_action( 'wp_ajax_wcml_update_setting_ajx', [ $this, 'update_setting_ajx' ] );
325
+
326
+ return true;
327
+ }
328
+
329
  /**
330
  * Get settings
331
  *
523
  * @return bool
524
  */
525
  public function is_wpml_prior_4_2() {
526
+ $sitepress = getSitePress();
527
 
528
  return $sitepress->get_wp_api()->version_compare( $this->get_constant( 'ICL_SITEPRESS_VERSION' ), '4.2.0', '<' ) ||
529
  $sitepress->get_wp_api()->version_compare( $this->get_constant( 'WPML_TM_VERSION' ), '2.8.0', '<' );
535
  * @return int|string
536
  */
537
  private function get_constant( $name ) {
538
+ return getSitePress()->get_wp_api()->constant( $name );
 
 
539
  }
540
  }
classes/multi-currency/class-wcml-exchange-rates.php CHANGED
@@ -1,5 +1,8 @@
1
  <?php
2
 
 
 
 
3
  /**
4
  * Class WCML_Exchange_Rates
5
  */
@@ -11,23 +14,37 @@ class WCML_Exchange_Rates {
11
  private $services = [];
12
  /** @var array */
13
  private $settings;
14
- /** @var WP_Locale */
15
  private $wp_locale;
16
 
17
  const CRONJOB_EVENT = 'wcml_exchange_rates_update';
18
  const DIGITS_AFTER_DECIMAL_POINT = 6;
 
19
 
20
  /**
21
- * WCML_Exchange_Rates constructor.
22
- *
23
- * @param $woocommerce_wpml
24
- * @param WP_Locale
25
  */
26
- public function __construct( $woocommerce_wpml, $wp_locale ) {
27
  $this->woocommerce_wpml = $woocommerce_wpml;
28
  $this->wp_locale = $wp_locale;
29
  }
30
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  public function add_actions() {
32
  if ( is_admin() ) {
33
  add_action( 'wcml_saved_mc_options', [ $this, 'update_exchange_rate_options' ] ); // before init
@@ -49,7 +66,7 @@ class WCML_Exchange_Rates {
49
  if ( ! isset( $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] ) ) {
50
  $this->settings = [
51
  'automatic' => 0,
52
- 'service' => 'fixerio',
53
  'lifting_charge' => 0,
54
  'schedule' => 'manual',
55
  'week_day' => 1,
@@ -70,7 +87,7 @@ class WCML_Exchange_Rates {
70
 
71
  /**
72
  * @param string $service_id
73
- * @param \WCML\MultiCurrency\ExchangeRateServices\Service $service
74
  */
75
  public function add_service( $service_id, $service ) {
76
  $this->services[ $service_id ] = $service;
@@ -131,14 +148,35 @@ class WCML_Exchange_Rates {
131
  * @throws Exception
132
  */
133
  public function update_exchange_rates() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  if ( ! isset( $this->services[ $this->settings['service'] ] ) ) {
135
  throw new Exception( 'The exchange rate service "' . $this->settings['service'] . '" is not defined.' );
136
  }
137
 
138
- /** @var \WCML\MultiCurrency\ExchangeRateServices\Service $service */
139
- $service =& $this->services[ $this->settings['service'] ];
140
 
141
- $currencies = $this->woocommerce_wpml->multi_currency->get_currency_codes();
142
  $default_currency = wcml_get_woocommerce_currency_option();
143
  $secondary_currencies = array_diff( $currencies, [ $default_currency ] );
144
 
@@ -153,15 +191,6 @@ class WCML_Exchange_Rates {
153
 
154
  $this->apply_lifting_charge( $rates );
155
 
156
- foreach ( $rates as $to => $rate ) {
157
- if ( $rate && is_numeric( $rate ) ) {
158
- $this->save_exchage_rate( $to, $rate );
159
- }
160
- }
161
-
162
- $this->settings['last_updated'] = current_time( 'timestamp' );
163
- $this->save_settings();
164
-
165
  return $rates;
166
  }
167
 
@@ -197,6 +226,10 @@ class WCML_Exchange_Rates {
197
  public function update_exchange_rate_options( $post_data ) {
198
 
199
  if ( isset( $post_data['exchange-rates-automatic'] ) && $post_data['exchange-rates-automatic'] ) {
 
 
 
 
200
 
201
  $this->settings['automatic'] = (int) $post_data['exchange-rates-automatic'];
202
 
@@ -208,14 +241,19 @@ class WCML_Exchange_Rates {
208
  }
209
 
210
  $this->settings['service'] = sanitize_text_field( $post_data['exchange-rates-service'] );
211
-
212
  }
213
 
214
  if ( isset( $post_data['services'] ) ) {
 
215
 
216
  foreach ( $post_data['services'] as $service_id => $service_data ) {
217
  if ( isset( $service_data['api-key'] ) ) {
218
  $this->services[ $service_id ]->saveSetting( 'api-key', $service_data['api-key'] );
 
 
 
 
219
  }
220
  }
221
  }
@@ -243,13 +281,33 @@ class WCML_Exchange_Rates {
243
  } else {
244
  $this->enable_update_cronjob();
245
  }
 
 
 
 
 
 
 
 
 
 
246
  } else {
247
  $this->settings['automatic'] = 0;
248
  $this->delete_update_cronjob();
249
  }
250
 
251
  $this->save_settings();
 
252
 
 
 
 
 
 
 
 
 
 
253
  }
254
 
255
  public function enable_update_cronjob() {
@@ -337,6 +395,7 @@ class WCML_Exchange_Rates {
337
 
338
  $schedules[ 'wcml_monthly_on_' . $this->settings['month_day'] ] = [
339
  'interval' => $interval,
 
340
  'display' => sprintf( __( 'Monthly on the %s', 'woocommerce-multilingual' ), $month_day ),
341
  ];
342
 
@@ -345,6 +404,7 @@ class WCML_Exchange_Rates {
345
  $week_day = $this->wp_locale->get_weekday( $this->settings['week_day'] );
346
  $schedules[ 'wcml_weekly_on_' . $this->settings['week_day'] ] = [
347
  'interval' => WEEK_IN_SECONDS,
 
348
  'display' => sprintf( __( 'Weekly on %s', 'woocommerce-multilingual' ), $week_day ),
349
  ];
350
 
@@ -372,4 +432,25 @@ class WCML_Exchange_Rates {
372
  return $month_day;
373
  }
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  }
1
  <?php
2
 
3
+ use WCML\MultiCurrency\ExchangeRateServices\Service;
4
+ use WPML\FP\Obj;
5
+
6
  /**
7
  * Class WCML_Exchange_Rates
8
  */
14
  private $services = [];
15
  /** @var array */
16
  private $settings;
17
+ /** @var WP_Locale|mixed */
18
  private $wp_locale;
19
 
20
  const CRONJOB_EVENT = 'wcml_exchange_rates_update';
21
  const DIGITS_AFTER_DECIMAL_POINT = 6;
22
+ const KEY_RATES_UPDATED_FLAG = 'wcml_exchange_rates_manually_updated';
23
 
24
  /**
25
+ * @param woocommerce_wpml $woocommerce_wpml
26
+ * @param WP_Locale|mixed $wp_locale
 
 
27
  */
28
+ public function __construct( woocommerce_wpml $woocommerce_wpml, $wp_locale ) {
29
  $this->woocommerce_wpml = $woocommerce_wpml;
30
  $this->wp_locale = $wp_locale;
31
  }
32
 
33
+ /**
34
+ * Please use `make( WCML_Exchange_Rates::class )` to get the instance of this class.
35
+ *
36
+ * @return WCML_Exchange_Rates
37
+ */
38
+ public static function create() {
39
+ /**
40
+ * @var woocommerce_wpml $woocommerce_wpml
41
+ * @var WP_Locale|mixed $wp_locale
42
+ */
43
+ global $woocommerce_wpml, $wp_locale;
44
+
45
+ return new self( $woocommerce_wpml, $wp_locale );
46
+ }
47
+
48
  public function add_actions() {
49
  if ( is_admin() ) {
50
  add_action( 'wcml_saved_mc_options', [ $this, 'update_exchange_rate_options' ] ); // before init
66
  if ( ! isset( $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] ) ) {
67
  $this->settings = [
68
  'automatic' => 0,
69
+ 'service' => 'currencylayer',
70
  'lifting_charge' => 0,
71
  'schedule' => 'manual',
72
  'week_day' => 1,
87
 
88
  /**
89
  * @param string $service_id
90
+ * @param Service $service
91
  */
92
  public function add_service( $service_id, $service ) {
93
  $this->services[ $service_id ] = $service;
148
  * @throws Exception
149
  */
150
  public function update_exchange_rates() {
151
+ $currencies = $this->woocommerce_wpml->multi_currency->get_currency_codes();
152
+ $rates = $this->fetch_exchange_rates_from_active_service( $currencies );
153
+
154
+ foreach ( $rates as $to => $rate ) {
155
+ if ( $rate && is_numeric( $rate ) ) {
156
+ $this->save_exchage_rate( $to, $rate );
157
+ }
158
+ }
159
+
160
+ $this->settings['last_updated'] = current_time( 'timestamp' );
161
+ $this->save_settings();
162
+
163
+ return $rates;
164
+ }
165
+
166
+ /**
167
+ * @param array $currencies
168
+ *
169
+ * @return array
170
+ * @throws Exception
171
+ */
172
+ public function fetch_exchange_rates_from_active_service( $currencies ) {
173
  if ( ! isset( $this->services[ $this->settings['service'] ] ) ) {
174
  throw new Exception( 'The exchange rate service "' . $this->settings['service'] . '" is not defined.' );
175
  }
176
 
177
+ /** @var Service $service */
178
+ $service = $this->get_current_service();
179
 
 
180
  $default_currency = wcml_get_woocommerce_currency_option();
181
  $secondary_currencies = array_diff( $currencies, [ $default_currency ] );
182
 
191
 
192
  $this->apply_lifting_charge( $rates );
193
 
 
 
 
 
 
 
 
 
 
194
  return $rates;
195
  }
196
 
226
  public function update_exchange_rate_options( $post_data ) {
227
 
228
  if ( isset( $post_data['exchange-rates-automatic'] ) && $post_data['exchange-rates-automatic'] ) {
229
+ $active_service_changed = false;
230
+ $active_key_changed = false;
231
+ $active_service_id = Obj::prop( 'service', $this->settings );
232
+ $active_service = Obj::prop( $active_service_id, $this->services );
233
 
234
  $this->settings['automatic'] = (int) $post_data['exchange-rates-automatic'];
235
 
241
  }
242
 
243
  $this->settings['service'] = sanitize_text_field( $post_data['exchange-rates-service'] );
244
+ $active_service_changed = $active_service_id !== $this->settings['service'];
245
  }
246
 
247
  if ( isset( $post_data['services'] ) ) {
248
+ $active_service_key = $active_service ? $active_service->getSetting( 'api-key' ) : '';
249
 
250
  foreach ( $post_data['services'] as $service_id => $service_data ) {
251
  if ( isset( $service_data['api-key'] ) ) {
252
  $this->services[ $service_id ]->saveSetting( 'api-key', $service_data['api-key'] );
253
+
254
+ if ( $service_id === $active_service_id ) {
255
+ $active_key_changed = $active_service_key !== $service_data['api-key'];
256
+ }
257
  }
258
  }
259
  }
281
  } else {
282
  $this->enable_update_cronjob();
283
  }
284
+
285
+ if ( $active_key_changed || $active_service_changed ) {
286
+ $currentService = $this->get_current_service();
287
+
288
+ if ( $currentService ) {
289
+ $currentService->resetConnectionCache();
290
+ }
291
+
292
+ add_action( 'init', [ $this, 'update_rates_on_service_or_key_changed' ], 5 );
293
+ }
294
  } else {
295
  $this->settings['automatic'] = 0;
296
  $this->delete_update_cronjob();
297
  }
298
 
299
  $this->save_settings();
300
+ }
301
 
302
+ public function update_rates_on_service_or_key_changed() {
303
+ try {
304
+ $this->update_exchange_rates();
305
+ $this->woocommerce_wpml->get_multi_currency()->init_currencies(); // Re-init currencies.
306
+ wp_cache_add( self::KEY_RATES_UPDATED_FLAG, true );
307
+ add_action( 'shutdown', function() {
308
+ wp_cache_delete( WCML_Exchange_Rates::KEY_RATES_UPDATED_FLAG );
309
+ } );
310
+ } catch ( \Exception $e ) {} // Exception is handled inside `update_exchange_rates`.
311
  }
312
 
313
  public function enable_update_cronjob() {
395
 
396
  $schedules[ 'wcml_monthly_on_' . $this->settings['month_day'] ] = [
397
  'interval' => $interval,
398
+ /* translators: %s is the month day */
399
  'display' => sprintf( __( 'Monthly on the %s', 'woocommerce-multilingual' ), $month_day ),
400
  ];
401
 
404
  $week_day = $this->wp_locale->get_weekday( $this->settings['week_day'] );
405
  $schedules[ 'wcml_weekly_on_' . $this->settings['week_day'] ] = [
406
  'interval' => WEEK_IN_SECONDS,
407
+ /* translators: %s is the week day */
408
  'display' => sprintf( __( 'Weekly on %s', 'woocommerce-multilingual' ), $week_day ),
409
  ];
410
 
432
  return $month_day;
433
  }
434
 
435
+ /**
436
+ * @return Service|null
437
+ */
438
+ private function get_current_service() {
439
+ return Obj::prop( Obj::prop( 'service', (array) $this->settings ), (array) $this->services );
440
+ }
441
+
442
+ /**
443
+ * Check if a service is defined and has a key if needed.
444
+ *
445
+ * @return bool
446
+ */
447
+ public function is_current_service_actionable() {
448
+ $current_service = $this->get_current_service();
449
+
450
+ return $current_service
451
+ && (
452
+ ! $current_service->isKeyRequired()
453
+ || $current_service->getSetting( 'api-key' )
454
+ );
455
+ }
456
  }
classes/multi-currency/exchange-rate-services/ApiLayerService.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\MultiCurrency\ExchangeRateServices;
4
+
5
+ use WPML\FP\Obj;
6
+
7
+ abstract class ApiLayerService extends Service {
8
+
9
+ /**
10
+ * @return string
11
+ */
12
+ abstract protected function getApiLayerUrl();
13
+
14
+ /**
15
+ * @return string
16
+ */
17
+ abstract protected function getApiLegacyUrl();
18
+
19
+ /**
20
+ * @return string
21
+ */
22
+ public function getApiUrl() {
23
+ return $this->getSelectedApiEndpoint();
24
+ }
25
+
26
+ /**
27
+ * @return void
28
+ */
29
+ public function resetConnectionCache() {
30
+ $this->setSelectedApiEndpoint( null );
31
+ }
32
+
33
+ /**
34
+ * @param string|null $endpoint
35
+ *
36
+ * @return void
37
+ */
38
+ private function setSelectedApiEndpoint( $endpoint ) {
39
+ $this->saveSetting( 'selected-endpoint', $endpoint );
40
+ }
41
+
42
+ /**
43
+ * @return string|null
44
+ */
45
+ private function getSelectedApiEndpoint() {
46
+ return $this->getSetting( 'selected-endpoint' );
47
+ }
48
+
49
+ /**
50
+ * @param string $from The base currency code.
51
+ * @param array $tos The target currency codes.
52
+ *
53
+ * @return array|\WP_Error
54
+ */
55
+ protected function makeRequest( $from, $tos ) {
56
+ if ( $this->getSelectedApiEndpoint() ) {
57
+ $response = parent::makeRequest( $from, $tos );
58
+ } else {
59
+ $this->setSelectedApiEndpoint( $this->getApiLayerUrl() );
60
+ $response = parent::makeRequest( $from, $tos );
61
+
62
+ if ( $this->isWrongAuthenticationWithApiLayer( $response ) ) {
63
+ $this->setSelectedApiEndpoint( $this->getApiLegacyUrl() );
64
+ $response = parent::makeRequest( $from, $tos );
65
+ }
66
+ }
67
+
68
+ return $response;
69
+ }
70
+
71
+ /**
72
+ * @param object $data
73
+ *
74
+ * @return bool
75
+ */
76
+ private function isWrongAuthenticationWithApiLayer( $data ) {
77
+ return Obj::path( [ 'response', 'code' ], $data ) === 401;
78
+ }
79
+
80
+ /**
81
+ * @return array
82
+ */
83
+ protected function getRequestHeaders() {
84
+ return [ 'apikey' => $this->getApiKey() ];
85
+ }
86
+
87
+ /**
88
+ * @return bool
89
+ */
90
+ public function isKeyRequired() {
91
+ return true;
92
+ }
93
+ }
classes/multi-currency/exchange-rate-services/CurrencyLayer.php CHANGED
@@ -5,7 +5,7 @@ namespace WCML\MultiCurrency\ExchangeRateServices;
5
  /**
6
  * Class CurrencyLayer
7
  */
8
- class CurrencyLayer extends Service {
9
 
10
  /**
11
  * @return string
@@ -31,67 +31,42 @@ class CurrencyLayer extends Service {
31
  /**
32
  * @return string
33
  */
34
- public function getApiUrl() {
 
 
 
 
 
 
 
35
  return 'http://apilayer.net/api/live?access_key=%s&source=%s&currencies=%s&amount=1';
36
  }
37
 
38
  /**
 
 
39
  * @return bool
40
  */
41
- public function isKeyRequired() {
42
- return true;
43
  }
44
 
45
  /**
46
- * @param string $from Base currency.
47
- * @param array $tos Target currencies.
 
48
  *
49
  * @return array
50
- * @throws \Exception Thrown where there are connection problems.
51
  */
52
- public function getRates( $from, $tos ) {
53
- $this->clearLastError();
54
-
55
  $rates = [];
56
 
57
- $url = sprintf( $this->getApiUrl(), $this->getSetting( 'api-key' ), $from, implode( ',', $tos ) );
58
-
59
- $data = wp_safe_remote_get( $url );
60
-
61
- if ( is_wp_error( $data ) ) {
62
-
63
- $http_error = implode( "\n", $data->get_error_messages() );
64
- $this->saveLastError( $http_error );
65
- throw new \Exception( $http_error );
66
-
67
- }
68
-
69
- $json = json_decode( $data['body'] );
70
-
71
- if ( empty( $json->success ) ) {
72
- if ( ! empty( $json->error->info ) ) {
73
- if ( strpos( $json->error->info, 'You have not supplied an API Access Key' ) !== false ) {
74
- $error = __( 'You have entered an incorrect API Access Key', 'woocommerce-multilingual' );
75
- } else {
76
- $error = $json->error->info;
77
- }
78
- } else {
79
- $error = __( 'Cannot get exchange rates. Connection failed.', 'woocommerce-multilingual' );
80
- }
81
- $this->saveLastError( $error );
82
- throw new \Exception( $error );
83
- }
84
-
85
- if ( isset( $json->quotes ) ) {
86
- foreach ( $tos as $to ) {
87
- if ( isset( $json->quotes->{$from . $to} ) ) {
88
- $rates[ $to ] = round( $json->quotes->{$from . $to}, \WCML_Exchange_Rates::DIGITS_AFTER_DECIMAL_POINT );
89
- }
90
  }
91
  }
92
 
93
  return $rates;
94
-
95
  }
96
-
97
  }
5
  /**
6
  * Class CurrencyLayer
7
  */
8
+ class CurrencyLayer extends ApiLayerService {
9
 
10
  /**
11
  * @return string
31
  /**
32
  * @return string
33
  */
34
+ protected function getApiLayerUrl() {
35
+ return 'https://api.apilayer.com/currency_data/live?source=%2$s&currencies=%3$s';
36
+ }
37
+
38
+ /**
39
+ * @return string
40
+ */
41
+ protected function getApiLegacyUrl() {
42
  return 'http://apilayer.net/api/live?access_key=%s&source=%s&currencies=%s&amount=1';
43
  }
44
 
45
  /**
46
+ * @param object $decodedData
47
+ *
48
  * @return bool
49
  */
50
+ protected function isInvalidResponse( $decodedData ) {
51
+ return empty( $decodedData->quotes );
52
  }
53
 
54
  /**
55
+ * @param object $validData
56
+ * @param string $from
57
+ * @param array $tos
58
  *
59
  * @return array
 
60
  */
61
+ protected function extractRates( $validData, $from, $tos ) {
 
 
62
  $rates = [];
63
 
64
+ foreach ( $tos as $to ) {
65
+ if ( isset( $validData->quotes->{$from . $to} ) ) {
66
+ $rates[ $to ] = round( $validData->quotes->{$from . $to}, \WCML_Exchange_Rates::DIGITS_AFTER_DECIMAL_POINT );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
  }
69
 
70
  return $rates;
 
71
  }
 
72
  }
classes/multi-currency/exchange-rate-services/ExchangeRatesApi.php CHANGED
@@ -5,7 +5,7 @@ namespace WCML\MultiCurrency\ExchangeRateServices;
5
  /**
6
  * Class ExchangeRatesApi
7
  */
8
- class ExchangeRatesApi extends Service {
9
 
10
  /**
11
  * @return string
@@ -31,15 +31,14 @@ class ExchangeRatesApi extends Service {
31
  /**
32
  * @return string
33
  */
34
- public function getApiUrl() {
35
- return 'http://api.exchangeratesapi.io/v1/latest?access_key=%1$s&base=%2$s&symbols=%3$s';
36
  }
37
 
38
  /**
39
- * @return bool
40
  */
41
- public function isKeyRequired() {
42
- return true;
43
  }
44
-
45
  }
5
  /**
6
  * Class ExchangeRatesApi
7
  */
8
+ class ExchangeRatesApi extends ApiLayerService {
9
 
10
  /**
11
  * @return string
31
  /**
32
  * @return string
33
  */
34
+ protected function getApiLayerUrl() {
35
+ return 'https://api.apilayer.com/exchangerates_data/latest?base=%2$s&symbols=%3$s&amount=1';
36
  }
37
 
38
  /**
39
+ * @return string
40
  */
41
+ protected function getApiLegacyUrl() {
42
+ return 'http://api.exchangeratesapi.io/v1/latest?access_key=%1$s&base=%2$s&symbols=%3$s';
43
  }
 
44
  }
classes/multi-currency/exchange-rate-services/Fixerio.php CHANGED
@@ -5,7 +5,7 @@ namespace WCML\MultiCurrency\ExchangeRateServices;
5
  /**
6
  * Class Fixerio
7
  */
8
- class Fixerio extends Service {
9
 
10
  /**
11
  * @return string
@@ -31,15 +31,14 @@ class Fixerio extends Service {
31
  /**
32
  * @return string
33
  */
34
- public function getApiUrl() {
35
- return 'http://data.fixer.io/api/latest?access_key=%1$s&base=%2$s&symbols=%3$s';
36
  }
37
 
38
  /**
39
- * @return bool
40
  */
41
- public function isKeyRequired() {
42
- return true;
43
  }
44
-
45
  }
5
  /**
6
  * Class Fixerio
7
  */
8
+ class Fixerio extends ApiLayerService {
9
 
10
  /**
11
  * @return string
31
  /**
32
  * @return string
33
  */
34
+ protected function getApiLayerUrl() {
35
+ return 'https://api.apilayer.com/fixer/latest?base=%2$s&symbols=%3$s';
36
  }
37
 
38
  /**
39
+ * @return string
40
  */
41
+ protected function getApiLegacyUrl() {
42
+ return 'http://data.fixer.io/api/latest?access_key=%1$s&base=%2$s&symbols=%3$s';
43
  }
 
44
  }
classes/multi-currency/exchange-rate-services/Service.php CHANGED
@@ -37,6 +37,13 @@ abstract class Service {
37
  */
38
  abstract public function isKeyRequired();
39
 
 
 
 
 
 
 
 
40
  /**
41
  * @param string $from Base currency.
42
  * @param array $tos Target currencies.
@@ -47,43 +54,120 @@ abstract class Service {
47
  public function getRates( $from, $tos ) {
48
  $this->clearLastError();
49
 
50
- $rates = [];
51
 
52
- if ( $this->isKeyRequired() ) {
53
- $url = sprintf( $this->getApiUrl(), $this->getSetting( 'api-key' ), $from, implode( ',', $tos ) );
54
- } else {
55
- $url = sprintf( $this->getApiUrl(), $from, implode( ',', $tos ) );
56
- }
57
-
58
- $data = wp_safe_remote_get( $url );
59
-
60
- if ( is_wp_error( $data ) ) {
61
-
62
- $http_error = implode( "\n", $data->get_error_messages() );
63
  $this->saveLastError( $http_error );
64
  throw new \Exception( $http_error );
65
-
66
  }
67
 
68
- $json = json_decode( $data['body'] );
69
 
70
- if ( empty( $json->rates ) ) {
71
- if ( isset( $json->error->info ) ) {
72
- $error = $json->error->info;
73
- } else {
74
- $error = __( 'Cannot get exchange rates. Connection failed.', 'woocommerce-multilingual' );
75
- }
76
  $this->saveLastError( $error );
77
  throw new \Exception( $error );
78
  }
79
 
80
- foreach ( $json->rates as $to => $rate ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  $rates[ $to ] = round( $rate, \WCML_Exchange_Rates::DIGITS_AFTER_DECIMAL_POINT );
82
  }
83
 
84
  return $rates;
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  /**
88
  * @return array
89
  */
@@ -142,4 +226,10 @@ abstract class Service {
142
  return $this->getSetting( 'last_error' );
143
  }
144
 
 
 
 
 
 
 
145
  }
37
  */
38
  abstract public function isKeyRequired();
39
 
40
+ /**
41
+ * @return void
42
+ */
43
+ public function resetConnectionCache() {
44
+
45
+ }
46
+
47
  /**
48
  * @param string $from Base currency.
49
  * @param array $tos Target currencies.
54
  public function getRates( $from, $tos ) {
55
  $this->clearLastError();
56
 
57
+ $response = $this->makeRequest( $from, $tos );
58
 
59
+ if ( is_wp_error( $response ) ) {
60
+ $http_error = implode( "\n", $response->get_error_messages() );
 
 
 
 
 
 
 
 
 
61
  $this->saveLastError( $http_error );
62
  throw new \Exception( $http_error );
 
63
  }
64
 
65
+ $data = json_decode( $response['body'] );
66
 
67
+ if ( $this->isInvalidResponse( $data ) ) {
68
+ $error = self::get_formatted_error( $data );
 
 
 
 
69
  $this->saveLastError( $error );
70
  throw new \Exception( $error );
71
  }
72
 
73
+ return $this->extractRates( $data, $from, $tos );
74
+ }
75
+
76
+ /**
77
+ * @param string $from The base currency code.
78
+ * @param array $tos The target currency codes.
79
+ *
80
+ * @return array|\WP_Error
81
+ */
82
+ protected function makeRequest( $from, $tos ) {
83
+ if ( $this->isKeyRequired() ) {
84
+ $url = sprintf( $this->getApiUrl(), $this->getApiKey(), $from, implode( ',', $tos ) );
85
+ } else {
86
+ $url = sprintf( $this->getApiUrl(), $from, implode( ',', $tos ) );
87
+ }
88
+
89
+ return wp_safe_remote_get( $url, [ 'headers' => $this->getRequestHeaders() ] );
90
+ }
91
+
92
+ /**
93
+ * @return array
94
+ */
95
+ protected function getRequestHeaders() {
96
+ return [];
97
+ }
98
+
99
+ /**
100
+ * @param object $decodedData
101
+ *
102
+ * @return bool
103
+ */
104
+ protected function isInvalidResponse( $decodedData ) {
105
+ return empty( $decodedData->rates );
106
+ }
107
+
108
+ /**
109
+ * @param object $validData
110
+ * @param string $from
111
+ * @param array $tos
112
+ *
113
+ * @return array
114
+ */
115
+ protected function extractRates( $validData, $from, $tos ) {
116
+ $rates = [];
117
+
118
+ foreach ( $validData->rates as $to => $rate ) {
119
  $rates[ $to ] = round( $rate, \WCML_Exchange_Rates::DIGITS_AFTER_DECIMAL_POINT );
120
  }
121
 
122
  return $rates;
123
  }
124
 
125
+ /**
126
+ * Each service has its own response signature,
127
+ * and I also noticed that it does not always
128
+ * respect their own doc.
129
+ *
130
+ * So the idea is to just catch all possible information
131
+ * and return it as raw output.
132
+ *
133
+ * Example: "error_code: 104 - error_message: ..."
134
+ *
135
+ * @param array|\stdClass $response
136
+ *
137
+ * @return string
138
+ */
139
+ public static function get_formatted_error( $response ) {
140
+ // $getFromPath :: array -> string|null
141
+ $getFromPath = function( $path ) use ( $response ) {
142
+ try {
143
+ $value = Obj::path( $path, $response );
144
+ return is_string( $value ) || is_int( $value ) ? $value : null;
145
+ } catch ( \Exception $e ) {
146
+ return null;
147
+ }
148
+ };
149
+
150
+ $formattedError = wpml_collect( [
151
+ // Codes or types
152
+ 'error' => $getFromPath( [ 'error' ] ),
153
+ 'error_code' => $getFromPath( [ 'error', 'code' ] ),
154
+ 'error_type' => $getFromPath( [ 'error', 'type' ] ),
155
+ // Descriptions or messages
156
+ 'error_info' => $getFromPath( [ 'error', 'info' ] ),
157
+ 'error_message' => $getFromPath( [ 'error', 'message' ] ),
158
+ 'message' => $getFromPath( [ 'message' ] ),
159
+ 'description' => $getFromPath( [ 'description' ] ),
160
+ ] )->filter()
161
+ ->map( function( $value, $key ) {
162
+ return "$key: $value";
163
+ } )
164
+ ->implode( ' - ' );
165
+
166
+ return $formattedError
167
+ ? strip_tags( $formattedError )
168
+ : esc_html__( 'Cannot get exchange rates. Connection failed.', 'woocommerce-multilingual' );
169
+ }
170
+
171
  /**
172
  * @return array
173
  */
226
  return $this->getSetting( 'last_error' );
227
  }
228
 
229
+ /**
230
+ * @return string|null
231
+ */
232
+ protected function getApiKey() {
233
+ return $this->getSetting( 'api-key' );
234
+ }
235
  }
classes/multi-currency/geolocation/Geolocation.php CHANGED
@@ -2,15 +2,17 @@
2
 
3
  namespace WCML\MultiCurrency;
4
 
 
5
  use WPML\FP\Obj;
6
  use WPML\FP\Relation;
7
  use WPML\FP\Logic;
8
 
9
  class Geolocation {
10
 
11
- const DEFAULT_COUNTRY_CURRENCY_CONFIG = 'country-currency.json';
12
- const MODE_BY_LANGUAGE = 'by_language';
13
- const MODE_BY_LOCATION = 'by_location';
 
14
 
15
  /**
16
  * @return bool
@@ -19,17 +21,13 @@ class Geolocation {
19
  /** @var \woocommerce_wpml $woocommerce_wpml */
20
  global $woocommerce_wpml;
21
 
22
- $isByLocationMode = function() use ( $woocommerce_wpml ) {
23
- return Geolocation::MODE_BY_LOCATION === $woocommerce_wpml->get_setting( 'currency_mode' );
24
- };
25
-
26
  $useDefaultCurrencyByLocation = function() use ( $woocommerce_wpml ) {
27
  return (bool) wpml_collect( $woocommerce_wpml->get_setting( 'default_currencies', [] ) )
28
  ->first( Relation::equals( 'location' ) );
29
  };
30
 
31
  return wcml_is_multi_currency_on()
32
- && ( $isByLocationMode() || $useDefaultCurrencyByLocation() );
33
  }
34
 
35
  /**
@@ -63,7 +61,7 @@ class Geolocation {
63
  */
64
  private static function parseConfigFile() {
65
  $config = [];
66
- $configuration_file = WCML_PLUGIN_PATH . '/res/geolocation/' . self::DEFAULT_COUNTRY_CURRENCY_CONFIG;
67
 
68
  if ( file_exists( $configuration_file ) ) {
69
  $json_content = file_get_contents( $configuration_file );
@@ -74,48 +72,18 @@ class Geolocation {
74
  }
75
 
76
  /**
77
- * Get currency code by user country
78
- *
79
- * @return string|bool
80
- */
81
- public static function getCurrencyCodeByUserCountry() {
82
-
83
- $country = self::getUserCountry();
84
-
85
- if ( $country ) {
86
- $config = self::parseConfigFile();
87
-
88
- return isset( $config[ $country ] ) ? $config[ $country ] : false;
89
- }
90
-
91
- return false;
92
- }
93
-
94
- /**
95
- * Get first available country currency from settings if default country currency not active
96
  *
97
- * @param array $currenciesSettings
98
- *
99
- * @return string|bool
100
  */
101
- public static function getFirstAvailableCountryCurrencyFromSettings( $currenciesSettings ) {
102
-
103
- $currency = false;
104
-
105
- wpml_collect( $currenciesSettings )->each( function ( $settings, $code ) use ( &$currency ) {
106
- if ( self::isCurrencyAvailableForCountry( $settings ) ) {
107
- $currency = $code;
108
- }
109
- } );
110
-
111
- return $currency;
112
  }
113
 
114
  /**
115
  * @return string
116
  */
117
  public static function getUserCountry(){
118
-
119
  if ( defined( 'WCML_GEOLOCATED_COUNTRY' ) ) {
120
  return WCML_GEOLOCATED_COUNTRY;
121
  }
@@ -125,7 +93,8 @@ class Geolocation {
125
  'shipping' => self::getUserCountryByAddress( 'shipping' ),
126
  'geolocation' => self::getCountryByUserIp()
127
  ];
128
- $userCountry = $allUserCountries['billing'] ?: $allUserCountries['geolocation'];
 
129
 
130
  /**
131
  * This filter allows to override the address country declared by the user.
@@ -152,8 +121,8 @@ class Geolocation {
152
  * @return string
153
  */
154
  private static function getUserCountryByAddress( $addressType ){
155
-
156
  $orderCountry = self::getUserCountryFromOrder( $addressType );
 
157
  if( $orderCountry ){
158
  return $orderCountry;
159
  }
@@ -161,7 +130,7 @@ class Geolocation {
161
  $current_user_id = get_current_user_id();
162
 
163
  if ( $current_user_id ) {
164
- $customer = new \WC_Customer( $current_user_id, WC()->session ? true : false );
165
 
166
  return 'shipping' === $addressType ? $customer->get_shipping_country() : $customer->get_billing_country();
167
  }
@@ -177,42 +146,15 @@ class Geolocation {
177
  * @return string
178
  */
179
  private static function getUserCountryFromOrder( $addressType ) {
180
-
181
  $country = '';
182
- $wcAjax = Obj::prop( 'wc-ajax', $_GET );
183
 
184
- if ( 'update_order_review' === $wcAjax && isset( $_POST['country'] ) ) {
185
  $country = $_POST['country'];
186
- } elseif ( 'checkout' === $wcAjax && isset( $_POST[ $addressType . '_country' ] ) ) {
187
  $country = $_POST[ $addressType . '_country' ];
188
  }
189
 
190
  return wc_clean( wp_unslash( $country ) );
191
  }
192
-
193
- /**
194
- * @param array $currencySettings
195
- *
196
- * @return bool
197
- */
198
- public static function isCurrencyAvailableForCountry( $currencySettings ) {
199
-
200
- if ( isset( $currencySettings['location_mode'] ) ) {
201
-
202
- if ( 'all' === $currencySettings['location_mode'] ) {
203
- return true;
204
- }
205
-
206
- if ( 'include' === $currencySettings['location_mode'] && in_array( self::getUserCountry(), $currencySettings['countries'] ) ) {
207
- return true;
208
- }
209
-
210
- if ( 'exclude' === $currencySettings['location_mode'] && ! in_array( self::getUserCountry(), $currencySettings['countries'] ) ) {
211
- return true;
212
- }
213
-
214
- }
215
-
216
- return false;
217
- }
218
  }
2
 
3
  namespace WCML\MultiCurrency;
4
 
5
+ use WPML\FP\Fns;
6
  use WPML\FP\Obj;
7
  use WPML\FP\Relation;
8
  use WPML\FP\Logic;
9
 
10
  class Geolocation {
11
 
12
+ const DEFAULT_COUNTRY_CURRENCY_CONFIG = '/res/geolocation/country-currency.json';
13
+
14
+ const MODE_BY_LANGUAGE = Settings::MODE_BY_LANGUAGE;
15
+ const MODE_BY_LOCATION = Settings::MODE_BY_LOCATION;
16
 
17
  /**
18
  * @return bool
21
  /** @var \woocommerce_wpml $woocommerce_wpml */
22
  global $woocommerce_wpml;
23
 
 
 
 
 
24
  $useDefaultCurrencyByLocation = function() use ( $woocommerce_wpml ) {
25
  return (bool) wpml_collect( $woocommerce_wpml->get_setting( 'default_currencies', [] ) )
26
  ->first( Relation::equals( 'location' ) );
27
  };
28
 
29
  return wcml_is_multi_currency_on()
30
+ && ( Settings::isModeByLocation() || $useDefaultCurrencyByLocation() );
31
  }
32
 
33
  /**
61
  */
62
  private static function parseConfigFile() {
63
  $config = [];
64
+ $configuration_file = WCML_PLUGIN_PATH . self::DEFAULT_COUNTRY_CURRENCY_CONFIG;
65
 
66
  if ( file_exists( $configuration_file ) ) {
67
  $json_content = file_get_contents( $configuration_file );
72
  }
73
 
74
  /**
75
+ * @param string
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  *
77
+ * @return string|null
 
 
78
  */
79
+ public static function getOfficialCurrencyCodeByCountry( $country ) {
80
+ return Obj::prop( $country, self::parseConfigFile() );
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
  /**
84
  * @return string
85
  */
86
  public static function getUserCountry(){
 
87
  if ( defined( 'WCML_GEOLOCATED_COUNTRY' ) ) {
88
  return WCML_GEOLOCATED_COUNTRY;
89
  }
93
  'shipping' => self::getUserCountryByAddress( 'shipping' ),
94
  'geolocation' => self::getCountryByUserIp()
95
  ];
96
+
97
+ $userCountry = $allUserCountries['billing'] ?: $allUserCountries['geolocation'];
98
 
99
  /**
100
  * This filter allows to override the address country declared by the user.
121
  * @return string
122
  */
123
  private static function getUserCountryByAddress( $addressType ){
 
124
  $orderCountry = self::getUserCountryFromOrder( $addressType );
125
+
126
  if( $orderCountry ){
127
  return $orderCountry;
128
  }
130
  $current_user_id = get_current_user_id();
131
 
132
  if ( $current_user_id ) {
133
+ $customer = new \WC_Customer( $current_user_id, (bool) WC()->session );
134
 
135
  return 'shipping' === $addressType ? $customer->get_shipping_country() : $customer->get_billing_country();
136
  }
146
  * @return string
147
  */
148
  private static function getUserCountryFromOrder( $addressType ) {
 
149
  $country = '';
150
+ $isWcAjax = Relation::propEq( 'wc-ajax', Fns::__, $_GET );
151
 
152
+ if ( $isWcAjax( 'update_order_review' ) && isset( $_POST['country'] ) ) {
153
  $country = $_POST['country'];
154
+ } elseif ( $isWcAjax( 'checkout' ) && isset( $_POST[ $addressType . '_country' ] ) ) {
155
  $country = $_POST[ $addressType . '_country' ];
156
  }
157
 
158
  return wc_clean( wp_unslash( $country ) );
159
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  }
classes/multi-currency/geolocation/GeolocationBackendHooks.php CHANGED
@@ -2,7 +2,9 @@
2
 
3
  namespace WCML\MultiCurrency;
4
 
5
- class GeolocationBackendHooks implements \IWPML_Backend_Action {
 
 
6
 
7
  public function add_hooks() {
8
  add_filter( 'wcml_geolocation_is_used', [ Geolocation::class, 'isUsed' ] );
2
 
3
  namespace WCML\MultiCurrency;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ class GeolocationBackendHooks implements \IWPML_Backend_Action, IStandAloneAction {
8
 
9
  public function add_hooks() {
10
  add_filter( 'wcml_geolocation_is_used', [ Geolocation::class, 'isUsed' ] );
classes/multi-currency/geolocation/GeolocationFrontendHooks.php CHANGED
@@ -2,7 +2,9 @@
2
 
3
  namespace WCML\MultiCurrency;
4
 
5
- class GeolocationFrontendHooks implements \IWPML_Frontend_Action {
 
 
6
 
7
  const KEY_CLIENT_COUNTRY = 'wcml_client_country';
8
 
2
 
3
  namespace WCML\MultiCurrency;
4
 
5
+ use WCML\StandAlone\IStandAloneAction;
6
+
7
+ class GeolocationFrontendHooks implements \IWPML_Frontend_Action, IStandAloneAction {
8
 
9
  const KEY_CLIENT_COUNTRY = 'wcml_client_country';
10
 
classes/multi-currency/payment-gateways/class-wcml-currencies-payment-gateways.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  /**
4
  * Class WCML_Currencies_Payment_Gateways
5
  */
@@ -36,9 +38,9 @@ class WCML_Currencies_Payment_Gateways {
36
 
37
  add_filter( 'woocommerce_gateway_description', [ $this, 'filter_gateway_description' ], 10, 2 );
38
  add_filter( 'option_woocommerce_stripe_settings', [ 'WCML_Payment_Gateway_Stripe', 'filter_stripe_settings' ] );
 
39
 
40
- // Temporary until we support "WooCommerce PayPal Payments" addon - wcml-3727
41
- add_filter( 'woocommerce_should_load_paypal_standard', '__return_true' );
42
 
43
  if ( ! is_admin() && wcml_is_multi_currency_on() ) {
44
  add_filter(
@@ -95,9 +97,10 @@ class WCML_Currencies_Payment_Gateways {
95
  $this->available_gateways = $this->get_available_payment_gateways();
96
 
97
  $this->supported_gateways = [
98
- 'bacs' => 'WCML_Payment_Gateway_Bacs',
99
- 'paypal' => 'WCML_Payment_Gateway_PayPal',
100
- 'stripe' => 'WCML_Payment_Gateway_Stripe',
 
101
  ];
102
  $this->supported_gateways = apply_filters( 'wcml_supported_currency_payment_gateways', $this->supported_gateways );
103
 
1
  <?php
2
 
3
+ use WCML\Multicurrency\Transient\Hooks as TransientHooks;
4
+
5
  /**
6
  * Class WCML_Currencies_Payment_Gateways
7
  */
38
 
39
  add_filter( 'woocommerce_gateway_description', [ $this, 'filter_gateway_description' ], 10, 2 );
40
  add_filter( 'option_woocommerce_stripe_settings', [ 'WCML_Payment_Gateway_Stripe', 'filter_stripe_settings' ] );
41
+ add_filter( 'option_woocommerce-ppcp-settings', [ 'WCML_Payment_Gateway_PayPal_V2', 'filter_ppcp_args' ] );
42
 
43
+ TransientHooks::addHooks( WCML_Payment_Gateway_PayPal_V2::BEARER_TOKEN_TRANSIENT );
 
44
 
45
  if ( ! is_admin() && wcml_is_multi_currency_on() ) {
46
  add_filter(
97
  $this->available_gateways = $this->get_available_payment_gateways();
98
 
99
  $this->supported_gateways = [
100
+ 'bacs' => 'WCML_Payment_Gateway_Bacs',
101
+ 'paypal' => 'WCML_Payment_Gateway_PayPal',
102
+ 'ppcp-gateway' => 'WCML_Payment_Gateway_PayPal_V2',
103
+ 'stripe' => 'WCML_Payment_Gateway_Stripe',
104
  ];
105
  $this->supported_gateways = apply_filters( 'wcml_supported_currency_payment_gateways', $this->supported_gateways );
106
 
classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal-v2.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WPML\FP\Obj;
4
+ use WPML\FP\Fns;
5
+ use function WCML\functions\getClientCurrency;
6
+
7
+ /**
8
+ * @see https://wordpress.org/plugins/woocommerce-paypal-payments/
9
+ */
10
+ class WCML_Payment_Gateway_PayPal_V2 extends WCML_Payment_Gateway_PayPal {
11
+
12
+ const ID = 'ppcp-gateway';
13
+
14
+ const FIELDS = [
15
+ 'merchant_email',
16
+ 'merchant_id',
17
+ 'client_id',
18
+ 'client_secret',
19
+ ];
20
+
21
+ const BEARER_TOKEN_TRANSIENT = 'ppcp-paypal-bearerppcp-bearer';
22
+
23
+ public function get_output_model() {
24
+ return [
25
+ 'id' => $this->get_id(),
26
+ 'title' => $this->get_title(),
27
+ 'isSupported' => true,
28
+ 'settings' => $this->get_currencies_details(),
29
+ 'tooltip' => '',
30
+ 'strings' => [
31
+ 'labelCurrency' => __( 'Currency', 'woocommerce-multilingual' ),
32
+ 'labelPayPalEmail' => __( 'PayPal Email', 'woocommerce-multilingual' ),
33
+ 'labelMerchantId' => __( 'Merchant ID', 'woocommerce-multilingual' ),
34
+ 'labelClientId' => __( 'Client ID', 'woocommerce-multilingual' ),
35
+ 'labelSecretKey' => __( 'Secret Key', 'woocommerce-multilingual' ),
36
+ // translators: %s is currency code.
37
+ 'tooltipNotSupported' => __( 'This gateway does not support %s. To show this gateway please select another currency.', 'woocommerce-multilingual' ),
38
+ ],
39
+ ];
40
+ }
41
+
42
+ /**
43
+ * @return array
44
+ */
45
+ public function get_currencies_details() {
46
+ $currencies_details = [];
47
+ $default_currency = wcml_get_woocommerce_currency_option();
48
+ $woocommerce_currencies = get_woocommerce_currencies();
49
+
50
+ foreach ( $woocommerce_currencies as $code => $currency ) {
51
+ if ( $default_currency === $code ) {
52
+ $getSetting = Obj::propOr( '', Fns::__, $this->get_gateway()->settings );
53
+ } else {
54
+ $getSetting = Obj::propOr( '', Fns::__, $this->get_setting( $code ) );
55
+ }
56
+
57
+ foreach ( self::FIELDS as $key ) {
58
+ $currencies_details[ $code ][ $key ] = $getSetting( $key );
59
+ }
60
+
61
+ $currencies_details[ $code ]['currency'] = $code;
62
+ $currencies_details[ $code ]['isValid'] = $this->is_valid_for_use( $code );
63
+ }
64
+
65
+ return $currencies_details;
66
+ }
67
+
68
+ public function add_hooks() {
69
+
70
+ }
71
+
72
+ /**
73
+ * @param array $settings
74
+ *
75
+ * @return array
76
+ */
77
+ public static function filter_ppcp_args( $settings ) {
78
+ if ( is_admin() ) {
79
+ return $settings;
80
+ }
81
+
82
+ $gateway = Obj::prop( getClientCurrency(), get_option( self::OPTION_KEY . self::ID, [] ) );
83
+
84
+ if ( $gateway ) {
85
+ $getSetting = Obj::prop( Fns::__, $gateway );
86
+
87
+ foreach ( self::FIELDS as $key ) {
88
+ $settings[ $key ] = $getSetting( $key ) ?: $settings[ $key ];
89
+ }
90
+ }
91
+
92
+ return $settings;
93
+ }
94
+
95
+ }
classes/multi-currency/payment-gateways/class-wcml-payment-gateway-paypal.php CHANGED
@@ -46,13 +46,14 @@ class WCML_Payment_Gateway_PayPal extends WCML_Payment_Gateway {
46
  'strings' => [
47
  'labelCurrency' => __( 'Currency', 'woocommerce-multilingual' ),
48
  'labelPayPalEmail' => __( 'PayPal Email', 'woocommerce-multilingual' ),
 
49
  'tooltipNotSupported' => __( 'This gateway does not support %s. To show this gateway please select another currency.', 'woocommerce-multilingual' ),
50
  ],
51
  ];
52
  }
53
 
54
  /**
55
- * @param $currency
56
  *
57
  * @return bool
58
  */
@@ -77,8 +78,6 @@ class WCML_Payment_Gateway_PayPal extends WCML_Payment_Gateway {
77
  }
78
 
79
  /**
80
- * @param array $active_currencies
81
- *
82
  * @return array
83
  */
84
  public function get_currencies_details() {
@@ -90,14 +89,14 @@ class WCML_Payment_Gateway_PayPal extends WCML_Payment_Gateway {
90
  foreach ( $woocommerce_currencies as $code => $currency ) {
91
 
92
  if ( $default_currency === $code ) {
93
- $currencies_details[ $code ]['value'] = $this->get_gateway()->settings['email'];
94
  $currencies_details[ $code ]['currency'] = $code;
95
- $currencies_details[ $code ]['isValid'] = $this->is_valid_for_use( $default_currency );
96
  } else {
97
  $currency_gateway_setting = $this->get_setting( $code );
98
  $currencies_details[ $code ]['value'] = $currency_gateway_setting ? $currency_gateway_setting['value'] : '';
99
  $currencies_details[ $code ]['currency'] = $currency_gateway_setting ? $currency_gateway_setting['currency'] : $code;
100
- $currencies_details[ $code ]['isValid'] = $this->is_valid_for_use( $code );
101
  }
102
  }
103
 
46
  'strings' => [
47
  'labelCurrency' => __( 'Currency', 'woocommerce-multilingual' ),
48
  'labelPayPalEmail' => __( 'PayPal Email', 'woocommerce-multilingual' ),
49
+ // translators: %s is currency code.
50
  'tooltipNotSupported' => __( 'This gateway does not support %s. To show this gateway please select another currency.', 'woocommerce-multilingual' ),
51
  ],
52
  ];
53
  }
54
 
55
  /**
56
+ * @param string $currency
57
  *
58
  * @return bool
59
  */
78
  }
79
 
80
  /**
 
 
81
  * @return array
82
  */
83
  public function get_currencies_details() {
89
  foreach ( $woocommerce_currencies as $code => $currency ) {
90
 
91
  if ( $default_currency === $code ) {
92
+ $currencies_details[ $code ]['value'] = isset( $this->get_gateway()->settings['email'] ) ? $this->get_gateway()->settings['email'] : '';
93
  $currencies_details[ $code ]['currency'] = $code;
94
+ $currencies_details[ $code ]['isValid'] = $this->is_valid_for_use( $default_currency );
95
  } else {
96
  $currency_gateway_setting = $this->get_setting( $code );
97
  $currencies_details[ $code ]['value'] = $currency_gateway_setting ? $currency_gateway_setting['value'] : '';
98
  $currencies_details[ $code ]['currency'] = $currency_gateway_setting ? $currency_gateway_setting['currency'] : $code;
99
+ $currencies_details[ $code ]['isValid'] = $this->is_valid_for_use( $code );
100
  }
101
  }
102
 
classes/pointers/class-wcml-pointers.php CHANGED
@@ -1,5 +1,7 @@
1
  <?php
2
 
 
 
3
  class WCML_Pointers{
4
 
5
  public function add_hooks() {
@@ -8,24 +10,29 @@ class WCML_Pointers{
8
 
9
  public function setup() {
10
  $current_screen = get_current_screen();
11
-
12
  if ( empty( $current_screen ) ) {
13
  return;
14
  }
 
 
 
 
15
 
16
- $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : '';
17
- $section = isset( $_GET['section'] ) ? $_GET['section'] : '';
 
18
  wp_register_style( 'wcml-pointers', WCML_PLUGIN_URL . '/res/css/wcml-pointers.css' );
19
 
20
- if ( 'edit-product' === $current_screen->id ) {
21
  add_action( 'admin_footer', array( $this, 'add_products_translation_link' ), 100 );
22
  } elseif ( 'woocommerce_page_wc-settings' === $current_screen->id ) {
23
- if ( 'shipping' === $tab && 'classes' === $section ) {
24
  add_action( 'admin_footer', array( $this, 'add_shipping_classes_translation_link' ) );
25
  } elseif ( ! $tab || 'general' === $tab ) {
26
  add_filter( 'woocommerce_general_settings', array( $this, 'add_multi_currency_link' ) );
27
- } elseif ( 'account' === $tab ) {
28
- add_filter( 'woocommerce_account_settings', array( $this, 'add_endpoints_translation_link' ) );
29
  }
30
  }
31
  }
@@ -53,7 +60,7 @@ class WCML_Pointers{
53
  */
54
  public function add_multi_currency_link( array $settings ) {
55
  $link = admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' );
56
- $name = __( 'Configure multi-currency for multilingual sites', 'woocommerce-multilingual' );
57
 
58
  $anchor = '<a class="button button-small button-wpml wcml-pointer-multi_currency" href="{{ url }}">{{ text }}</a>';
59
 
@@ -71,7 +78,7 @@ class WCML_Pointers{
71
 
72
  $anchor = '<a class="button button-small button-wpml wcml-pointer-endpoints_translation" href="{{ url }}">{{ text }}</a>';
73
 
74
- return $this->add_link_with_settings( $link, $name, 'account_endpoint_options', $settings, $anchor );
75
  }
76
 
77
  /**
1
  <?php
2
 
3
+ use function WCML\functions\isStandAlone;
4
+
5
  class WCML_Pointers{
6
 
7
  public function add_hooks() {
10
 
11
  public function setup() {
12
  $current_screen = get_current_screen();
13
+
14
  if ( empty( $current_screen ) ) {
15
  return;
16
  }
17
+
18
+ if ( ! WCML_Capabilities::canManageWcml() ) {
19
+ return;
20
+ }
21
 
22
+ $tab = isset( $_GET['tab'] ) ? $_GET['tab'] : '';
23
+ $section = isset( $_GET['section'] ) ? $_GET['section'] : '';
24
+ $isFullMode = ! isStandAlone();
25
  wp_register_style( 'wcml-pointers', WCML_PLUGIN_URL . '/res/css/wcml-pointers.css' );
26
 
27
+ if ( $isFullMode && 'edit-product' === $current_screen->id ) {
28
  add_action( 'admin_footer', array( $this, 'add_products_translation_link' ), 100 );
29
  } elseif ( 'woocommerce_page_wc-settings' === $current_screen->id ) {
30
+ if ( $isFullMode && 'shipping' === $tab && 'classes' === $section ) {
31
  add_action( 'admin_footer', array( $this, 'add_shipping_classes_translation_link' ) );
32
  } elseif ( ! $tab || 'general' === $tab ) {
33
  add_filter( 'woocommerce_general_settings', array( $this, 'add_multi_currency_link' ) );
34
+ } elseif ( $isFullMode && 'advanced' === $tab ) {
35
+ add_filter( 'woocommerce_settings_pages', array( $this, 'add_endpoints_translation_link' ) );
36
  }
37
  }
38
  }
60
  */
61
  public function add_multi_currency_link( array $settings ) {
62
  $link = admin_url( 'admin.php?page=wpml-wcml&tab=multi-currency' );
63
+ $name = __( 'Configure multicurrency for multilingual sites', 'woocommerce-multilingual' );
64
 
65
  $anchor = '<a class="button button-small button-wpml wcml-pointer-multi_currency" href="{{ url }}">{{ text }}</a>';
66
 
78
 
79
  $anchor = '<a class="button button-small button-wpml wcml-pointer-endpoints_translation" href="{{ url }}">{{ text }}</a>';
80
 
81
+ return $this->add_link_with_settings( $link, $name, 'checkout_endpoint_options', $settings, $anchor );
82
  }
83
 
84
  /**
classes/privacy/class-wcml-privacy-content.php CHANGED
@@ -9,7 +9,7 @@ class WCML_Privacy_Content extends WPML_Privacy_Content {
9
  * @return string
10
  */
11
  protected function get_plugin_name() {
12
- return 'WooCommerce Multilingual';
13
  }
14
 
15
  /**
@@ -17,8 +17,8 @@ class WCML_Privacy_Content extends WPML_Privacy_Content {
17
  */
18
  protected function get_privacy_policy() {
19
  return [
20
- __( 'WooCommerce Multilingual will use cookies to understand the basket info when using languages in domains and to transfer data between the domains.', 'woocommerce-multilingual' ),
21
- __( 'WooCommerce Multilingual will also use cookies to identify the language and currency of each customer’s order as well as the currency of the reports created by WooCommerce. WooCommerce Multilingual extends these reports by adding the currency’s information.', 'woocommerce-multilingual' ),
22
  ];
23
  }
24
 
9
  * @return string
10
  */
11
  protected function get_plugin_name() {
12
+ return 'WooCommerce Multilingual & Multicurrency';
13
  }
14
 
15
  /**
17
  */
18
  protected function get_privacy_policy() {
19
  return [
20
+ __( 'WooCommerce Multilingual & Multicurrency will use cookies to understand the basket info when using languages in domains and to transfer data between the domains.', 'woocommerce-multilingual' ),
21
+ __( 'WooCommerce Multilingual & Multicurrency will also use cookies to identify the language and currency of each customer’s order as well as the currency of the reports created by WooCommerce. WooCommerce Multilingual extends these reports by adding the currency’s information.', 'woocommerce-multilingual' ),
22
  ];
23
  }
24
 
classes/shortcodes/class-wcml-wc-shortcode-product-category.php CHANGED
@@ -19,7 +19,7 @@ class WCML_WC_Shortcode_Product_Category {
19
  *
20
  * @param SitePress $sitepress
21
  */
22
- public function __construct( SitePress $sitepress ) {
23
  $this->sitepress = $sitepress;
24
  }
25
 
19
  *
20
  * @param SitePress $sitepress
21
  */
22
+ public function __construct( \WPML\Core\ISitePress $sitepress ) {
23
  $this->sitepress = $sitepress;
24
  }
25
 
classes/taxonomy-translation/class-wcml-taxonomy-translation-link-filters.php CHANGED
@@ -31,10 +31,12 @@ class WCML_Taxonomy_Translation_Link_Filters {
31
  $link = sprintf(
32
  '<a href="%s">%s</a>',
33
  $this->get_screen_url( $taxonomy->name ),
 
34
  sprintf( esc_html__( '%s translation', 'woocommerce-multilingual' ), $taxonomy->labels->singular_name )
35
  );
36
 
37
  $text = sprintf(
 
38
  esc_html__( 'Translating %1$s? Use the %2$s table for easier translation.', 'woocommerce-multilingual' ),
39
  $taxonomy->labels->name,
40
  $link
31
  $link = sprintf(
32
  '<a href="%s">%s</a>',
33
  $this->get_screen_url( $taxonomy->name ),
34
+ /* translators: %s is a taxonomy singular label */
35
  sprintf( esc_html__( '%s translation', 'woocommerce-multilingual' ), $taxonomy->labels->singular_name )
36
  );
37
 
38
  $text = sprintf(
39
+ /* translators: %1$s is a taxonomy singular label and %2$s is an HTML link */
40
  esc_html__( 'Translating %1$s? Use the %2$s table for easier translation.', 'woocommerce-multilingual' ),
41
  $taxonomy->labels->name,
42
  $link
classes/urls/class-wcml-xdomain-data.php CHANGED
@@ -4,7 +4,7 @@
4
  * Handles data being passed between different domains using WPML xDomain logic
5
  * https://wpml.org/?page_id=693147
6
  */
7
- class WCML_xDomain_Data {
8
 
9
  /**
10
  * @var WPML_Cookie
4
  * Handles data being passed between different domains using WPML xDomain logic
5
  * https://wpml.org/?page_id=693147
6
  */
7
+ class WCML_xDomain_Data implements \IWPML_Backend_Action, \IWPML_Frontend_Action, \IWPML_DIC_Action {
8
 
9
  /**
10
  * @var WPML_Cookie
classes/wcml-setup/class-wcml-setup.php CHANGED
@@ -28,7 +28,7 @@ class WCML_Setup {
28
  * @param woocommerce_wpml $woocommerce_wpml
29
  * @param SitePress $sitepress
30
  */
31
- public function __construct( WCML_Setup_UI $ui, WCML_Setup_Handlers $handlers, woocommerce_wpml $woocommerce_wpml, SitePress $sitepress ) {
32
 
33
  $this->ui = $ui;
34
  $this->handlers = $handlers;
@@ -153,7 +153,7 @@ class WCML_Setup {
153
 
154
  $this->step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : current( array_keys( $this->steps ) );
155
 
156
- wp_enqueue_style( 'otgs-ico', ICL_PLUGIN_URL . '/res/css/otgs-ico.css', null, ICL_SITEPRESS_VERSION );
157
  wp_enqueue_style(
158
  'wcml-setup',
159
  WCML_PLUGIN_URL . '/res/css/wcml-setup.css',
@@ -204,7 +204,7 @@ class WCML_Setup {
204
  }
205
 
206
  if ( ! current_user_can( 'manage_options' ) ) {
207
- wp_die( esc_html__( "Cheatin' huh?", 'woocommerce' ) );
208
  }
209
 
210
  $this->complete_setup();
28
  * @param woocommerce_wpml $woocommerce_wpml
29
  * @param SitePress $sitepress
30
  */
31
+ public function __construct( WCML_Setup_UI $ui, WCML_Setup_Handlers $handlers, woocommerce_wpml $woocommerce_wpml, \WPML\Core\ISitePress $sitepress ) {
32
 
33
  $this->ui = $ui;
34
  $this->handlers = $handlers;
153
 
154
  $this->step = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : current( array_keys( $this->steps ) );
155
 
156
+ wp_enqueue_style( 'otgs-ico', \WCML\functions\assetLink( '/res/css/otgs-ico.css' ), null, ICL_SITEPRESS_VERSION );
157
  wp_enqueue_style(
158
  'wcml-setup',
159
  WCML_PLUGIN_URL . '/res/css/wcml-setup.css',
204
  }
205
 
206
  if ( ! current_user_can( 'manage_options' ) ) {
207
+ wp_die( esc_html__( "Cheatin' huh?", 'woocommerce-multilingual' ) );
208
  }
209
 
210
  $this->complete_setup();
compatibility/AdventureTours/Factory.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\AdventureTours;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Adventure_tours;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+
10
+ class Factory extends ComponentFactory {
11
+
12
+ /**
13
+ * @inheritDoc
14
+ */
15
+ public function create() {
16
+ return new WCML_Adventure_tours( getWooCommerceWpml(), getSitePress(), self::getElementTranslationPackage() );
17
+ }
18
+ }
compatibility/{class-wcml-adventure-tours.php → AdventureTours/class-wcml-adventure-tours.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_Adventure_tours {
4
 
5
  /**
6
  * @var woocommerce_wpml
1
  <?php
2
 
3
+ class WCML_Adventure_tours implements \IWPML_Action {
4
 
5
  /**
6
  * @var woocommerce_wpml
compatibility/Aurum/Factory.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\Aurum;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://laborator.co/themes/aurum/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+ }
compatibility/{class-wcml-aurum.php → Aurum/MulticurrencyHooks.php} RENAMED
@@ -1,17 +1,21 @@
1
  <?php
2
 
3
- class WCML_Aurum {
4
 
5
- public function __construct() {
6
 
 
7
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_ajax_action' ] );
8
  }
9
 
 
 
 
 
 
10
  public function add_ajax_action( $actions ) {
11
-
12
  $actions[] = 'lab_wc_add_to_cart';
13
 
14
  return $actions;
15
  }
16
-
17
  }
1
  <?php
2
 
3
+ namespace WCML\Compatibility\Aurum;
4
 
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
 
7
+ public function add_hooks() {
8
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_ajax_action' ] );
9
  }
10
 
11
+ /**
12
+ * @param array $actions
13
+ *
14
+ * @return array
15
+ */
16
  public function add_ajax_action( $actions ) {
 
17
  $actions[] = 'lab_wc_add_to_cart';
18
 
19
  return $actions;
20
  }
 
21
  }
compatibility/ComponentFactory.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility;
4
+
5
+ use WooCommerce;
6
+ use wpdb;
7
+ use WPML_Element_Translation_Package;
8
+
9
+ abstract class ComponentFactory implements \IWPML_Backend_Action_Loader, \IWPML_Frontend_Action_Loader {
10
+
11
+ /**
12
+ * @return callable|\IWPML_Action|\IWPML_Action[]|void|null
13
+ */
14
+ abstract public function create();
15
+
16
+ /**
17
+ * @return wpdb
18
+ */
19
+ protected static function getWpdb() {
20
+ /**
21
+ * @var wpdb $wpdb
22
+ */
23
+ global $wpdb;
24
+
25
+ return $wpdb;
26
+ }
27
+
28
+ /**
29
+ * @return WooCommerce
30
+ */
31
+ protected static function getWooCommerce() {
32
+ /**
33
+ * @var WooCommerce $woocommerce
34
+ */
35
+ global $woocommerce;
36
+
37
+ return $woocommerce;
38
+ }
39
+
40
+ /**
41
+ * @return WPML_Element_Translation_Package|null
42
+ */
43
+ protected static function getElementTranslationPackage() {
44
+ return class_exists( 'WPML_Element_Translation_Package' ) ? new WPML_Element_Translation_Package() : null;
45
+ }
46
+
47
+ /**
48
+ * @return \WPML_Post_Translation|null
49
+ */
50
+ protected static function getPostTranslations() {
51
+ /**
52
+ * @var \WPML_Post_Translation|null $wpml_post_translations
53
+ */
54
+ global $wpml_post_translations;
55
+
56
+ return $wpml_post_translations;
57
+ }
58
+ }
compatibility/Flatsome/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\Flatsome;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Flatsome;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Flatsome();
15
+ }
16
+ }
compatibility/{class-wcml-flatsome.php → Flatsome/class-wcml-flatsome.php} RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
- class WCML_Flatsome {
4
 
5
- public function __construct() {
6
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_action_to_multi_currency_ajax' ] );
7
  }
8
 
1
  <?php
2
 
3
+ class WCML_Flatsome implements \IWPML_Action {
4
 
5
+ public function add_hooks() {
6
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_action_to_multi_currency_ajax' ] );
7
  }
8
 
compatibility/GravityForms/Factory.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\GravityForms;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_gravityforms;
8
+ use function WCML\functions\getSitePress;
9
+ use function WCML\functions\getWooCommerceWpml;
10
+ use function WCML\functions\isStandAlone;
11
+
12
+ /**
13
+ * @see https://www.gravityforms.com/
14
+ */
15
+ class Factory extends ComponentFactory implements IStandAloneAction {
16
+
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ public function create() {
21
+ $hooks = [];
22
+
23
+ if ( wcml_is_multi_currency_on() ) {
24
+ $hooks[] = new MulticurrencyHooks();
25
+ }
26
+
27
+ if ( ! isStandAlone() ) {
28
+ $hooks[] = new WCML_gravityforms( getSitePress(), getWooCommerceWpml() );
29
+ }
30
+
31
+ return $hooks;
32
+ }
33
+
34
+ }
compatibility/GravityForms/MulticurrencyHooks.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\GravityForms;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'gform_formatted_money', [ $this, 'wcml_convert_price' ], 10, 2 );
9
+ add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_ajax_action' ] );
10
+ }
11
+
12
+ /**
13
+ * @param string $formatted
14
+ * @param string $unformatted
15
+ *
16
+ * @return string
17
+ */
18
+ public function wcml_convert_price( $formatted, $unformatted ) {
19
+ if ( ! is_admin() ) {
20
+ $currency = apply_filters( 'wcml_price_currency', wcml_get_woocommerce_currency_option() );
21
+ $formatted = strip_tags( wc_price( apply_filters( 'wcml_raw_price_amount', $unformatted ), [ 'currency' => $currency ] ) );
22
+ }
23
+ return $formatted;
24
+ }
25
+
26
+ /**
27
+ * @param string[] $actions
28
+ *
29
+ * @return string[]
30
+ */
31
+ public function add_ajax_action( $actions ) {
32
+ $actions[] = 'get_updated_price'; // Deprecated from 2.7.
33
+ $actions[] = 'gforms_get_updated_price';
34
+ return $actions;
35
+ }
36
+
37
+ }
compatibility/{class-wcml-gravityforms.php → GravityForms/class-wcml-gravityforms.php} RENAMED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
- class WCML_gravityforms {
4
 
5
  /**
6
- * @param SitePress $sitepress
7
  */
8
  private $sitepress;
9
 
@@ -18,33 +18,15 @@ class WCML_gravityforms {
18
  }
19
 
20
  public function add_hooks() {
21
- add_filter( 'gform_formatted_money', [ $this, 'wcml_convert_price' ], 10, 2 );
22
- add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'add_ajax_action' ] );
23
-
24
  add_action( 'wcml_after_duplicate_product_post_meta', [ $this, 'sync_gf_data' ], 10, 2 );
25
  }
26
 
27
- public function wcml_convert_price( $formatted, $unformatted ) {
28
- if ( ! is_admin() ) {
29
- $currency = apply_filters( 'wcml_price_currency', wcml_get_woocommerce_currency_option() );
30
- $formatted = strip_tags( wc_price( apply_filters( 'wcml_raw_price_amount', $unformatted ), [ 'currency' => $currency ] ) );
31
- }
32
- return $formatted;
33
- }
34
-
35
-
36
- public function add_ajax_action( $actions ) {
37
- $actions[] = 'get_updated_price'; // Deprecated from 2.7.
38
- $actions[] = 'gforms_get_updated_price';
39
- return $actions;
40
- }
41
-
42
  /**
43
  * @param int $original_product_id
44
  * @param int $trnsl_product_id
45
  */
46
  public function sync_gf_data( $original_product_id, $trnsl_product_id ) {
47
- // sync only if WCML editor is in use
48
  if ( $this->woocommerce_wpml->is_wpml_prior_4_2() ) {
49
  $wcml_settings = get_option( '_wcml_settings' );
50
  $is_using_tm_editor = $wcml_settings['trnsl_interface'];
@@ -53,7 +35,7 @@ class WCML_gravityforms {
53
  }
54
 
55
  if ( $is_using_tm_editor ) {
56
- $orig_gf = maybe_unserialize( get_post_meta( $original_product_id, '_gravity_form_data', true ) );
57
 
58
  if ( $orig_gf ) {
59
  $trnsl_gf = maybe_unserialize( get_post_meta( $trnsl_product_id, '_gravity_form_data', true ) );
1
  <?php
2
 
3
+ class WCML_gravityforms implements \IWPML_Action {
4
 
5
  /**
6
+ * @var SitePress $sitepress
7
  */
8
  private $sitepress;
9
 
18
  }
19
 
20
  public function add_hooks() {
 
 
 
21
  add_action( 'wcml_after_duplicate_product_post_meta', [ $this, 'sync_gf_data' ], 10, 2 );
22
  }
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  /**
25
  * @param int $original_product_id
26
  * @param int $trnsl_product_id
27
  */
28
  public function sync_gf_data( $original_product_id, $trnsl_product_id ) {
29
+ // sync only if WCML editor is in use.
30
  if ( $this->woocommerce_wpml->is_wpml_prior_4_2() ) {
31
  $wcml_settings = get_option( '_wcml_settings' );
32
  $is_using_tm_editor = $wcml_settings['trnsl_interface'];
35
  }
36
 
37
  if ( $is_using_tm_editor ) {
38
+ $orig_gf = maybe_unserialize( get_post_meta( $original_product_id, '_gravity_form_data', true ) );
39
 
40
  if ( $orig_gf ) {
41
  $trnsl_gf = maybe_unserialize( get_post_meta( $trnsl_product_id, '_gravity_form_data', true ) );
compatibility/KlarnaPayments/Factory.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\KlarnaPayments;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://wordpress.org/plugins/klarna-checkout-for-woocommerce/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+
26
+ }
compatibility/{class-wcml-klarna-gateway.php → KlarnaPayments/MulticurrencyHooks.php} RENAMED
@@ -1,15 +1,14 @@
1
  <?php
2
 
3
- class WCML_Klarna_Gateway {
4
 
5
- public function add_hooks() {
6
 
 
7
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'ajax_action_needs_multi_currency' ] );
8
-
9
  }
10
 
11
  public function ajax_action_needs_multi_currency( $actions ) {
12
-
13
  $actions[] = 'klarna_checkout_cart_callback_update';
14
  $actions[] = 'klarna_checkout_coupons_callback';
15
  $actions[] = 'klarna_checkout_remove_coupon_callback';
1
  <?php
2
 
3
+ namespace WCML\Compatibility\KlarnaPayments;
4
 
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
 
7
+ public function add_hooks() {
8
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'ajax_action_needs_multi_currency' ] );
 
9
  }
10
 
11
  public function ajax_action_needs_multi_currency( $actions ) {
 
12
  $actions[] = 'klarna_checkout_cart_callback_update';
13
  $actions[] = 'klarna_checkout_coupons_callback';
14
  $actions[] = 'klarna_checkout_remove_coupon_callback';
compatibility/MaxStorePro/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\MaxStorePro;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_MaxStore;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_MaxStore();
15
+ }
16
+ }
compatibility/{class-wcml-maxstore.php → MaxStorePro/class-wcml-maxstore.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_MaxStore {
4
 
5
  public function add_hooks() {
6
 
1
  <?php
2
 
3
+ class WCML_MaxStore implements \IWPML_Action {
4
 
5
  public function add_hooks() {
6
 
compatibility/PerProductShipping/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\PerProductShipping;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Per_Product_Shipping;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Per_Product_Shipping();
15
+ }
16
+ }
compatibility/{class-wcml-per-product-shipping.php → PerProductShipping/class-wcml-per-product-shipping.php} RENAMED
@@ -1,15 +1,11 @@
1
  <?php
2
 
3
- class WCML_Per_Product_Shipping {
4
-
5
- public function __construct() {
6
 
 
7
  if ( ! is_admin() ) {
8
-
9
  add_filter( 'woocommerce_per_product_shipping_get_matching_rule_product_id', [ $this, 'original_product_id' ] );
10
-
11
  }
12
-
13
  }
14
 
15
  public function original_product_id( $product_id ) {
1
  <?php
2
 
3
+ class WCML_Per_Product_Shipping implements \IWPML_Action {
 
 
4
 
5
+ public function add_hooks() {
6
  if ( ! is_admin() ) {
 
7
  add_filter( 'woocommerce_per_product_shipping_get_matching_rule_product_id', [ $this, 'original_product_id' ] );
 
8
  }
 
9
  }
10
 
11
  public function original_product_id( $product_id ) {
compatibility/Relevanssi/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\Relevanssi;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Relevanssi;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Relevanssi();
15
+ }
16
+ }
compatibility/{class-wcml-relevanssi.php → Relevanssi/class-wcml-relevanssi.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_Relevanssi {
4
 
5
  public function add_hooks() {
6
  // Re-index translated product to add missing terms (wcml-2282)
1
  <?php
2
 
3
+ class WCML_Relevanssi implements \IWPML_Action {
4
 
5
  public function add_hooks() {
6
  // Re-index translated product to add missing terms (wcml-2282)
compatibility/Sensei/Factory.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\Sensei;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Sensei;
7
+ use WPML_Custom_Columns;
8
+ use function WCML\functions\getSitePress;
9
+
10
+ class Factory extends ComponentFactory {
11
+
12
+ /**
13
+ * @inheritDoc
14
+ */
15
+ public function create() {
16
+ return new WCML_Sensei( getSitePress(), self::getWpdb(), new WPML_Custom_Columns( getSitePress() ) );
17
+ }
18
+ }
compatibility/{class-wcml-sensei.php → Sensei/class-wcml-sensei.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_Sensei {
4
 
5
  /** @var SitePress */
6
  private $sitepress;
1
  <?php
2
 
3
+ class WCML_Sensei implements \IWPML_Action {
4
 
5
  /** @var SitePress */
6
  private $sitepress;
compatibility/StripePayments/Factory.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\StripePayments;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ use function WCML\functions\getWooCommerceWpml;
9
+
10
+ /**
11
+ * @see https://wordpress.org/plugins/woocommerce-gateway-stripe/
12
+ */
13
+ class Factory extends ComponentFactory implements IStandAloneAction {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ $hooks = [];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks( getWooCommerceWpml()->get_multi_currency()->orders );
23
+ }
24
+
25
+ return $hooks;
26
+ }
27
+ }
compatibility/StripePayments/MulticurrencyHooks.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\StripePayments;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ /**
8
+ * @var \WCML_Multi_Currency_Orders
9
+ */
10
+ private $orders;
11
+
12
+ const PRIORITY = 10;
13
+
14
+ public function __construct( \WCML_Multi_Currency_Orders $orders ) {
15
+ $this->orders = $orders;
16
+ }
17
+
18
+ public function add_hooks() {
19
+ add_action( 'woocommerce_admin_order_totals_after_total', [ $this, 'suspendCurrencySymbolFilter' ], self::PRIORITY - 1 );
20
+ }
21
+
22
+ public function suspendCurrencySymbolFilter() {
23
+ if ( remove_filter( 'woocommerce_currency_symbol', [ $this->orders, '_use_order_currency_symbol' ] ) ) {
24
+ add_action(
25
+ 'woocommerce_admin_order_totals_after_total',
26
+ function() {
27
+ add_filter( 'woocommerce_currency_symbol', [ $this->orders, '_use_order_currency_symbol' ] );
28
+ },
29
+ self::PRIORITY + 100
30
+ );
31
+ }
32
+ }
33
+ }
compatibility/TableRateShipping/Factory.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\TableRateShipping;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_Table_Rate_Shipping;
8
+ use function WCML\functions\getSitePress;
9
+ use function WCML\functions\getWooCommerceWpml;
10
+ use function WCML\functions\isStandAlone;
11
+
12
+ /**
13
+ * @see https://woocommerce.com/products/table-rate-shipping/
14
+ */
15
+ class Factory extends ComponentFactory implements IStandAloneAction {
16
+
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ public function create() {
21
+ $hooks = [];
22
+
23
+ $woocommerce_wpml = getWooCommerceWpml();
24
+
25
+ if ( wcml_is_multi_currency_on() ) {
26
+ $hooks[] = new MulticurrencyHooks( $woocommerce_wpml, $woocommerce_wpml->get_multi_currency() );
27
+ }
28
+
29
+ if ( ! isStandAlone() ) {
30
+ $hooks[] = new WCML_Table_Rate_Shipping( getSitePress(), $woocommerce_wpml, self::getWpdb() );
31
+ }
32
+
33
+ return $hooks;
34
+ }
35
+
36
+ }
compatibility/TableRateShipping/MulticurrencyHooks.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\TableRateShipping;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ /**
8
+ * @var \woocommerce_wpml
9
+ */
10
+ public $woocommerce_wpml;
11
+
12
+ /**
13
+ * @var \WCML_Multi_Currency
14
+ */
15
+ public $multicurrency;
16
+
17
+ /**
18
+ * @param \woocommerce_wpml $woocommerce_wpml
19
+ * @param \WCML_Multi_Currency $multicurrency
20
+ */
21
+ public function __construct( \woocommerce_wpml $woocommerce_wpml, \WCML_Multi_Currency $multicurrency ) {
22
+ $this->woocommerce_wpml = $woocommerce_wpml;
23
+ $this->multicurrency = $multicurrency;
24
+ }
25
+
26
+ public function add_hooks() {
27
+ if ( version_compare( constant( 'TABLE_RATE_SHIPPING_VERSION' ), '3.0.11', '<' ) ) {
28
+ add_filter( 'woocommerce_table_rate_query_rates_args', [ $this, 'filterQueryRatesArgs' ] );
29
+ }
30
+
31
+ add_filter( 'woocommerce_table_rate_package_row_base_price', [ $this, 'filterProductBasePrice' ], 10, 3 );
32
+ }
33
+
34
+ /**
35
+ * It's not possible to filter rate_min and rate_max so we use the original price to compare against these values
36
+ *
37
+ * @param array $args
38
+ *
39
+ * @return array
40
+ */
41
+ public function filterQueryRatesArgs( $args ) {
42
+ if ( isset( $args['price'] ) && wcml_get_woocommerce_currency_option() !== $this->multicurrency->get_client_currency() ) {
43
+ $args['price'] = $this->multicurrency->prices->unconvert_price_amount( $args['price'] );
44
+ }
45
+
46
+ return $args;
47
+ }
48
+
49
+ /**
50
+ * @param float $rowBasePrice
51
+ * @param \WC_Product $product
52
+ * @param int $quantity
53
+ *
54
+ * @return float
55
+ */
56
+ public function filterProductBasePrice( $rowBasePrice, $product, $quantity ) {
57
+ if ( $product && wcml_get_woocommerce_currency_option() !== $this->multicurrency->get_client_currency() ) {
58
+ $rowBasePrice = $this->woocommerce_wpml->products->get_product_price_from_db( $product->get_id() ) * $quantity;
59
+ }
60
+
61
+ return $rowBasePrice;
62
+ }
63
+
64
+ }
compatibility/{class-wcml-table-rate-shipping.php → TableRateShipping/class-wcml-table-rate-shipping.php} RENAMED
@@ -7,7 +7,7 @@ use WPML\FP\Obj;
7
  /**
8
  * Class WCML_Table_Rate_Shipping
9
  */
10
- class WCML_Table_Rate_Shipping {
11
 
12
  /**
13
  * @var SitePress
@@ -48,20 +48,6 @@ class WCML_Table_Rate_Shipping {
48
  add_filter( 'woocommerce_shipping_table_rate_is_available', [ $this, 'shipping_table_rate_is_available' ], 10, 3 );
49
  }
50
 
51
- if ( wcml_is_multi_currency_on() ) {
52
- $wpml_api = $this->sitepress->get_wp_api();
53
- if ( $wpml_api->version_compare( $wpml_api->constant( 'TABLE_RATE_SHIPPING_VERSION' ), '3.0.11', '<' ) ) {
54
- add_filter( 'woocommerce_table_rate_query_rates_args', [ $this, 'filter_query_rates_args' ] );
55
- }
56
-
57
- add_filter(
58
- 'woocommerce_table_rate_package_row_base_price',
59
- [ $this, 'filter_product_base_price' ],
60
- 10,
61
- 3
62
- );
63
- }
64
-
65
  if ( is_admin() ) {
66
  // phpcs:disable WordPress.Security.NonceVerification.Missing
67
  if ( Obj::prop( 'shipping_abort_reason', $_POST ) ) {
@@ -154,23 +140,9 @@ class WCML_Table_Rate_Shipping {
154
  return $terms;
155
  }
156
 
157
- /**
158
- * It's not possible to filter rate_min and rate_max so we use the original price to compare against these values
159
- *
160
- * @param array $args
161
- *
162
- * @return mixed
163
- */
164
- public function filter_query_rates_args( $args ) {
165
- if ( isset( $args['price'] ) && wcml_get_woocommerce_currency_option() !== $this->woocommerce_wpml->multi_currency->get_client_currency() ) {
166
- $args['price'] = $this->woocommerce_wpml->multi_currency->prices->unconvert_price_amount( $args['price'] );
167
- }
168
-
169
- return $args;
170
- }
171
-
172
  public function show_pointer_info() {
173
  $pointer_ui = new WCML_Pointer_UI(
 
174
  sprintf( __( 'You can translate this method title on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the method title string.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' ) . '">', '</a>' ),
175
  WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
176
  'woocommerce_table_rate_title'
@@ -179,6 +151,7 @@ class WCML_Table_Rate_Shipping {
179
  $pointer_ui->show();
180
 
181
  $pointer_ui = new WCML_Pointer_UI(
 
182
  sprintf( __( 'You can translate the labels of your table rates on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the labels strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' ) . '">', '</a>' ),
183
  WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
184
  'shipping_rates .shipping_label a'
@@ -187,22 +160,6 @@ class WCML_Table_Rate_Shipping {
187
  $pointer_ui->show();
188
  }
189
 
190
- /**
191
- * @param $row_base_price
192
- * @param WC_Product $_product
193
- * @param $qty
194
- *
195
- * @return mixed
196
- */
197
- public function filter_product_base_price( $row_base_price, $_product, $qty ) {
198
-
199
- if ( $_product && wcml_get_woocommerce_currency_option() !== $this->woocommerce_wpml->multi_currency->get_client_currency() ) {
200
- $row_base_price = $this->woocommerce_wpml->products->get_product_price_from_db( $_product->get_id() ) * $qty;
201
- }
202
-
203
- return $row_base_price;
204
- }
205
-
206
  /**
207
  * Register the new rate's shipping abort reasons.
208
  *
7
  /**
8
  * Class WCML_Table_Rate_Shipping
9
  */
10
+ class WCML_Table_Rate_Shipping implements \IWPML_Action {
11
 
12
  /**
13
  * @var SitePress
48
  add_filter( 'woocommerce_shipping_table_rate_is_available', [ $this, 'shipping_table_rate_is_available' ], 10, 3 );
49
  }
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  if ( is_admin() ) {
52
  // phpcs:disable WordPress.Security.NonceVerification.Missing
53
  if ( Obj::prop( 'shipping_abort_reason', $_POST ) ) {
140
  return $terms;
141
  }
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  public function show_pointer_info() {
144
  $pointer_ui = new WCML_Pointer_UI(
145
+ /* translators: %1$s and %2$s are opening and closing HTML link tag */
146
  sprintf( __( 'You can translate this method title on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the method title string.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' ) . '">', '</a>' ),
147
  WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
148
  'woocommerce_table_rate_title'
151
  $pointer_ui->show();
152
 
153
  $pointer_ui = new WCML_Pointer_UI(
154
+ /* translators: %1$s and %2$s are opening and closing HTML link tag */
155
  sprintf( __( 'You can translate the labels of your table rates on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the labels strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php' ) . '">', '</a>' ),
156
  WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
157
  'shipping_rates .shipping_label a'
160
  $pointer_ui->show();
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /**
164
  * Register the new rate's shipping abort reasons.
165
  *
compatibility/TheEventsCalendar/Factory.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\TheEventsCalendar;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ use function WCML\functions\getSitePress;
9
+ use function WCML\functions\getWooCommerceWpml;
10
+ use function WCML\functions\isStandAlone;
11
+
12
+ /**
13
+ * @see https://wordpress.org/plugins/the-events-calendar/
14
+ */
15
+ class Factory extends ComponentFactory implements IStandAloneAction {
16
+
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ public function create() {
21
+ $hooks = [];
22
+
23
+ if ( wcml_is_multi_currency_on() ) {
24
+ $hooks[] = new MulticurrencyHooks();
25
+ }
26
+
27
+ if ( ! isStandAlone() ) {
28
+ $hooks[] = new \WCML_The_Events_Calendar( getSitePress(), getWooCommerceWpml() );
29
+ }
30
+
31
+ return $hooks;
32
+ }
33
+
34
+ }
compatibility/TheEventsCalendar/MulticurrencyHooks.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\TheEventsCalendar;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ if ( ! is_admin() ) {
9
+ add_filter( 'tribe_events_cost_unformatted', [ $this, 'convert_events_cost' ], 10, 1 );
10
+ }
11
+ }
12
+
13
+ /**
14
+ * @param float $cost
15
+ *
16
+ * @return float
17
+ */
18
+ public function convert_events_cost( $cost ) {
19
+ return apply_filters( 'wcml_raw_price_amount', $cost );
20
+ }
21
+
22
+ }
compatibility/{class-wcml-the-events-calendar.php → TheEventsCalendar/class-wcml-the-events-calendar.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_The_Events_Calendar {
4
 
5
  /** @var SitePress */
6
  private $sitepress;
@@ -23,11 +23,13 @@ class WCML_The_Events_Calendar {
23
  // @todo Cover by tests, required for wcml-3037.
24
  $this->sitepress = $sitepress;
25
  $this->woocommerce_wpml = $woocommerce_wpml;
 
26
 
 
 
27
  if ( isset( $_POST['action'] ) && 0 === strpos( $_POST['action'], 'tribe-ticket-add-' ) ) {
28
  add_action( 'tribe_tickets_ticket_add', [ $this, 'unset_post_post_id' ] );
29
  add_action( 'event_tickets_after_save_ticket', [ $this, 'restore_post_post_id' ] );
30
-
31
  }
32
 
33
  if ( is_admin() ) {
@@ -50,7 +52,6 @@ class WCML_The_Events_Calendar {
50
  } else {
51
  add_action( 'event_tickets_rsvp_tickets_generated', [ $this, 'sync_rsvp_fields_on_attendee_created' ], 10, 3 );
52
  add_filter( 'tribe_get_organizer_ids', [ $this, 'get_translated_organizer_ids' ], 10, 2 );
53
- add_filter( 'tribe_events_cost_unformatted', [ $this, 'convert_events_cost' ], 10, 1 );
54
  }
55
 
56
  }
@@ -482,9 +483,4 @@ class WCML_The_Events_Calendar {
482
  return $organizer_ids;
483
  }
484
 
485
- public function convert_events_cost( $cost ) {
486
- return apply_filters( 'wcml_raw_price_amount', $cost );
487
- }
488
-
489
  }
490
-
1
  <?php
2
 
3
+ class WCML_The_Events_Calendar implements \IWPML_Action {
4
 
5
  /** @var SitePress */
6
  private $sitepress;
23
  // @todo Cover by tests, required for wcml-3037.
24
  $this->sitepress = $sitepress;
25
  $this->woocommerce_wpml = $woocommerce_wpml;
26
+ }
27
 
28
+ public function add_hooks() {
29
+ /* phpcs:ignore WordPress.VIP.SuperGlobalInputUsage.AccessDetected */
30
  if ( isset( $_POST['action'] ) && 0 === strpos( $_POST['action'], 'tribe-ticket-add-' ) ) {
31
  add_action( 'tribe_tickets_ticket_add', [ $this, 'unset_post_post_id' ] );
32
  add_action( 'event_tickets_after_save_ticket', [ $this, 'restore_post_post_id' ] );
 
33
  }
34
 
35
  if ( is_admin() ) {
52
  } else {
53
  add_action( 'event_tickets_rsvp_tickets_generated', [ $this, 'sync_rsvp_fields_on_attendee_created' ], 10, 3 );
54
  add_filter( 'tribe_get_organizer_ids', [ $this, 'get_translated_organizer_ids' ], 10, 2 );
 
55
  }
56
 
57
  }
483
  return $organizer_ids;
484
  }
485
 
 
 
 
 
486
  }
 
compatibility/TmExtraProductOptions/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\TmExtraProductOptions;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Extra_Product_Options;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Extra_Product_Options();
15
+ }
16
+ }
compatibility/{class-wcml-extra-product-options.php → TmExtraProductOptions/class-wcml-extra-product-options.php} RENAMED
@@ -1,9 +1,8 @@
1
  <?php
2
 
3
- class WCML_Extra_Product_Options {
4
-
5
- public function __construct() {
6
 
 
7
  add_action( 'tm_before_extra_product_options', [ $this, 'inf_translate_product_page_strings' ] );
8
  add_action( 'tm_before_price_rules', [ $this, 'inf_translate_strings' ] );
9
  }
@@ -20,6 +19,7 @@ class WCML_Extra_Product_Options {
20
 
21
  public function inf_message( $text ) {
22
  $message = '<div><p class="icl_cyan_box">';
 
23
  $message .= sprintf( __( 'To translate Extra Options strings please save %1$s and go to the <b><a href="%2$s">String Translation interface</a></b>', 'woocommerce-multilingual' ), esc_html( $text ), admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=wc_extra_product_options' ) );
24
  $message .= '</p></div>';
25
 
1
  <?php
2
 
3
+ class WCML_Extra_Product_Options implements \IWPML_Action {
 
 
4
 
5
+ public function add_hooks() {
6
  add_action( 'tm_before_extra_product_options', [ $this, 'inf_translate_product_page_strings' ] );
7
  add_action( 'tm_before_price_rules', [ $this, 'inf_translate_strings' ] );
8
  }
19
 
20
  public function inf_message( $text ) {
21
  $message = '<div><p class="icl_cyan_box">';
22
+ /* translators: %1$s is a dynamic text and %2$s is a URL */
23
  $message .= sprintf( __( 'To translate Extra Options strings please save %1$s and go to the <b><a href="%2$s">String Translation interface</a></b>', 'woocommerce-multilingual' ), esc_html( $text ), admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=wc_extra_product_options' ) );
24
  $message .= '</p></div>';
25
 
compatibility/WcAjaxLayeredNav/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcAjaxLayeredNav;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Ajax_Layered_Nav_Widget;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Ajax_Layered_Nav_Widget();
15
+ }
16
+ }
compatibility/{class-wcml-ajax-layered-nav-widget.php → WcAjaxLayeredNav/class-wcml-ajax-layered-nav-widget.php} RENAMED
@@ -4,8 +4,9 @@
4
  Class for WooCommerce Advanced Ajax Layered Navigation
5
  */
6
 
7
- class WCML_Ajax_Layered_Nav_Widget {
8
- public function __construct() {
 
9
  add_filter( 'wc_ajax_layered_nav_sizeselector_term_id', [ $this, 'wc_ajax_layered_nav_sizeselector_term_id' ] );
10
  add_filter( 'wc_ajax_layered_nav_query_editor', [ $this, 'wc_ajax_layered_nav_query_editor' ], 10, 3 );
11
  }
4
  Class for WooCommerce Advanced Ajax Layered Navigation
5
  */
6
 
7
+ class WCML_Ajax_Layered_Nav_Widget implements \IWPML_Action {
8
+
9
+ public function add_hooks() {
10
  add_filter( 'wc_ajax_layered_nav_sizeselector_term_id', [ $this, 'wc_ajax_layered_nav_sizeselector_term_id' ] );
11
  add_filter( 'wc_ajax_layered_nav_query_editor', [ $this, 'wc_ajax_layered_nav_query_editor' ], 10, 3 );
12
  }
compatibility/WcBookings/Factory.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcBookings;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+ use function WCML\functions\isStandAlone;
10
+
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [
18
+ new SharedHooks( self::getWpdb() ),
19
+ ];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks( getWooCommerceWpml() );
23
+ }
24
+
25
+ if ( ! isStandAlone() ) {
26
+ $hooks[] = new \WCML_Bookings(
27
+ getSitePress(),
28
+ getWooCommerceWpml(),
29
+ self::getWooCommerce(),
30
+ self::getWpdb(),
31
+ self::getElementTranslationPackage(),
32
+ self::getPostTranslations()
33
+ );
34
+ }
35
+
36
+ if ( defined( 'WC_ACCOMMODATION_BOOKINGS_VERSION' ) && wcml_is_multi_currency_on() ) {
37
+ $hooks[] = new \WCML_Accommodation_Bookings( getWooCommerceWpml() );
38
+ }
39
+
40
+ return $hooks;
41
+ }
42
+ }
compatibility/WcBookings/MulticurrencyHooks.php ADDED
@@ -0,0 +1,936 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcBookings;
4
+
5
+ /**
6
+ * @todo: Most of the code in this class was just moved from
7
+ * the original \WCML_Bookings class with the minimal
8
+ * adjustments. There's a lot of weak/obsolete formatting
9
+ * and code duplication that we should fix in the future.
10
+ */
11
+ class MulticurrencyHooks implements \IWPML_Action {
12
+
13
+
14
+ /** @var \woocommerce_wpml $woocommerce_wpml */
15
+ private $woocommerce_wpml;
16
+
17
+ public function __construct( \woocommerce_wpml $woocommerce_wpml ) {
18
+ $this->woocommerce_wpml = $woocommerce_wpml;
19
+ }
20
+
21
+ public function add_hooks() {
22
+ add_action( 'woocommerce_bookings_after_booking_base_cost', [ $this, 'wcml_price_field_after_booking_base_cost' ] );
23
+ add_action( 'woocommerce_bookings_after_booking_block_cost', [ $this, 'wcml_price_field_after_booking_block_cost' ] );
24
+ add_action( 'woocommerce_bookings_after_display_cost', [ $this, 'wcml_price_field_after_display_cost' ] );
25
+ add_action( 'woocommerce_bookings_after_booking_pricing_base_cost', [ $this, 'wcml_price_field_after_booking_pricing_base_cost' ], 10, 2 );
26
+ add_action( 'woocommerce_bookings_after_booking_pricing_cost', [ $this, 'wcml_price_field_after_booking_pricing_cost' ], 10, 2 );
27
+ add_action( 'woocommerce_bookings_after_person_cost', [ $this, 'wcml_price_field_after_person_cost' ] );
28
+ add_action( 'woocommerce_bookings_after_person_block_cost', [ $this, 'wcml_price_field_after_person_block_cost' ] );
29
+ add_action( 'woocommerce_bookings_after_resource_cost', [ $this, 'wcml_price_field_after_resource_cost' ], 10, 2 );
30
+ add_action( 'woocommerce_bookings_after_resource_block_cost', [ $this, 'wcml_price_field_after_resource_block_cost' ], 10, 2 );
31
+
32
+ add_action( 'woocommerce_bookings_after_bookings_pricing', [ $this, 'after_bookings_pricing' ] );
33
+
34
+ add_action( 'save_post', [ $this, 'save_custom_costs' ], \WCML_Bookings::PRIORITY_SAVE_POST_ACTION - 1 );
35
+
36
+ add_filter( 'woocommerce_bookings_process_cost_rules_cost', [ $this, 'wc_bookings_process_cost_rules_cost' ], 10, 3 );
37
+ add_filter( 'woocommerce_bookings_process_cost_rules_base_cost', [ $this, 'wc_bookings_process_cost_rules_base_cost' ], 10, 3 );
38
+ add_filter( 'woocommerce_bookings_process_cost_rules_override_block', [ $this, 'wc_bookings_process_cost_rules_override_block_cost' ], 10, 3 );
39
+
40
+ add_action( 'woocommerce_bookings_after_create_booking_page', [ $this, 'booking_currency_dropdown' ] );
41
+ add_action( 'init', [ $this, 'set_booking_currency' ] );
42
+ add_action( 'wp_ajax_wcml_booking_set_currency', [ $this, 'set_booking_currency_ajax' ] );
43
+
44
+ add_action( 'woocommerce_bookings_create_booking_page_add_order_item', [ $this, 'set_order_currency_on_create_booking_page' ] );
45
+ add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
46
+
47
+ add_filter( 'wcml_filter_currency_position', [ $this, 'create_booking_page_client_currency' ] );
48
+ add_filter( 'wcml_client_currency', [ $this, 'create_booking_page_client_currency' ] );
49
+
50
+ if ( ! is_admin() || isset( $_POST['action'] ) && 'wc_bookings_calculate_costs' === $_POST['action'] ) {
51
+ add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * @param int $postId
57
+ *
58
+ * @return void
59
+ */
60
+ public function wcml_price_field_after_booking_base_cost( $postId ) {
61
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_cost' );
62
+ }
63
+
64
+ /**
65
+ * @param int $postId
66
+ *
67
+ * @return void
68
+ */
69
+ public function wcml_price_field_after_booking_block_cost( $postId ) {
70
+ if ( self::isWcBookingsBefore_1_10_9() ) {
71
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_base_cost' );
72
+ } else {
73
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_block_cost' );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * @param int $postId
79
+ *
80
+ * @return void
81
+ */
82
+ public function wcml_price_field_after_display_cost( $postId ) {
83
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_display_cost' );
84
+ }
85
+
86
+ /**
87
+ * @param array $pricing
88
+ * @param int $postId
89
+ *
90
+ * @return void
91
+ */
92
+ public function wcml_price_field_after_booking_pricing_base_cost( $pricing, $postId ) {
93
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_pricing_base_cost', $pricing );
94
+ }
95
+
96
+ /**
97
+ * @param array $pricing
98
+ * @param int $postId
99
+ *
100
+ * @return void
101
+ */
102
+ public function wcml_price_field_after_booking_pricing_cost( $pricing, $postId ) {
103
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_pricing_cost', $pricing );
104
+ }
105
+
106
+ /**
107
+ * @param int $personTypeId
108
+ *
109
+ * @return void
110
+ */
111
+ public function wcml_price_field_after_person_cost( $personTypeId ) {
112
+ $this->echo_wcml_price_field( $personTypeId, 'wcml_wc_booking_person_cost', false, false );
113
+ }
114
+
115
+ /**
116
+ * @param int $personTypeId
117
+ *
118
+ * @return void
119
+ */
120
+ public function wcml_price_field_after_person_block_cost( $personTypeId ) {
121
+ $this->echo_wcml_price_field( $personTypeId, 'wcml_wc_booking_person_block_cost', false, false );
122
+ }
123
+
124
+ /**
125
+ * @param int $resourceId
126
+ * @param int $postId
127
+ *
128
+ * @return void
129
+ */
130
+ public function wcml_price_field_after_resource_cost( $resourceId, $postId ) {
131
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_resource_cost', false, true, $resourceId );
132
+ }
133
+
134
+ /**
135
+ * @param int $resourceId
136
+ * @param int $postId
137
+ *
138
+ * @return void
139
+ */
140
+ public function wcml_price_field_after_resource_block_cost( $resourceId, $postId ) {
141
+ $this->echo_wcml_price_field( $postId, 'wcml_wc_booking_resource_block_cost', false, true, $resourceId );
142
+ }
143
+
144
+ /**
145
+ * @param int $postId
146
+ * @param string $field
147
+ * @param array|false $pricing
148
+ * @param bool $check
149
+ * @param int|false $resourceId
150
+ *
151
+ * @return void
152
+ */
153
+ public function echo_wcml_price_field( $postId, $field, $pricing = false, $check = true, $resourceId = false ) {
154
+ if ( ( ! $check || $this->woocommerce_wpml->products->is_original_product( $postId ) ) ) {
155
+
156
+ $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
157
+
158
+ $wc_currencies = get_woocommerce_currencies();
159
+
160
+ if ( ! function_exists( 'woocommerce_wp_text_input' ) ) {
161
+ include_once dirname( WC_PLUGIN_FILE ) . '/includes/admin/wc-meta-box-functions.php';
162
+ }
163
+
164
+ echo '<div class="wcml_custom_cost_field" >';
165
+
166
+ foreach ( $currencies as $currency_code => $currency ) {
167
+
168
+ switch ( $field ) {
169
+ case 'wcml_wc_booking_cost':
170
+ woocommerce_wp_text_input(
171
+ [
172
+ 'id' => 'wcml_wc_booking_cost',
173
+ 'class' => 'wcml_bookings_custom_price',
174
+ 'name' => 'wcml_wc_booking_cost[' . $currency_code . ']',
175
+ 'label' => get_woocommerce_currency_symbol( $currency_code ),
176
+ 'description' => __( 'One-off cost for the booking as a whole.', 'woocommerce-bookings' ),
177
+ 'value' => get_post_meta( $postId, '_wc_booking_cost_' . $currency_code, true ),
178
+ 'type' => 'number',
179
+ 'desc_tip' => true,
180
+ 'custom_attributes' => [
181
+ 'min' => '',
182
+ 'step' => '0.01',
183
+ ],
184
+ ]
185
+ );
186
+ break;
187
+ case 'wcml_wc_booking_block_cost':
188
+ case 'wcml_wc_booking_base_cost':
189
+ $block_cost_key = '_wc_booking_base_cost_';
190
+ if ( $field === 'wcml_wc_booking_block_cost' ) {
191
+ $block_cost_key = '_wc_booking_block_cost_';
192
+ }
193
+ $block_cost_key .= $currency_code;
194
+ woocommerce_wp_text_input(
195
+ [
196
+ 'id' => $field,
197
+ 'class' => 'wcml_bookings_custom_price',
198
+ 'name' => $field . '[' . $currency_code . ']',
199
+ 'label' => get_woocommerce_currency_symbol( $currency_code ),
200
+ 'description' => __( 'This is the cost per block booked. All other costs (for resources and persons) are added to this.', 'woocommerce-bookings' ),
201
+ 'value' => get_post_meta( $postId, $block_cost_key, true ),
202
+ 'type' => 'number',
203
+ 'desc_tip' => true,
204
+ 'custom_attributes' => [
205
+ 'min' => '',
206
+ 'step' => '0.01',
207
+ ],
208
+ ]
209
+ );
210
+ break;
211
+ case 'wcml_wc_display_cost':
212
+ woocommerce_wp_text_input(
213
+ [
214
+ 'id' => 'wcml_wc_display_cost',
215
+ 'class' => 'wcml_bookings_custom_price',
216
+ 'name' => 'wcml_wc_display_cost[' . $currency_code . ']',
217
+ 'label' => get_woocommerce_currency_symbol( $currency_code ),
218
+ 'description' => __( 'The cost is displayed to the user on the frontend. Leave blank to have it calculated for you. If a booking has varying costs, this will be prefixed with the word "from:".', 'woocommerce-bookings' ),
219
+ 'value' => get_post_meta( $postId, '_wc_display_cost_' . $currency_code, true ),
220
+ 'type' => 'number',
221
+ 'desc_tip' => true,
222
+ 'custom_attributes' => [
223
+ 'min' => '',
224
+ 'step' => '0.01',
225
+ ],
226
+ ]
227
+ );
228
+ break;
229
+
230
+ case 'wcml_wc_booking_pricing_base_cost':
231
+ if ( isset( $pricing[ 'base_cost_' . $currency_code ] ) ) {
232
+ $value = $pricing[ 'base_cost_' . $currency_code ];
233
+ } else {
234
+ $value = '';
235
+ }
236
+
237
+ echo '<div class="wcml_bookings_range_block" >';
238
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
239
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_base_cost[' . esc_html( $currency_code ) . '][]" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
240
+ echo '</div>';
241
+ break;
242
+
243
+ case 'wcml_wc_booking_pricing_cost':
244
+ if ( isset( $pricing[ 'cost_' . $currency_code ] ) ) {
245
+ $value = $pricing[ 'cost_' . $currency_code ];
246
+ } else {
247
+ $value = '';
248
+ }
249
+
250
+ echo '<div class="wcml_bookings_range_block" >';
251
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
252
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_cost[' . esc_html( $currency_code ) . '][]" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
253
+ echo '</div>';
254
+ break;
255
+
256
+ case 'wcml_wc_booking_person_cost':
257
+ $value = get_post_meta( $postId, 'cost_' . $currency_code, true );
258
+
259
+ echo '<div class="wcml_bookings_person_block" >';
260
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
261
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_person_cost[' . intval( $postId ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
262
+ echo '</div>';
263
+ break;
264
+
265
+ case 'wcml_wc_booking_person_block_cost':
266
+ $value = get_post_meta( $postId, 'block_cost_' . $currency_code, true );
267
+
268
+ echo '<div class="wcml_bookings_person_block" >';
269
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
270
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_person_block_cost[' . intval( $postId ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
271
+ echo '</div>';
272
+ break;
273
+
274
+ case 'wcml_wc_booking_resource_cost':
275
+ $resource_base_costs = maybe_unserialize( get_post_meta( $postId, '_resource_base_costs', true ) );
276
+
277
+ if ( isset( $resource_base_costs['custom_costs'][ $currency_code ][ $resourceId ] ) ) {
278
+ $value = $resource_base_costs['custom_costs'][ $currency_code ][ $resourceId ];
279
+ } else {
280
+ $value = '';
281
+ }
282
+
283
+ echo '<div class="wcml_bookings_resource_block" >';
284
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
285
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_cost[' . esc_html( $resourceId ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
286
+ echo '</div>';
287
+ break;
288
+
289
+ case 'wcml_wc_booking_resource_block_cost':
290
+ $resource_block_costs = maybe_unserialize( get_post_meta( $postId, '_resource_block_costs', true ) );
291
+
292
+ if ( isset( $resource_block_costs['custom_costs'][ $currency_code ][ $resourceId ] ) ) {
293
+ $value = $resource_block_costs['custom_costs'][ $currency_code ][ $resourceId ];
294
+ } else {
295
+ $value = '';
296
+ }
297
+
298
+ echo '<div class="wcml_bookings_resource_block" >';
299
+ echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
300
+ echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_block_cost[' . esc_html( $resourceId ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
301
+ echo '</div>';
302
+ break;
303
+
304
+ default:
305
+ break;
306
+
307
+ }
308
+ }
309
+
310
+ echo '</div>';
311
+ }
312
+ }
313
+
314
+ /**
315
+ * @param int $postId
316
+ *
317
+ * @return void
318
+ */
319
+ public function after_bookings_pricing( $postId ) {
320
+
321
+ if ( in_array( 'booking', wp_get_post_terms( $postId, 'product_type', [ 'fields' => 'names' ] ) ) && $this->woocommerce_wpml->products->is_original_product( $postId ) ) {
322
+
323
+ $customCostsStatus = get_post_meta( $postId, '_wcml_custom_costs_status', true );
324
+
325
+ $checked = ! $customCostsStatus ? 'checked="checked"' : ' ';
326
+
327
+ echo '<div class="wcml_custom_costs">';
328
+
329
+ echo '<input type="radio" name="_wcml_custom_costs" id="wcml_custom_costs_auto" value="0" class="wcml_custom_costs_input" ' . esc_html( $checked ) . ' />';
330
+ echo '<label for="wcml_custom_costs_auto">' . esc_html__( 'Calculate costs in other currencies automatically', 'woocommerce-multilingual' ) . '</label>';
331
+
332
+ $checked = 1 === (int) $customCostsStatus ? 'checked="checked"' : ' ';
333
+
334
+ echo '<input type="radio" name="_wcml_custom_costs" value="1" id="wcml_custom_costs_manually" class="wcml_custom_costs_input" ' . esc_html( $checked ) . ' />';
335
+ echo '<label for="wcml_custom_costs_manually">' . esc_html__( 'Set costs in other currencies manually', 'woocommerce-multilingual' ) . '</label>';
336
+
337
+ wp_nonce_field( 'wcml_save_custom_costs', '_wcml_custom_costs_nonce' );
338
+
339
+ echo '</div>';
340
+ }
341
+ }
342
+
343
+ /**
344
+ * @param int $postId
345
+ *
346
+ * @return false|void
347
+ */
348
+ public function save_custom_costs( $postId ) {
349
+ $nonce = filter_var( isset( $_POST['_wcml_custom_costs_nonce'] ) ? $_POST['_wcml_custom_costs_nonce'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
350
+
351
+ if ( isset( $_POST['_wcml_custom_costs'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_costs' ) ) {
352
+
353
+ update_post_meta( $postId, '_wcml_custom_costs_status', $_POST['_wcml_custom_costs'] );
354
+
355
+ if ( 1 === (int) $_POST['_wcml_custom_costs'] ) {
356
+
357
+ $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
358
+ if ( empty( $currencies ) || 0 === $postId ) {
359
+ return false;
360
+ }
361
+
362
+ $this->update_booking_costs( $currencies, $postId );
363
+ $this->update_booking_pricing( $currencies, $postId );
364
+
365
+ if ( isset( $_POST['wcml_wc_booking_person_cost'] ) && is_array( $_POST['wcml_wc_booking_person_cost'] ) ) {
366
+ $this->update_booking_person_cost( $currencies, $_POST['wcml_wc_booking_person_cost'] );
367
+ }
368
+
369
+ if ( isset( $_POST['wcml_wc_booking_person_block_cost'] ) && is_array( $_POST['wcml_wc_booking_person_block_cost'] ) ) {
370
+ $this->update_booking_person_block_cost( $currencies, $_POST['wcml_wc_booking_person_block_cost'] );
371
+ }
372
+
373
+ if ( isset( $_POST['wcml_wc_booking_resource_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_cost'] ) ) {
374
+ $this->update_booking_resource_cost( $currencies, $postId, $_POST['wcml_wc_booking_resource_cost'] );
375
+ }
376
+
377
+ if ( isset( $_POST['wcml_wc_booking_resource_block_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_block_cost'] ) ) {
378
+ $this->update_booking_resource_block_cost( $currencies, $postId, $_POST['wcml_wc_booking_resource_block_cost'] );
379
+ }
380
+
381
+ update_post_meta( $postId, '_price', '' );
382
+ } else {
383
+ return false;
384
+ }
385
+ }
386
+ }
387
+
388
+ /**
389
+ * @param array $currencies
390
+ * @param int $postId
391
+ *
392
+ * @return bool
393
+ */
394
+ private function update_booking_costs( $currencies = [], $postId = 0 ) {
395
+ $bookingOptions = [
396
+ 'wcml_wc_booking_cost' => '_wc_booking_cost_',
397
+ 'wcml_wc_booking_block_cost' => '_wc_booking_block_cost_',
398
+ 'wcml_wc_display_cost' => '_wc_display_cost_',
399
+ ];
400
+
401
+ if ( self::isWcBookingsBefore_1_10_9() ) {
402
+ unset( $bookingOptions['wcml_wc_booking_block_cost'] );
403
+ $bookingOptions['wcml_wc_booking_base_cost'] = '_wc_booking_base_cost_';
404
+ }
405
+
406
+ foreach ( $currencies as $code => $currency ) {
407
+ foreach ( $bookingOptions as $bookingOptionsPostKey => $bookingOptionsMetaKeyPrefix ) {
408
+ if ( isset( $_POST[ $bookingOptionsPostKey ][ $code ] ) ) {
409
+ update_post_meta( $postId, $bookingOptionsMetaKeyPrefix . $code, sanitize_text_field( $_POST[ $bookingOptionsPostKey ][ $code ] ) );
410
+ }
411
+ }
412
+ }
413
+
414
+ return true;
415
+ }
416
+
417
+ /**
418
+ * @param array $currencies
419
+ * @param int $postId
420
+ *
421
+ * @return bool
422
+ */
423
+ private function update_booking_pricing( $currencies = [], $postId = 0 ) {
424
+ $updatedMeta = [];
425
+ $bookingPricing = get_post_meta( $postId, '_wc_booking_pricing', true );
426
+ if ( empty( $bookingPricing ) ) {
427
+ return false;
428
+ }
429
+
430
+ foreach ( $bookingPricing as $key => $prices ) {
431
+ $updatedMeta[ $key ] = $prices;
432
+ foreach ( $currencies as $code => $currency ) {
433
+ if ( isset( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] ) ) {
434
+ $updatedMeta[ $key ][ 'base_cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] );
435
+ }
436
+ if ( isset( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] ) ) {
437
+ $updatedMeta[ $key ][ 'cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] );
438
+ }
439
+ }
440
+ }
441
+
442
+ update_post_meta( $postId, '_wc_booking_pricing', $updatedMeta );
443
+
444
+ return true;
445
+ }
446
+
447
+ /**
448
+ * @param array $currencies
449
+ * @param array $personCosts
450
+ *
451
+ * @return bool
452
+ */
453
+ private function update_booking_person_cost( $currencies = [], $personCosts = [] ) {
454
+ if ( empty( $personCosts ) ) {
455
+ return false;
456
+ }
457
+
458
+ foreach ( $personCosts as $personId => $costs ) {
459
+ foreach ( $currencies as $code => $currency ) {
460
+ if ( isset( $costs[ $code ] ) ) {
461
+ update_post_meta( $personId, 'cost_' . $code, sanitize_text_field( $costs[ $code ] ) );
462
+ }
463
+ }
464
+ }
465
+
466
+ return true;
467
+ }
468
+
469
+ /**
470
+ * @param array $currencies
471
+ * @param array $blockCosts
472
+ *
473
+ * @return bool
474
+ */
475
+ private function update_booking_person_block_cost( $currencies = [], $blockCosts = [] ) {
476
+ if ( empty( $blockCosts ) ) {
477
+ return false;
478
+ }
479
+
480
+ foreach ( $blockCosts as $personId => $costs ) {
481
+ foreach ( $currencies as $code => $currency ) {
482
+ if ( isset( $costs[ $code ] ) ) {
483
+ update_post_meta( $personId, 'block_cost_' . $code, sanitize_text_field( $costs[ $code ] ) );
484
+ }
485
+ }
486
+ }
487
+
488
+ return true;
489
+ }
490
+
491
+ /**
492
+ * @param array $currencies
493
+ * @param int $postId
494
+ * @param array $resourceCost
495
+ *
496
+ * @return bool
497
+ */
498
+ private function update_booking_resource_cost( $currencies = [], $postId = 0, $resourceCost = [] ) {
499
+ if ( empty( $resourceCost ) ) {
500
+ return false;
501
+ }
502
+
503
+ $updatedMeta = get_post_meta( $postId, '_resource_base_costs', true );
504
+ if ( ! is_array( $updatedMeta ) ) {
505
+ $updatedMeta = [];
506
+ }
507
+
508
+ $wcBookingResourceCosts = [];
509
+
510
+ foreach ( $resourceCost as $resourceId => $costs ) {
511
+
512
+ foreach ( $currencies as $code => $currency ) {
513
+
514
+ if ( isset( $costs[ $code ] ) ) {
515
+ $wcBookingResourceCosts[ $code ][ $resourceId ] = sanitize_text_field( $costs[ $code ] );
516
+ }
517
+ }
518
+ }
519
+
520
+ $updatedMeta['custom_costs'] = $wcBookingResourceCosts;
521
+
522
+ update_post_meta( $postId, '_resource_base_costs', $updatedMeta );
523
+
524
+ self::triggerActionResourceCostsUpdated( $postId, '_resource_base_costs' );
525
+
526
+ return true;
527
+ }
528
+
529
+ /**
530
+ * @param array $currencies
531
+ * @param int $postId
532
+ * @param array $resourceBlockCost
533
+ *
534
+ * @return bool
535
+ */
536
+ private function update_booking_resource_block_cost( $currencies = [], $postId = 0, $resourceBlockCost = [] ) {
537
+ if ( empty( $resourceBlockCost ) ) {
538
+ return false;
539
+ }
540
+
541
+ $updatedMeta = get_post_meta( $postId, '_resource_block_costs', true );
542
+ if ( ! is_array( $updatedMeta ) ) {
543
+ $updatedMeta = [];
544
+ }
545
+
546
+ $wc_booking_resource_block_costs = [];
547
+
548
+ foreach ( $resourceBlockCost as $resource_id => $costs ) {
549
+
550
+ foreach ( $currencies as $code => $currency ) {
551
+
552
+ if ( isset( $costs[ $code ] ) ) {
553
+ $wc_booking_resource_block_costs[ $code ][ $resource_id ] = sanitize_text_field( $costs[ $code ] );
554
+ }
555
+ }
556
+ }
557
+
558
+ $updatedMeta['custom_costs'] = $wc_booking_resource_block_costs;
559
+
560
+ update_post_meta( $postId, '_resource_block_costs', $updatedMeta );
561
+
562
+ self::triggerActionResourceCostsUpdated( $postId, '_resource_block_costs' );
563
+
564
+ return true;
565
+ }
566
+
567
+ /**
568
+ * This is an internal action hook required after splitting
569
+ * the original WC Bookings compatibility code.
570
+ *
571
+ * @see \WCML_Bookings::sync_resource_costs_with_translations
572
+ *
573
+ * @param int|string $postId
574
+ * @param string $key
575
+ *
576
+ * @return void
577
+ */
578
+ private static function triggerActionResourceCostsUpdated( $postId, $key ) {
579
+ do_action( 'wcml_bookings_resource_costs_updated', $postId, $key );
580
+ }
581
+
582
+ /**
583
+ * @param float|int $cost
584
+ * @param array $fields
585
+ * @param string $key
586
+ *
587
+ * @return float|int
588
+ */
589
+ public function wc_bookings_process_cost_rules_cost( $cost, $fields, $key ) {
590
+ return $this->filter_pricing_cost( $cost, $fields, 'cost_', $key );
591
+ }
592
+
593
+ /**
594
+ * @param float|int $base_cost
595
+ * @param array $fields
596
+ * @param string $key
597
+ *
598
+ * @return float|int
599
+ */
600
+ public function wc_bookings_process_cost_rules_base_cost( $base_cost, $fields, $key ) {
601
+ return $this->filter_pricing_cost( $base_cost, $fields, 'base_cost_', $key );
602
+ }
603
+
604
+ /**
605
+ * @param float|int $override_cost
606
+ * @param array $fields
607
+ * @param string $key
608
+ *
609
+ * @return float|int
610
+ */
611
+ public function wc_bookings_process_cost_rules_override_block_cost( $override_cost, $fields, $key ) {
612
+ return $this->filter_pricing_cost( $override_cost, $fields, 'override_block_', $key );
613
+ }
614
+
615
+ /**
616
+ * @param float|int $cost
617
+ * @param array $fields
618
+ * @param string $name
619
+ * @param string $key
620
+ *
621
+ * @return float|int|mixed|string
622
+ */
623
+ public function filter_pricing_cost( $cost, $fields, $name, $key ) {
624
+ $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
625
+
626
+ if ( $currency === wcml_get_woocommerce_currency_option() ) {
627
+ return $cost;
628
+ }
629
+
630
+ if ( isset( $_POST['form'] ) ) {
631
+ parse_str( $_POST['form'], $posted );
632
+
633
+ $booking_id = $posted['add-to-cart'];
634
+
635
+ } elseif ( isset( $_POST['add-to-cart'] ) ) {
636
+
637
+ $booking_id = $_POST['add-to-cart'];
638
+
639
+ }
640
+
641
+ if ( isset( $booking_id ) ) {
642
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $booking_id );
643
+
644
+ if ( $booking_id != $original_id ) {
645
+ $fields = maybe_unserialize( get_post_meta( $original_id, '_wc_booking_pricing', true ) );
646
+ $fields = $fields[ $key ];
647
+ }
648
+ }
649
+
650
+ $needs_filter_pricing_cost = $this->needs_filter_pricing_cost( $name, $fields );
651
+
652
+ if ( $needs_filter_pricing_cost ) {
653
+ if ( isset( $fields[ $name . $currency ] ) ) {
654
+ return $fields[ $name . $currency ];
655
+ } else {
656
+ return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
657
+ }
658
+ }
659
+
660
+ return $cost;
661
+ }
662
+
663
+ /**
664
+ * @param string $name
665
+ * @param array $fields
666
+ *
667
+ * @return bool
668
+ */
669
+ public function needs_filter_pricing_cost( $name, $fields ) {
670
+
671
+ $modifier_skip_values = [ 'divide', 'times' ];
672
+
673
+ if (
674
+ 'override_block_' === $name ||
675
+ ( 'cost_' === $name && ! in_array( $fields['modifier'], $modifier_skip_values ) ) ||
676
+ ( 'base_cost_' === $name && ! in_array( $fields['base_modifier'], $modifier_skip_values ) )
677
+ ) {
678
+ return true;
679
+ } else {
680
+ return false;
681
+ }
682
+ }
683
+
684
+ public function booking_currency_dropdown() {
685
+ $current_booking_currency = $this->get_cookie_booking_currency();
686
+
687
+ $wc_currencies = get_woocommerce_currencies();
688
+ $currencies = $this->woocommerce_wpml->multi_currency->get_currencies( true );
689
+ ?>
690
+ <tr valign="top">
691
+ <th scope="row"><?php _e( 'Booking currency', 'woocommerce-multilingual' ); ?></th>
692
+ <td>
693
+ <select id="dropdown_booking_currency">
694
+ <?php foreach ( $currencies as $currency => $count ) : ?>
695
+ <option
696
+ value="<?php echo esc_html( $currency ); ?>" <?php echo $current_booking_currency == $currency ? 'selected="selected"' : ''; ?>><?php echo esc_html( $wc_currencies[ $currency ] ); ?></option>
697
+ <?php endforeach; ?>
698
+ </select>
699
+ </td>
700
+ </tr>
701
+
702
+ <?php
703
+
704
+ $wcml_booking_set_currency_nonce = wp_create_nonce( 'booking_set_currency' );
705
+
706
+ wc_enqueue_js(
707
+ "
708
+
709
+ jQuery(document).on('change', '#dropdown_booking_currency', function(){
710
+ jQuery.ajax({
711
+ url: ajaxurl,
712
+ type: 'post',
713
+ data: {
714
+ action: 'wcml_booking_set_currency',
715
+ currency: jQuery('#dropdown_booking_currency').val(),
716
+ wcml_nonce: '" . $wcml_booking_set_currency_nonce . "'
717
+ },
718
+ success: function( response ){
719
+ if(typeof response.error !== 'undefined'){
720
+ alert(response.error);
721
+ }else{
722
+ window.location = window.location.href;
723
+ }
724
+ }
725
+ })
726
+ });
727
+ "
728
+ );
729
+ }
730
+
731
+ public function set_booking_currency_ajax() {
732
+ $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
733
+ if ( ! $nonce || ! wp_verify_nonce( $nonce, 'booking_set_currency' ) ) {
734
+ echo json_encode( [ 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ] );
735
+ die();
736
+ }
737
+
738
+ $this->set_booking_currency( filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
739
+
740
+ die();
741
+ }
742
+
743
+ public function set_booking_currency( $currency_code = false ) {
744
+ $cookie_name = '_wcml_booking_currency';
745
+
746
+ if ( ! isset( $_COOKIE[ $cookie_name ] ) && ! headers_sent() ) {
747
+ $currency_code = $this->woocommerce_wpml->multi_currency->get_currency_code();
748
+ }
749
+
750
+ if ( $currency_code ) {
751
+ // @todo uncomment or delete when #wpmlcore-5796 is resolved
752
+ // do_action( 'wpsc_add_cookie', $cookie_name );
753
+ setcookie( $cookie_name, $currency_code, time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
754
+ }
755
+ }
756
+
757
+ public function get_cookie_booking_currency() {
758
+ if ( isset( $_COOKIE ['_wcml_booking_currency'] ) ) {
759
+ $currency = $_COOKIE['_wcml_booking_currency'];
760
+ } else {
761
+ $currency = wcml_get_woocommerce_currency_option();
762
+ }
763
+
764
+ return $currency;
765
+ }
766
+
767
+ public function set_order_currency_on_create_booking_page( $order_id ) {
768
+ update_post_meta( $order_id, '_order_currency', $this->get_cookie_booking_currency() );
769
+ }
770
+
771
+ public function filter_booking_currency_symbol( $currency ) {
772
+ global $pagenow;
773
+
774
+ remove_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
775
+ if ( isset( $_COOKIE ['_wcml_booking_currency'] ) && $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) {
776
+ $currency = get_woocommerce_currency_symbol( $_COOKIE ['_wcml_booking_currency'] );
777
+ }
778
+ add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
779
+
780
+ return $currency;
781
+ }
782
+
783
+ public function create_booking_page_client_currency( $currency ) {
784
+ global $pagenow;
785
+
786
+ if ( wpml_is_ajax() && isset( $_POST['form'] ) ) {
787
+ parse_str( $_POST['form'], $posted );
788
+ }
789
+
790
+ if ( ( $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) || ( isset( $posted['_wp_http_referer'] ) && strpos( $posted['_wp_http_referer'], 'page=create_booking' ) !== false ) ) {
791
+ $currency = $this->get_cookie_booking_currency();
792
+ }
793
+
794
+ return $currency;
795
+ }
796
+
797
+ public function filter_wc_booking_cost( $check, $object_id, $meta_key, $single ) {
798
+
799
+ if ( in_array(
800
+ $meta_key,
801
+ [
802
+ '_wc_booking_cost',
803
+ '_wc_booking_base_cost',
804
+ '_wc_display_cost',
805
+ '_wc_booking_pricing',
806
+ 'cost',
807
+ '_wc_booking_block_cost',
808
+ 'block_cost',
809
+ '_resource_base_costs',
810
+ '_resource_block_costs',
811
+ ]
812
+ ) ) {
813
+
814
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
815
+
816
+ $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
817
+
818
+ $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
819
+
820
+ if ( $currency === wcml_get_woocommerce_currency_option() ) {
821
+ return $check;
822
+ }
823
+
824
+ if ( in_array( $meta_key, [ 'cost', 'block_cost' ] ) ) {
825
+
826
+ if ( get_post_type( $object_id ) == 'bookable_person' ) {
827
+
828
+ $original_id = apply_filters( 'translate_object_id', wp_get_post_parent_id( $object_id ), 'product', true, $this->woocommerce_wpml->products->get_original_product_language( wp_get_post_parent_id( $object_id ) ) );
829
+ $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
830
+
831
+ $value = get_post_meta( $object_id, $meta_key . '_' . $currency, true );
832
+
833
+ if ( $cost_status && $value ) {
834
+
835
+ return $value;
836
+
837
+ } else {
838
+
839
+ remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
840
+
841
+ $cost = get_post_meta( $object_id, $meta_key, true );
842
+
843
+ add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
844
+
845
+ return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
846
+ }
847
+ } else {
848
+
849
+ return $check;
850
+
851
+ }
852
+ }
853
+
854
+ if ( in_array(
855
+ $meta_key,
856
+ [
857
+ '_wc_booking_pricing',
858
+ '_resource_base_costs',
859
+ '_resource_block_costs',
860
+ ]
861
+ ) ) {
862
+
863
+ remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
864
+
865
+ if ( $meta_key == '_wc_booking_pricing' ) {
866
+
867
+ if ( $original_id != $object_id ) {
868
+ $value = get_post_meta( $original_id, $meta_key );
869
+ } else {
870
+ $value = $check;
871
+ }
872
+ } else {
873
+
874
+ $costs = maybe_unserialize( get_post_meta( $object_id, $meta_key, true ) );
875
+
876
+ if ( ! $costs ) {
877
+ $value = $check;
878
+ } elseif ( $cost_status && isset( $costs['custom_costs'][ $currency ] ) ) {
879
+
880
+ $res_costs = [];
881
+ foreach ( $costs['custom_costs'][ $currency ] as $resource_id => $cost ) {
882
+ $trns_resource_id = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', true );
883
+ $res_costs[ $trns_resource_id ] = $cost;
884
+ }
885
+ $value = [ 0 => $res_costs ];
886
+ } elseif ( $cost_status && isset( $costs[0]['custom_costs'][ $currency ] ) ) {
887
+ $value = [ 0 => $costs[0]['custom_costs'][ $currency ] ];
888
+ } else {
889
+
890
+ $converted_values = [];
891
+
892
+ foreach ( $costs as $resource_id => $cost ) {
893
+ $converted_values[0][ $resource_id ] = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
894
+ }
895
+
896
+ $value = $converted_values;
897
+ }
898
+ }
899
+
900
+ add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
901
+
902
+ return $value;
903
+
904
+ }
905
+
906
+ $value = get_post_meta( $original_id, $meta_key . '_' . $currency, true );
907
+
908
+ if ( $cost_status && ( ! empty( $value ) || ( empty( $value ) && $meta_key == '_wc_display_cost' ) ) ) {
909
+
910
+ return $value;
911
+
912
+ } else {
913
+
914
+ remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
915
+
916
+ $value = get_post_meta( $original_id, $meta_key, true );
917
+
918
+ $value = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $value, $currency );
919
+
920
+ add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
921
+
922
+ return $value;
923
+
924
+ }
925
+ }
926
+
927
+ return $check;
928
+ }
929
+
930
+ /**
931
+ * @return bool
932
+ */
933
+ public static function isWcBookingsBefore_1_10_9() {
934
+ return version_compare( WC_BOOKINGS_VERSION, '1.10.9', '<' );
935
+ }
936
+ }
compatibility/WcBookings/SharedHooks.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcBookings;
4
+
5
+ use WC_Product;
6
+
7
+ class SharedHooks implements \IWPML_Action {
8
+
9
+ /** @var \wpdb $wpdb */
10
+ private $wpdb;
11
+
12
+ /**
13
+ * @param \wpdb $wpdb
14
+ */
15
+ public function __construct( \wpdb $wpdb ) {
16
+ $this->wpdb = $wpdb;
17
+ }
18
+
19
+ public function add_hooks() {
20
+ add_action( 'init', [ __CLASS__, 'load_assets' ] );
21
+ add_filter( 'wcml_multi_currency_ajax_actions', [ __CLASS__, 'wcml_multi_currency_is_ajax' ] );
22
+
23
+ $this->clear_transient_fields();
24
+ }
25
+
26
+ /**
27
+ * @param string|false $externalProductType
28
+ *
29
+ * @return void
30
+ */
31
+ public static function load_assets( $externalProductType = false ) {
32
+ global $pagenow;
33
+
34
+ $productId = $pagenow == 'post.php' && isset( $_GET['post'] ) ? (int) $_GET['post'] : false;
35
+
36
+ if ( $productId && get_post_type( $productId ) === 'product' ) {
37
+ $product = wc_get_product( $productId );
38
+ $productType = $product->get_type();
39
+
40
+ if ( ( self::isBooking( $product ) || $productType === $externalProductType ) || $pagenow == 'post-new.php' ) {
41
+ wp_register_style( 'wcml-bookings-css', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-bookings.css', [], WCML_VERSION );
42
+ wp_enqueue_style( 'wcml-bookings-css' );
43
+
44
+ wp_register_script( 'wcml-bookings-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-bookings.js', [ 'jquery' ], WCML_VERSION, true );
45
+ wp_enqueue_script( 'wcml-bookings-js' );
46
+ }
47
+ }
48
+ }
49
+
50
+ /**
51
+ * @param array $actions
52
+ *
53
+ * @return array
54
+ */
55
+ public static function wcml_multi_currency_is_ajax( $actions ) {
56
+ $actions[] = 'wc_bookings_calculate_costs';
57
+
58
+ return $actions;
59
+ }
60
+
61
+ public function clear_transient_fields() {
62
+ if ( isset( $_GET['post_type'] ) && $_GET['post_type'] == 'wc_booking' && isset( $_GET['page'] ) && $_GET['page'] == 'booking_calendar' ) {
63
+
64
+ // delete transient fields
65
+ $this->wpdb->query(
66
+ "
67
+ DELETE FROM {$this->wpdb->options}
68
+ WHERE option_name LIKE '%book_dr_%'
69
+ "
70
+ );
71
+ }
72
+ }
73
+
74
+ /**
75
+ * @param WC_Product|int|string $product
76
+ *
77
+ * @return bool
78
+ */
79
+ public static function isBooking( $product ) {
80
+ if ( ! $product instanceof WC_Product ) {
81
+ $product = wc_get_product( $product );
82
+ }
83
+
84
+ return $product && $product->get_type() === 'booking';
85
+ }
86
+ }
compatibility/{class-wcml-accommodation-bookings.php → WcBookings/class-wcml-accommodation-bookings.php} RENAMED
@@ -1,26 +1,17 @@
1
  <?php
2
 
3
- class WCML_Accommodation_Bookings{
4
 
5
- /**
6
- * @var woocommerce_wpml
7
- */
8
- private $woocommerce_wpml;
9
 
10
- /**
11
- * @var WCML_Bookings
12
- */
13
- private $bookings;
14
-
15
- public function __construct(
16
- woocommerce_wpml $woocommerce_wpml,
17
- WCML_Bookings $bookings
18
- ) {
19
- // @todo Cover by tests, required for wcml-3037.
20
 
 
21
  $this->woocommerce_wpml = $woocommerce_wpml;
22
- $this->bookings = $bookings;
23
 
 
24
  add_action( 'woocommerce_accommodation_bookings_after_booking_base_cost', [ $this, 'wcml_price_field_after_booking_base_cost', ] );
25
  add_action( 'woocommerce_accommodation_bookings_after_booking_pricing_override_block_cost', [ $this, 'wcml_price_field_after_booking_pricing_override_block_cost', ], 10, 2 );
26
  add_action( 'woocommerce_accommodation_bookings_after_bookings_pricing', [ $this, 'after_bookings_pricing' ] );
@@ -48,8 +39,7 @@ class WCML_Accommodation_Bookings{
48
  $product_terms = wp_get_post_terms( $post_id, 'product_type', array( "fields" => "names" ) );
49
 
50
  if(
51
- in_array( 'accommodation-booking', $product_terms )&&
52
- $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT &&
53
  $this->woocommerce_wpml->products->is_original_product( $post_id )
54
  ){
55
 
@@ -76,15 +66,10 @@ class WCML_Accommodation_Bookings{
76
 
77
  function echo_wcml_price_field( $post_id, $field, $pricing = false, $check = true, $resource_id = false ){
78
 
79
- if(
80
- $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT &&
81
- ( !$check || $this->woocommerce_wpml->products->is_original_product( $post_id ) )
82
- ){
83
 
84
  $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
85
 
86
- $wc_currencies = get_woocommerce_currencies();
87
-
88
  echo '<div class="wcml_custom_cost_field" >';
89
 
90
  foreach($currencies as $currency_code => $currency){
@@ -170,7 +155,6 @@ class WCML_Accommodation_Bookings{
170
 
171
  if(
172
  $meta_key == '_price' &&
173
- $this->woocommerce_wpml->settings[ 'enable_multi_currency' ] == WCML_MULTI_CURRENCIES_INDEPENDENT &&
174
  !is_admin() &&
175
  get_post_type( $object_id ) == 'product' &&
176
  ( $currency = $this->woocommerce_wpml->multi_currency->get_client_currency() ) !== wcml_get_woocommerce_currency_option()
@@ -191,9 +175,8 @@ class WCML_Accommodation_Bookings{
191
  return isset( $price) ? $price : $value;
192
  }
193
 
194
- public function load_assets(){
195
-
196
- $this->bookings->load_assets( 'accommodation-booking' );
197
  }
198
 
199
  }
1
  <?php
2
 
3
+ use WCML\Compatibility\WcBookings\SharedHooks;
4
 
5
+ class WCML_Accommodation_Bookings implements \IWPML_Action {
 
 
 
6
 
7
+ /** @var \woocommerce_wpml $woocommerce_wpml */
8
+ private $woocommerce_wpml;
 
 
 
 
 
 
 
 
9
 
10
+ public function __construct( \woocommerce_wpml $woocommerce_wpml ) {
11
  $this->woocommerce_wpml = $woocommerce_wpml;
12
+ }
13
 
14
+ public function add_hooks() {
15
  add_action( 'woocommerce_accommodation_bookings_after_booking_base_cost', [ $this, 'wcml_price_field_after_booking_base_cost', ] );
16
  add_action( 'woocommerce_accommodation_bookings_after_booking_pricing_override_block_cost', [ $this, 'wcml_price_field_after_booking_pricing_override_block_cost', ], 10, 2 );
17
  add_action( 'woocommerce_accommodation_bookings_after_bookings_pricing', [ $this, 'after_bookings_pricing' ] );
39
  $product_terms = wp_get_post_terms( $post_id, 'product_type', array( "fields" => "names" ) );
40
 
41
  if(
42
+ in_array( 'accommodation-booking', $product_terms ) &&
 
43
  $this->woocommerce_wpml->products->is_original_product( $post_id )
44
  ){
45
 
66
 
67
  function echo_wcml_price_field( $post_id, $field, $pricing = false, $check = true, $resource_id = false ){
68
 
69
+ if ( ! $check || $this->woocommerce_wpml->products->is_original_product( $post_id ) ) {
 
 
 
70
 
71
  $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
72
 
 
 
73
  echo '<div class="wcml_custom_cost_field" >';
74
 
75
  foreach($currencies as $currency_code => $currency){
155
 
156
  if(
157
  $meta_key == '_price' &&
 
158
  !is_admin() &&
159
  get_post_type( $object_id ) == 'product' &&
160
  ( $currency = $this->woocommerce_wpml->multi_currency->get_client_currency() ) !== wcml_get_woocommerce_currency_option()
175
  return isset( $price) ? $price : $value;
176
  }
177
 
178
+ public function load_assets() {
179
+ SharedHooks::load_assets( 'accommodation-booking' );
 
180
  }
181
 
182
  }
compatibility/{class-wcml-bookings.php → WcBookings/class-wcml-bookings.php} RENAMED
@@ -1,16 +1,19 @@
1
  <?php
2
 
3
  use WPML\FP\Maybe;
 
4
  use function WPML\FP\invoke;
5
  use function WPML\FP\pipe;
6
 
7
  /**
8
  * Class WCML_Bookings.
9
  */
10
- class WCML_Bookings {
11
 
12
  const DOMAIN = 'woocommerce-bookings';
13
 
 
 
14
  /**
15
  * @var WPML_Element_Translation_Package
16
  */
@@ -76,104 +79,12 @@ class WCML_Bookings {
76
  add_filter( 'woocommerce_booking_reminder_notification', [ $this, 'translate_notification' ], 9 );
77
  add_filter( 'woocommerce_booking_cancelled_notification', [ $this, 'translate_notification' ], 9 );
78
 
79
- add_action(
80
- 'woocommerce_bookings_after_booking_base_cost',
81
- [
82
- $this,
83
- 'wcml_price_field_after_booking_base_cost',
84
- ]
85
- );
86
- add_action(
87
- 'woocommerce_bookings_after_booking_block_cost',
88
- [
89
- $this,
90
- 'wcml_price_field_after_booking_block_cost',
91
- ]
92
- );
93
- add_action( 'woocommerce_bookings_after_display_cost', [ $this, 'wcml_price_field_after_display_cost' ] );
94
- add_action(
95
- 'woocommerce_bookings_after_booking_pricing_base_cost',
96
- [
97
- $this,
98
- 'wcml_price_field_after_booking_pricing_base_cost',
99
- ],
100
- 10,
101
- 2
102
- );
103
- add_action(
104
- 'woocommerce_bookings_after_booking_pricing_cost',
105
- [
106
- $this,
107
- 'wcml_price_field_after_booking_pricing_cost',
108
- ],
109
- 10,
110
- 2
111
- );
112
- add_action( 'woocommerce_bookings_after_person_cost', [ $this, 'wcml_price_field_after_person_cost' ] );
113
- add_action(
114
- 'woocommerce_bookings_after_person_block_cost',
115
- [
116
- $this,
117
- 'wcml_price_field_after_person_block_cost',
118
- ]
119
- );
120
- add_action(
121
- 'woocommerce_bookings_after_resource_cost',
122
- [
123
- $this,
124
- 'wcml_price_field_after_resource_cost',
125
- ],
126
- 10,
127
- 2
128
- );
129
- add_action(
130
- 'woocommerce_bookings_after_resource_block_cost',
131
- [
132
- $this,
133
- 'wcml_price_field_after_resource_block_cost',
134
- ],
135
- 10,
136
- 2
137
- );
138
- add_action( 'woocommerce_bookings_after_bookings_pricing', [ $this, 'after_bookings_pricing' ] );
139
-
140
- add_action( 'init', [ $this, 'load_assets' ] );
141
-
142
- add_action( 'save_post', [ $this, 'save_booking_action_handler' ], 110 );
143
 
144
  add_action( 'wcml_before_sync_product_data', [ $this, 'sync_bookings' ], 10, 3 );
145
  add_action( 'wcml_before_sync_product', [ $this, 'sync_booking_data' ], 10, 2 );
146
 
147
- add_filter(
148
- 'woocommerce_bookings_process_cost_rules_cost',
149
- [
150
- $this,
151
- 'wc_bookings_process_cost_rules_cost',
152
- ],
153
- 10,
154
- 3
155
- );
156
- add_filter(
157
- 'woocommerce_bookings_process_cost_rules_base_cost',
158
- [
159
- $this,
160
- 'wc_bookings_process_cost_rules_base_cost',
161
- ],
162
- 10,
163
- 3
164
- );
165
- add_filter(
166
- 'woocommerce_bookings_process_cost_rules_override_block',
167
- [
168
- $this,
169
- 'wc_bookings_process_cost_rules_override_block_cost',
170
- ],
171
- 10,
172
- 3
173
- );
174
-
175
- add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'wcml_multi_currency_is_ajax' ] );
176
-
177
  add_filter(
178
  'wcml_cart_contents_not_changed',
179
  [
@@ -184,22 +95,9 @@ class WCML_Bookings {
184
  3
185
  );
186
 
187
- add_action( 'woocommerce_bookings_after_create_booking_page', [ $this, 'booking_currency_dropdown' ] );
188
- add_action( 'init', [ $this, 'set_booking_currency' ] );
189
 
190
- add_action( 'wp_ajax_wcml_booking_set_currency', [ $this, 'set_booking_currency_ajax' ] );
191
- add_action(
192
- 'woocommerce_bookings_create_booking_page_add_order_item',
193
- [
194
- $this,
195
- 'set_order_currency_on_create_booking_page',
196
- ]
197
- );
198
- add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
199
  add_filter( 'get_booking_products_args', [ $this, 'filter_get_booking_products_args' ] );
200
- add_filter( 'wcml_filter_currency_position', [ $this, 'create_booking_page_client_currency' ] );
201
-
202
- add_filter( 'wcml_client_currency', [ $this, 'create_booking_page_client_currency' ] );
203
 
204
  add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
205
  add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
@@ -236,6 +134,7 @@ class WCML_Bookings {
236
  add_action( 'before_delete_post', [ $this, 'delete_bookings' ] );
237
  add_action( 'wp_trash_post', [ $this, 'trash_bookings' ] );
238
  add_action( 'wpml_translation_job_saved', [ $this, 'save_booking_data_to_translation' ], 10, 3 );
 
239
 
240
  if ( is_admin() ) {
241
 
@@ -302,14 +201,8 @@ class WCML_Bookings {
302
  }
303
  }
304
 
305
- if ( ! is_admin() || isset( $_POST['action'] ) && 'wc_bookings_calculate_costs' === $_POST['action'] ) {
306
- add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
307
- }
308
-
309
  add_filter( 'wpml_language_filter_extra_conditions_snippet', [ $this, 'extra_conditions_to_filter_bookings' ] );
310
 
311
- $this->clear_transient_fields();
312
-
313
  add_filter( 'wpml_tm_dashboard_translatable_types', [ $this, 'hide_bookings_type_on_tm_dashboard' ] );
314
 
315
  add_filter( 'wcml_add_to_cart_sold_individually', [ $this, 'add_to_cart_sold_individually' ], 10, 4 );
@@ -370,296 +263,9 @@ class WCML_Bookings {
370
 
371
  $this->maybe_set_booking_language( $booking_id );
372
 
373
- $this->save_custom_costs( $booking_id );
374
-
375
  $this->maybe_sync_updated_booking_meta( $booking_id );
376
  }
377
 
378
- public function wcml_price_field_after_booking_base_cost( $post_id ) {
379
-
380
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_cost' );
381
-
382
- }
383
-
384
- public function wcml_price_field_after_booking_block_cost( $post_id ) {
385
- if ( $this->sitepress->get_wp_api()->version_compare( $this->sitepress->get_wp_api()->constant( 'WC_BOOKINGS_VERSION' ), '1.10.9', '<' ) ) {
386
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_base_cost' );
387
- } else {
388
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_block_cost' );
389
- }
390
- }
391
-
392
- public function wcml_price_field_after_display_cost( $post_id ) {
393
-
394
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_display_cost' );
395
-
396
- }
397
-
398
- public function wcml_price_field_after_booking_pricing_base_cost( $pricing, $post_id ) {
399
-
400
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_pricing_base_cost', $pricing );
401
-
402
- }
403
-
404
- public function wcml_price_field_after_booking_pricing_cost( $pricing, $post_id ) {
405
-
406
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_pricing_cost', $pricing );
407
-
408
- }
409
-
410
- public function wcml_price_field_after_person_cost( $person_type_id ) {
411
-
412
- $this->echo_wcml_price_field( $person_type_id, 'wcml_wc_booking_person_cost', false, false );
413
-
414
- }
415
-
416
- public function wcml_price_field_after_person_block_cost( $person_type_id ) {
417
-
418
- $this->echo_wcml_price_field( $person_type_id, 'wcml_wc_booking_person_block_cost', false, false );
419
-
420
- }
421
-
422
- public function wcml_price_field_after_resource_cost( $resource_id, $post_id ) {
423
-
424
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_resource_cost', false, true, $resource_id );
425
-
426
- }
427
-
428
- public function wcml_price_field_after_resource_block_cost( $resource_id, $post_id ) {
429
-
430
- $this->echo_wcml_price_field( $post_id, 'wcml_wc_booking_resource_block_cost', false, true, $resource_id );
431
-
432
- }
433
-
434
- public function echo_wcml_price_field( $post_id, $field, $pricing = false, $check = true, $resource_id = false ) {
435
-
436
- if ( ( ! $check || $this->woocommerce_wpml->products->is_original_product( $post_id ) ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
437
-
438
- $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
439
-
440
- $wc_currencies = get_woocommerce_currencies();
441
-
442
- if ( ! function_exists( 'woocommerce_wp_text_input' ) ) {
443
- include_once dirname( WC_PLUGIN_FILE ) . '/includes/admin/wc-meta-box-functions.php';
444
- }
445
-
446
- echo '<div class="wcml_custom_cost_field" >';
447
-
448
- foreach ( $currencies as $currency_code => $currency ) {
449
-
450
- switch ( $field ) {
451
- case 'wcml_wc_booking_cost':
452
- woocommerce_wp_text_input(
453
- [
454
- 'id' => 'wcml_wc_booking_cost',
455
- 'class' => 'wcml_bookings_custom_price',
456
- 'name' => 'wcml_wc_booking_cost[' . $currency_code . ']',
457
- 'label' => get_woocommerce_currency_symbol( $currency_code ),
458
- 'description' => __( 'One-off cost for the booking as a whole.', 'woocommerce-bookings' ),
459
- 'value' => get_post_meta( $post_id, '_wc_booking_cost_' . $currency_code, true ),
460
- 'type' => 'number',
461
- 'desc_tip' => true,
462
- 'custom_attributes' => [
463
- 'min' => '',
464
- 'step' => '0.01',
465
- ],
466
- ]
467
- );
468
- break;
469
- case 'wcml_wc_booking_block_cost':
470
- case 'wcml_wc_booking_base_cost':
471
- $block_cost_key = '_wc_booking_base_cost_';
472
- if ( $field === 'wcml_wc_booking_block_cost' ) {
473
- $block_cost_key = '_wc_booking_block_cost_';
474
- }
475
- $block_cost_key .= $currency_code;
476
- woocommerce_wp_text_input(
477
- [
478
- 'id' => $field,
479
- 'class' => 'wcml_bookings_custom_price',
480
- 'name' => $field . '[' . $currency_code . ']',
481
- 'label' => get_woocommerce_currency_symbol( $currency_code ),
482
- 'description' => __( 'This is the cost per block booked. All other costs (for resources and persons) are added to this.', 'woocommerce-bookings' ),
483
- 'value' => get_post_meta( $post_id, $block_cost_key, true ),
484
- 'type' => 'number',
485
- 'desc_tip' => true,
486
- 'custom_attributes' => [
487
- 'min' => '',
488
- 'step' => '0.01',
489
- ],
490
- ]
491
- );
492
- break;
493
- case 'wcml_wc_display_cost':
494
- woocommerce_wp_text_input(
495
- [
496
- 'id' => 'wcml_wc_display_cost',
497
- 'class' => 'wcml_bookings_custom_price',
498
- 'name' => 'wcml_wc_display_cost[' . $currency_code . ']',
499
- 'label' => get_woocommerce_currency_symbol( $currency_code ),
500
- 'description' => __( 'The cost is displayed to the user on the frontend. Leave blank to have it calculated for you. If a booking has varying costs, this will be prefixed with the word "from:".', 'woocommerce-bookings' ),
501
- 'value' => get_post_meta( $post_id, '_wc_display_cost_' . $currency_code, true ),
502
- 'type' => 'number',
503
- 'desc_tip' => true,
504
- 'custom_attributes' => [
505
- 'min' => '',
506
- 'step' => '0.01',
507
- ],
508
- ]
509
- );
510
- break;
511
-
512
- case 'wcml_wc_booking_pricing_base_cost':
513
- if ( isset( $pricing[ 'base_cost_' . $currency_code ] ) ) {
514
- $value = $pricing[ 'base_cost_' . $currency_code ];
515
- } else {
516
- $value = '';
517
- }
518
-
519
- echo '<div class="wcml_bookings_range_block" >';
520
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
521
- echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_base_cost[' . esc_html( $currency_code ) . '][]" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
522
- echo '</div>';
523
- break;
524
-
525
- case 'wcml_wc_booking_pricing_cost':
526
- if ( isset( $pricing[ 'cost_' . $currency_code ] ) ) {
527
- $value = $pricing[ 'cost_' . $currency_code ];
528
- } else {
529
- $value = '';
530
- }
531
-
532
- echo '<div class="wcml_bookings_range_block" >';
533
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
534
- echo '<input type="number" step="0.01" name="wcml_wc_booking_pricing_cost[' . esc_html( $currency_code ) . '][]" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
535
- echo '</div>';
536
- break;
537
-
538
- case 'wcml_wc_booking_person_cost':
539
- $value = get_post_meta( $post_id, 'cost_' . $currency_code, true );
540
-
541
- echo '<div class="wcml_bookings_person_block" >';
542
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
543
- echo '<input type="number" step="0.01" name="wcml_wc_booking_person_cost[' . intval( $post_id ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
544
- echo '</div>';
545
- break;
546
-
547
- case 'wcml_wc_booking_person_block_cost':
548
- $value = get_post_meta( $post_id, 'block_cost_' . $currency_code, true );
549
-
550
- echo '<div class="wcml_bookings_person_block" >';
551
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
552
- echo '<input type="number" step="0.01" name="wcml_wc_booking_person_block_cost[' . intval( $post_id ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
553
- echo '</div>';
554
- break;
555
-
556
- case 'wcml_wc_booking_resource_cost':
557
- $resource_base_costs = maybe_unserialize( get_post_meta( $post_id, '_resource_base_costs', true ) );
558
-
559
- if ( isset( $resource_base_costs['custom_costs'][ $currency_code ][ $resource_id ] ) ) {
560
- $value = $resource_base_costs['custom_costs'][ $currency_code ][ $resource_id ];
561
- } else {
562
- $value = '';
563
- }
564
-
565
- echo '<div class="wcml_bookings_resource_block" >';
566
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
567
- echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_cost[' . esc_html( $resource_id ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
568
- echo '</div>';
569
- break;
570
-
571
- case 'wcml_wc_booking_resource_block_cost':
572
- $resource_block_costs = maybe_unserialize( get_post_meta( $post_id, '_resource_block_costs', true ) );
573
-
574
- if ( isset( $resource_block_costs['custom_costs'][ $currency_code ][ $resource_id ] ) ) {
575
- $value = $resource_block_costs['custom_costs'][ $currency_code ][ $resource_id ];
576
- } else {
577
- $value = '';
578
- }
579
-
580
- echo '<div class="wcml_bookings_resource_block" >';
581
- echo '<label>' . wp_kses_post( get_woocommerce_currency_symbol( $currency_code ) ) . '</label>';
582
- echo '<input type="number" step="0.01" name="wcml_wc_booking_resource_block_cost[' . esc_html( $resource_id ) . '][' . esc_html( $currency_code ) . ']" class="wcml_bookings_custom_price" value="' . esc_html( $value ) . '" placeholder="0" />';
583
- echo '</div>';
584
- break;
585
-
586
- default:
587
- break;
588
-
589
- }
590
- }
591
-
592
- echo '</div>';
593
-
594
- }
595
- }
596
-
597
- public function after_bookings_pricing( $post_id ) {
598
-
599
- if ( in_array( 'booking', wp_get_post_terms( $post_id, 'product_type', [ 'fields' => 'names' ] ) ) && $this->woocommerce_wpml->products->is_original_product( $post_id ) && $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
600
-
601
- $custom_costs_status = get_post_meta( $post_id, '_wcml_custom_costs_status', true );
602
-
603
- $checked = ! $custom_costs_status ? 'checked="checked"' : ' ';
604
-
605
- echo '<div class="wcml_custom_costs">';
606
-
607
- echo '<input type="radio" name="_wcml_custom_costs" id="wcml_custom_costs_auto" value="0" class="wcml_custom_costs_input" ' . esc_html( $checked ) . ' />';
608
- echo '<label for="wcml_custom_costs_auto">' . esc_html__( 'Calculate costs in other currencies automatically', 'woocommerce-multilingual' ) . '</label>';
609
-
610
- $checked = 1 === (int) $custom_costs_status ? 'checked="checked"' : ' ';
611
-
612
- echo '<input type="radio" name="_wcml_custom_costs" value="1" id="wcml_custom_costs_manually" class="wcml_custom_costs_input" ' . esc_html( $checked ) . ' />';
613
- echo '<label for="wcml_custom_costs_manually">' . esc_html__( 'Set costs in other currencies manually', 'woocommerce-multilingual' ) . '</label>';
614
-
615
- wp_nonce_field( 'wcml_save_custom_costs', '_wcml_custom_costs_nonce' );
616
-
617
- echo '</div>';
618
- }
619
-
620
- }
621
-
622
- public function save_custom_costs( $post_id ) {
623
- $nonce = filter_var( isset( $_POST['_wcml_custom_costs_nonce'] ) ? $_POST['_wcml_custom_costs_nonce'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
624
-
625
- if ( isset( $_POST['_wcml_custom_costs'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_costs' ) ) {
626
-
627
- update_post_meta( $post_id, '_wcml_custom_costs_status', $_POST['_wcml_custom_costs'] );
628
-
629
- if ( 1 === (int) $_POST['_wcml_custom_costs'] ) {
630
-
631
- $currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
632
- if ( empty( $currencies ) || 0 === $post_id ) {
633
- return false;
634
- }
635
-
636
- $this->update_booking_costs( $currencies, $post_id );
637
- $this->update_booking_pricing( $currencies, $post_id );
638
-
639
- if ( isset( $_POST['wcml_wc_booking_person_cost'] ) && is_array( $_POST['wcml_wc_booking_person_cost'] ) ) {
640
- $this->update_booking_person_cost( $currencies, $_POST['wcml_wc_booking_person_cost'] );
641
- }
642
-
643
- if ( isset( $_POST['wcml_wc_booking_person_block_cost'] ) && is_array( $_POST['wcml_wc_booking_person_block_cost'] ) ) {
644
- $this->update_booking_person_block_cost( $currencies, $_POST['wcml_wc_booking_person_block_cost'] );
645
- }
646
-
647
- if ( isset( $_POST['wcml_wc_booking_resource_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_cost'] ) ) {
648
- $this->update_booking_resource_cost( $currencies, $post_id, $_POST['wcml_wc_booking_resource_cost'] );
649
- }
650
-
651
- if ( isset( $_POST['wcml_wc_booking_resource_block_cost'] ) && is_array( $_POST['wcml_wc_booking_resource_block_cost'] ) ) {
652
- $this->update_booking_resource_block_cost( $currencies, $post_id, $_POST['wcml_wc_booking_resource_block_cost'] );
653
- }
654
-
655
- update_post_meta( $post_id, '_price', '' );
656
- } else {
657
- return false;
658
- }
659
- }
660
-
661
- }
662
-
663
  // sync existing product bookings for translations.
664
  public function sync_bookings( $original_product_id, $product_id, $language ) {
665
  $all_bookings_for_product = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id as id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_product_id' AND meta_value = %d", $original_product_id ) );
@@ -915,142 +521,6 @@ class WCML_Bookings {
915
  return $new_person_id;
916
  }
917
 
918
- public function filter_wc_booking_cost( $check, $object_id, $meta_key, $single ) {
919
-
920
- if ( in_array(
921
- $meta_key,
922
- [
923
- '_wc_booking_cost',
924
- '_wc_booking_base_cost',
925
- '_wc_display_cost',
926
- '_wc_booking_pricing',
927
- 'cost',
928
- '_wc_booking_block_cost',
929
- 'block_cost',
930
- '_resource_base_costs',
931
- '_resource_block_costs',
932
- ]
933
- ) ) {
934
-
935
- if ( WCML_MULTI_CURRENCIES_INDEPENDENT === $this->woocommerce_wpml->settings['enable_multi_currency'] ) {
936
-
937
- $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
938
-
939
- $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
940
-
941
- $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
942
-
943
- if ( $currency === wcml_get_woocommerce_currency_option() ) {
944
- return $check;
945
- }
946
-
947
- if ( in_array( $meta_key, [ 'cost', 'block_cost' ] ) ) {
948
-
949
- if ( get_post_type( $object_id ) == 'bookable_person' ) {
950
-
951
- $original_id = apply_filters( 'translate_object_id', wp_get_post_parent_id( $object_id ), 'product', true, $this->woocommerce_wpml->products->get_original_product_language( wp_get_post_parent_id( $object_id ) ) );
952
- $cost_status = get_post_meta( $original_id, '_wcml_custom_costs_status', true );
953
-
954
- $value = get_post_meta( $object_id, $meta_key . '_' . $currency, true );
955
-
956
- if ( $cost_status && $value ) {
957
-
958
- return $value;
959
-
960
- } else {
961
-
962
- remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
963
-
964
- $cost = get_post_meta( $object_id, $meta_key, true );
965
-
966
- add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
967
-
968
- return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
969
- }
970
- } else {
971
-
972
- return $check;
973
-
974
- }
975
- }
976
-
977
- if ( in_array(
978
- $meta_key,
979
- [
980
- '_wc_booking_pricing',
981
- '_resource_base_costs',
982
- '_resource_block_costs',
983
- ]
984
- ) ) {
985
-
986
- remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
987
-
988
- if ( $meta_key == '_wc_booking_pricing' ) {
989
-
990
- if ( $original_id != $object_id ) {
991
- $value = get_post_meta( $original_id, $meta_key );
992
- } else {
993
- $value = $check;
994
- }
995
- } else {
996
-
997
- $costs = maybe_unserialize( get_post_meta( $object_id, $meta_key, true ) );
998
-
999
- if ( ! $costs ) {
1000
- $value = $check;
1001
- } elseif ( $cost_status && isset( $costs['custom_costs'][ $currency ] ) ) {
1002
-
1003
- $res_costs = [];
1004
- foreach ( $costs['custom_costs'][ $currency ] as $resource_id => $cost ) {
1005
- $trns_resource_id = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', true, $this->sitepress->get_current_language() );
1006
- $res_costs[ $trns_resource_id ] = $cost;
1007
- }
1008
- $value = [ 0 => $res_costs ];
1009
- } elseif ( $cost_status && isset( $costs[0]['custom_costs'][ $currency ] ) ) {
1010
- $value = [ 0 => $costs[0]['custom_costs'][ $currency ] ];
1011
- } else {
1012
-
1013
- $converted_values = [];
1014
-
1015
- foreach ( $costs as $resource_id => $cost ) {
1016
- $converted_values[0][ $resource_id ] = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
1017
- }
1018
-
1019
- $value = $converted_values;
1020
- }
1021
- }
1022
-
1023
- add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
1024
-
1025
- return $value;
1026
-
1027
- }
1028
-
1029
- $value = get_post_meta( $original_id, $meta_key . '_' . $currency, true );
1030
-
1031
- if ( $cost_status && ( ! empty( $value ) || ( empty( $value ) && $meta_key == '_wc_display_cost' ) ) ) {
1032
-
1033
- return $value;
1034
-
1035
- } else {
1036
-
1037
- remove_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10 );
1038
-
1039
- $value = get_post_meta( $original_id, $meta_key, true );
1040
-
1041
- $value = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $value, $currency );
1042
-
1043
- add_filter( 'get_post_metadata', [ $this, 'filter_wc_booking_cost' ], 10, 4 );
1044
-
1045
- return $value;
1046
-
1047
- }
1048
- }
1049
- }
1050
-
1051
- return $check;
1052
- }
1053
-
1054
  public function sync_resource_costs_with_translations( $object_id, $meta_key, $check = false ) {
1055
 
1056
  $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
@@ -1115,112 +585,10 @@ class WCML_Bookings {
1115
 
1116
  }
1117
 
1118
- public function wc_bookings_process_cost_rules_cost( $cost, $fields, $key ) {
1119
- return $this->filter_pricing_cost( $cost, $fields, 'cost_', $key );
1120
- }
1121
-
1122
- public function wc_bookings_process_cost_rules_base_cost( $base_cost, $fields, $key ) {
1123
- return $this->filter_pricing_cost( $base_cost, $fields, 'base_cost_', $key );
1124
- }
1125
-
1126
- public function wc_bookings_process_cost_rules_override_block_cost( $override_cost, $fields, $key ) {
1127
- return $this->filter_pricing_cost( $override_cost, $fields, 'override_block_', $key );
1128
- }
1129
-
1130
- public function filter_pricing_cost( $cost, $fields, $name, $key ) {
1131
- global $product;
1132
-
1133
- if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
1134
-
1135
- $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
1136
-
1137
- if ( $currency === wcml_get_woocommerce_currency_option() ) {
1138
- return $cost;
1139
- }
1140
-
1141
- if ( isset( $_POST['form'] ) ) {
1142
- parse_str( $_POST['form'], $posted );
1143
-
1144
- $booking_id = $posted['add-to-cart'];
1145
-
1146
- } elseif ( isset( $_POST['add-to-cart'] ) ) {
1147
-
1148
- $booking_id = $_POST['add-to-cart'];
1149
-
1150
- }
1151
-
1152
- if ( isset( $booking_id ) ) {
1153
- $original_id = $this->woocommerce_wpml->products->get_original_product_id( $booking_id );
1154
-
1155
- if ( $booking_id != $original_id ) {
1156
- $fields = maybe_unserialize( get_post_meta( $original_id, '_wc_booking_pricing', true ) );
1157
- $fields = $fields[ $key ];
1158
- }
1159
- }
1160
-
1161
- $needs_filter_pricing_cost = $this->needs_filter_pricing_cost( $name, $fields );
1162
-
1163
- if ( $needs_filter_pricing_cost ) {
1164
- if ( isset( $fields[ $name . $currency ] ) ) {
1165
- return $fields[ $name . $currency ];
1166
- } else {
1167
- return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
1168
- }
1169
- }
1170
- }
1171
-
1172
- return $cost;
1173
-
1174
- }
1175
-
1176
- public function needs_filter_pricing_cost( $name, $fields ) {
1177
-
1178
- $modifier_skip_values = [ 'divide', 'times' ];
1179
-
1180
- if (
1181
- 'override_block_' === $name ||
1182
- ( 'cost_' === $name && ! in_array( $fields['modifier'], $modifier_skip_values ) ) ||
1183
- ( 'base_cost_' === $name && ! in_array( $fields['base_modifier'], $modifier_skip_values ) )
1184
- ) {
1185
- return true;
1186
- } else {
1187
- return false;
1188
- }
1189
- }
1190
-
1191
- public function load_assets( $external_product_type = false ) {
1192
- global $pagenow;
1193
-
1194
- $product_id = $pagenow == 'post.php' && isset( $_GET['post'] ) ? (int) $_GET['post'] : false;
1195
-
1196
- if ( $product_id && get_post_type( $product_id ) === 'product' ) {
1197
- $product = wc_get_product( $product_id );
1198
- $product_type = $product->get_type();
1199
-
1200
- if ( ( $this->is_booking( $product ) || $product_type === $external_product_type ) || $pagenow == 'post-new.php' ) {
1201
-
1202
- wp_register_style( 'wcml-bookings-css', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-bookings.css', [], WCML_VERSION );
1203
- wp_enqueue_style( 'wcml-bookings-css' );
1204
-
1205
- wp_register_script( 'wcml-bookings-js', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-bookings.js', [ 'jquery' ], WCML_VERSION, true );
1206
- wp_enqueue_script( 'wcml-bookings-js' );
1207
-
1208
- }
1209
- }
1210
-
1211
- }
1212
-
1213
  public function localize_lock_fields_js() {
1214
  wp_localize_script( 'wcml-bookings-js', 'lock_settings', [ 'lock_fields' => 1 ] );
1215
  }
1216
 
1217
- public function wcml_multi_currency_is_ajax( $actions ) {
1218
-
1219
- $actions[] = 'wc_bookings_calculate_costs';
1220
-
1221
- return $actions;
1222
- }
1223
-
1224
  public function filter_bundled_product_in_cart_contents( $cart_item, $key, $current_language ) {
1225
 
1226
  if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['booking'] ) ) {
@@ -1285,132 +653,9 @@ class WCML_Bookings {
1285
  return $cost;
1286
  }
1287
 
1288
- public function booking_currency_dropdown() {
1289
-
1290
- if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
1291
- $current_booking_currency = $this->get_cookie_booking_currency();
1292
-
1293
- $wc_currencies = get_woocommerce_currencies();
1294
- $currencies = $this->woocommerce_wpml->multi_currency->get_currencies( $include_default = true );
1295
- ?>
1296
- <tr valign="top">
1297
- <th scope="row"><?php _e( 'Booking currency', 'woocommerce-multilingual' ); ?></th>
1298
- <td>
1299
- <select id="dropdown_booking_currency">
1300
- <?php foreach ( $currencies as $currency => $count ) : ?>
1301
- <option
1302
- value="<?php echo esc_html( $currency ); ?>" <?php echo $current_booking_currency == $currency ? 'selected="selected"' : ''; ?>><?php echo esc_html( $wc_currencies[ $currency ] ); ?></option>
1303
- <?php endforeach; ?>
1304
- </select>
1305
- </td>
1306
- </tr>
1307
-
1308
- <?php
1309
-
1310
- $wcml_booking_set_currency_nonce = wp_create_nonce( 'booking_set_currency' );
1311
-
1312
- wc_enqueue_js(
1313
- "
1314
-
1315
- jQuery(document).on('change', '#dropdown_booking_currency', function(){
1316
- jQuery.ajax({
1317
- url: ajaxurl,
1318
- type: 'post',
1319
- data: {
1320
- action: 'wcml_booking_set_currency',
1321
- currency: jQuery('#dropdown_booking_currency').val(),
1322
- wcml_nonce: '" . $wcml_booking_set_currency_nonce . "'
1323
- },
1324
- success: function( response ){
1325
- if(typeof response.error !== 'undefined'){
1326
- alert(response.error);
1327
- }else{
1328
- window.location = window.location.href;
1329
- }
1330
- }
1331
- })
1332
- });
1333
- "
1334
- );
1335
-
1336
- }
1337
-
1338
- }
1339
-
1340
- public function set_booking_currency_ajax() {
1341
-
1342
- $nonce = filter_input( INPUT_POST, 'wcml_nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
1343
- if ( ! $nonce || ! wp_verify_nonce( $nonce, 'booking_set_currency' ) ) {
1344
- echo json_encode( [ 'error' => __( 'Invalid nonce', 'woocommerce-multilingual' ) ] );
1345
- die();
1346
- }
1347
-
1348
- $this->set_booking_currency( filter_input( INPUT_POST, 'currency', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
1349
-
1350
- die();
1351
- }
1352
-
1353
- public function set_booking_currency( $currency_code = false ) {
1354
- $cookie_name = '_wcml_booking_currency';
1355
-
1356
- if ( ! isset( $_COOKIE[ $cookie_name ] ) && ! headers_sent() ) {
1357
- $currency_code = wcml_get_woocommerce_currency_option();
1358
-
1359
- if ( WCML_MULTI_CURRENCIES_INDEPENDENT === $this->woocommerce_wpml->settings['enable_multi_currency'] ) {
1360
- $currency_code = $this->woocommerce_wpml->multi_currency->get_currency_code();
1361
- }
1362
- }
1363
-
1364
- if ( $currency_code ) {
1365
- // @todo uncomment or delete when #wpmlcore-5796 is resolved
1366
- // do_action( 'wpsc_add_cookie', $cookie_name );
1367
- setcookie( $cookie_name, $currency_code, time() + 86400, COOKIEPATH, COOKIE_DOMAIN );
1368
- }
1369
- }
1370
-
1371
- public function get_cookie_booking_currency() {
1372
-
1373
- if ( isset( $_COOKIE ['_wcml_booking_currency'] ) ) {
1374
- $currency = $_COOKIE['_wcml_booking_currency'];
1375
- } else {
1376
- $currency = wcml_get_woocommerce_currency_option();
1377
- }
1378
-
1379
- return $currency;
1380
- }
1381
-
1382
- public function filter_booking_currency_symbol( $currency ) {
1383
- global $pagenow;
1384
-
1385
- remove_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
1386
- if ( isset( $_COOKIE ['_wcml_booking_currency'] ) && $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) {
1387
- $currency = get_woocommerce_currency_symbol( $_COOKIE ['_wcml_booking_currency'] );
1388
- }
1389
- add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_booking_currency_symbol' ] );
1390
-
1391
- return $currency;
1392
- }
1393
-
1394
- public function create_booking_page_client_currency( $currency ) {
1395
- global $pagenow;
1396
-
1397
- if ( wpml_is_ajax() && isset( $_POST['form'] ) ) {
1398
- parse_str( $_POST['form'], $posted );
1399
- }
1400
-
1401
- if ( ( $pagenow == 'edit.php' && isset( $_GET['page'] ) && $_GET['page'] == 'create_booking' ) || ( isset( $posted['_wp_http_referer'] ) && strpos( $posted['_wp_http_referer'], 'page=create_booking' ) !== false ) ) {
1402
- $currency = $this->get_cookie_booking_currency();
1403
- }
1404
-
1405
- return $currency;
1406
- }
1407
-
1408
- public function set_order_currency_on_create_booking_page( $order_id ) {
1409
- update_post_meta( $order_id, '_order_currency', $this->get_cookie_booking_currency() );
1410
-
1411
- update_post_meta( $order_id, 'wpml_language', $this->sitepress->get_current_language() );
1412
-
1413
- }
1414
 
1415
  public function filter_get_booking_products_args( $args ) {
1416
  if ( isset( $args['suppress_filters'] ) ) {
@@ -1889,22 +1134,6 @@ class WCML_Bookings {
1889
 
1890
  }
1891
 
1892
- public function clear_transient_fields() {
1893
-
1894
- if ( isset( $_GET['post_type'] ) && $_GET['post_type'] == 'wc_booking' && isset( $_GET['page'] ) && $_GET['page'] == 'booking_calendar' ) {
1895
-
1896
- // delete transient fields
1897
- $this->wpdb->query(
1898
- "
1899
- DELETE FROM {$this->wpdb->options}
1900
- WHERE option_name LIKE '%book_dr_%'
1901
- "
1902
- );
1903
-
1904
- }
1905
-
1906
- }
1907
-
1908
  public function delete_bookings( $booking_id ) {
1909
 
1910
  if (
@@ -1992,61 +1221,57 @@ class WCML_Bookings {
1992
  private function save_person_translation( $post_id, $data, $job ) {
1993
  $person_translations = [];
1994
 
1995
- if ( $this->is_booking( $post_id ) ) {
1996
 
1997
- foreach ( $data as $value ) {
1998
 
1999
- if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:person:' ) === 0 ) {
2000
 
2001
- $exp = explode( ':', $value['field_type'] );
 
2002
 
2003
- $person_id = $exp[2];
2004
- $field = $exp[3];
2005
 
2006
- $person_translations[ $person_id ][ $field ] = $value['data'];
2007
-
2008
- }
2009
- }
2010
 
2011
- if ( $person_translations ) {
2012
 
2013
- foreach ( $person_translations as $person_id => $pt ) {
2014
 
2015
- $person_trid = $this->sitepress->get_element_trid( $person_id, 'post_bookable_person' );
2016
 
2017
- $person_id_translated = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $job->language_code );
2018
 
2019
- if ( empty( $person_id_translated ) ) {
2020
 
2021
- $person_post = [
2022
 
2023
- 'post_type' => 'bookable_person',
2024
- 'post_status' => 'publish',
2025
- 'post_title' => $pt['name'],
2026
- 'post_parent' => $post_id,
2027
- 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '',
2028
 
2029
- ];
2030
 
2031
- $person_id_translated = wp_insert_post( $person_post );
2032
 
2033
- $this->sitepress->set_element_language_details( $person_id_translated, 'post_bookable_person', $person_trid, $job->language_code );
2034
 
2035
- } else {
2036
 
2037
- $person_post = [
2038
- 'ID' => $person_id_translated,
2039
- 'post_title' => $pt['name'],
2040
- 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '',
2041
- ];
2042
 
2043
- wp_update_post( $person_post );
2044
-
2045
- }
2046
- }
2047
- }
2048
- }
2049
 
 
 
 
2050
  }
2051
 
2052
  public function append_resources_to_translation_package( $package, $post ) {
@@ -2076,76 +1301,72 @@ class WCML_Bookings {
2076
  private function save_resource_translation( $post_id, $data, $job ) {
2077
  $resource_translations = [];
2078
 
2079
- if ( $this->is_booking( $post_id ) ) {
2080
-
2081
- foreach ( $data as $value ) {
2082
-
2083
- if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:resource:' ) === 0 ) {
2084
 
2085
- $exp = explode( ':', $value['field_type'] );
2086
 
2087
- $resource_id = $exp[2];
2088
- $field = $exp[3];
2089
 
2090
- $resource_translations[ $resource_id ][ $field ] = $value['data'];
 
2091
 
2092
- }
2093
- }
2094
 
2095
- if ( $resource_translations ) {
 
2096
 
2097
- foreach ( $resource_translations as $resource_id => $rt ) {
2098
 
2099
- $resource_trid = $this->sitepress->get_element_trid( $resource_id, 'post_bookable_resource' );
2100
 
2101
- $resource_id_translated = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', false, $job->language_code );
2102
 
2103
- if ( empty( $resource_id_translated ) ) {
2104
 
2105
- $resource_post = [
2106
 
2107
- 'post_type' => 'bookable_resource',
2108
- 'post_status' => 'publish',
2109
- 'post_title' => $rt['name'],
2110
- 'post_parent' => $post_id,
2111
- ];
2112
 
2113
- $resource_id_translated = wp_insert_post( $resource_post );
 
 
 
 
2114
 
2115
- $this->sitepress->set_element_language_details( $resource_id_translated, 'post_bookable_resource', $resource_trid, $job->language_code );
2116
 
2117
- $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) );
2118
- $relationship = [
2119
- 'product_id' => $post_id,
2120
- 'resource_id' => $resource_id_translated,
2121
- 'sort_order' => $sort_order,
2122
- ];
2123
- $this->wpdb->insert( $this->wpdb->prefix . 'wc_booking_relationships', $relationship );
2124
 
2125
- } else {
 
 
 
 
 
 
2126
 
2127
- $resource_post = [
2128
- 'ID' => $resource_id_translated,
2129
- 'post_title' => $rt['name'],
2130
- ];
2131
 
2132
- wp_update_post( $resource_post );
 
 
 
2133
 
2134
- $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) );
2135
- $this->wpdb->update(
2136
- $this->wpdb->prefix . 'wc_booking_relationships',
2137
- [ 'sort_order' => $sort_order ],
2138
- [
2139
- 'product_id' => $post_id,
2140
- 'resource_id' => $resource_id_translated,
2141
- ]
2142
- );
2143
 
2144
- }
2145
- }
2146
- }
2147
- }
 
 
 
 
 
2148
 
 
 
 
2149
  }
2150
 
2151
  public function wcml_js_lock_fields_ids( $ids ) {
@@ -2199,181 +1420,6 @@ class WCML_Bookings {
2199
 
2200
  }
2201
 
2202
- /**
2203
- * @param array $currencies
2204
- * @param int $post_id
2205
- *
2206
- * @return bool
2207
- */
2208
- private function update_booking_costs( $currencies = [], $post_id = 0 ) {
2209
- $booking_options = [
2210
- 'wcml_wc_booking_cost' => '_wc_booking_cost_',
2211
- 'wcml_wc_booking_block_cost' => '_wc_booking_block_cost_',
2212
- 'wcml_wc_display_cost' => '_wc_display_cost_',
2213
- ];
2214
-
2215
- if ( $this->sitepress->get_wp_api()->version_compare( $this->sitepress->get_wp_api()->constant( 'WC_BOOKINGS_VERSION' ), '1.10.9', '<' ) ) {
2216
- unset( $booking_options['wcml_wc_booking_block_cost'] );
2217
- $booking_options['wcml_wc_booking_base_cost'] = '_wc_booking_base_cost_';
2218
- }
2219
-
2220
- foreach ( $currencies as $code => $currency ) {
2221
- foreach ( $booking_options as $booking_options_post_key => $booking_options_meta_key_prefix ) {
2222
- if ( isset( $_POST[ $booking_options_post_key ][ $code ] ) ) {
2223
- update_post_meta( $post_id, $booking_options_meta_key_prefix . $code, sanitize_text_field( $_POST[ $booking_options_post_key ][ $code ] ) );
2224
- }
2225
- }
2226
- }
2227
-
2228
- return true;
2229
- }
2230
-
2231
- /**
2232
- * @param array $currencies
2233
- * @param int $post_id
2234
- *
2235
- * @return bool
2236
- */
2237
- private function update_booking_pricing( $currencies = [], $post_id = 0 ) {
2238
- $updated_meta = [];
2239
- $booking_pricing = get_post_meta( $post_id, '_wc_booking_pricing', true );
2240
- if ( empty( $booking_pricing ) ) {
2241
- return false;
2242
- }
2243
-
2244
- foreach ( $booking_pricing as $key => $prices ) {
2245
- $updated_meta[ $key ] = $prices;
2246
- foreach ( $currencies as $code => $currency ) {
2247
- if ( isset( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] ) ) {
2248
- $updated_meta[ $key ][ 'base_cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_base_cost'][ $code ][ $key ] );
2249
- }
2250
- if ( isset( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] ) ) {
2251
- $updated_meta[ $key ][ 'cost_' . $code ] = sanitize_text_field( $_POST['wcml_wc_booking_pricing_cost'][ $code ][ $key ] );
2252
- }
2253
- }
2254
- }
2255
-
2256
- update_post_meta( $post_id, '_wc_booking_pricing', $updated_meta );
2257
-
2258
- return true;
2259
- }
2260
-
2261
- /**
2262
- * @param array $currencies
2263
- * @param array $person_costs
2264
- *
2265
- * @return bool
2266
- */
2267
- private function update_booking_person_cost( $currencies = [], $person_costs = [] ) {
2268
- if ( empty( $person_costs ) ) {
2269
- return false;
2270
- }
2271
-
2272
- foreach ( $person_costs as $person_id => $costs ) {
2273
- foreach ( $currencies as $code => $currency ) {
2274
- if ( isset( $costs[ $code ] ) ) {
2275
- update_post_meta( $person_id, 'cost_' . $code, sanitize_text_field( $costs[ $code ] ) );
2276
- }
2277
- }
2278
- }
2279
-
2280
- return true;
2281
- }
2282
-
2283
- /**
2284
- * @param array $currencies
2285
- * @param array $block_costs
2286
- *
2287
- * @return bool
2288
- */
2289
- private function update_booking_person_block_cost( $currencies = [], $block_costs = [] ) {
2290
- if ( empty( $block_costs ) ) {
2291
- return false;
2292
- }
2293
-
2294
- foreach ( $block_costs as $person_id => $costs ) {
2295
- foreach ( $currencies as $code => $currency ) {
2296
- if ( isset( $costs[ $code ] ) ) {
2297
- update_post_meta( $person_id, 'block_cost_' . $code, sanitize_text_field( $costs[ $code ] ) );
2298
- }
2299
- }
2300
- }
2301
-
2302
- return true;
2303
- }
2304
-
2305
- /**
2306
- * @param array $currencies
2307
- * @param int $post_id
2308
- * @param array $resource_cost
2309
- *
2310
- * @return bool
2311
- */
2312
- private function update_booking_resource_cost( $currencies = [], $post_id = 0, $resource_cost = [] ) {
2313
- if ( empty( $resource_cost ) ) {
2314
- return false;
2315
- }
2316
-
2317
- $updated_meta = get_post_meta( $post_id, '_resource_base_costs', true );
2318
- if ( ! is_array( $updated_meta ) ) {
2319
- $updated_meta = [];
2320
- }
2321
-
2322
- $wc_booking_resource_costs = [];
2323
-
2324
- foreach ( $resource_cost as $resource_id => $costs ) {
2325
-
2326
- foreach ( $currencies as $code => $currency ) {
2327
-
2328
- if ( isset( $costs[ $code ] ) ) {
2329
- $wc_booking_resource_costs[ $code ][ $resource_id ] = sanitize_text_field( $costs[ $code ] );
2330
- }
2331
- }
2332
- }
2333
-
2334
- $updated_meta['custom_costs'] = $wc_booking_resource_costs;
2335
-
2336
- update_post_meta( $post_id, '_resource_base_costs', $updated_meta );
2337
-
2338
- $this->sync_resource_costs_with_translations( $post_id, '_resource_base_costs' );
2339
-
2340
- return true;
2341
- }
2342
-
2343
- /**
2344
- * @param array $currencies
2345
- * @param int $post_id
2346
- *
2347
- * @return bool
2348
- */
2349
- private function update_booking_resource_block_cost( $currencies = [], $post_id = 0, $resource_block_cost = [] ) {
2350
- if ( empty( $resource_block_cost ) ) {
2351
- return false;
2352
- }
2353
-
2354
- $updated_meta = get_post_meta( $post_id, '_resource_block_costs', true );
2355
-
2356
- $wc_booking_resource_block_costs = [];
2357
-
2358
- foreach ( $resource_block_cost as $resource_id => $costs ) {
2359
-
2360
- foreach ( $currencies as $code => $currency ) {
2361
-
2362
- if ( isset( $costs[ $code ] ) ) {
2363
- $wc_booking_resource_block_costs[ $code ][ $resource_id ] = sanitize_text_field( $costs[ $code ] );
2364
- }
2365
- }
2366
- }
2367
-
2368
- $updated_meta['custom_costs'] = $wc_booking_resource_block_costs;
2369
-
2370
- update_post_meta( $post_id, '_resource_block_costs', $updated_meta );
2371
-
2372
- $this->sync_resource_costs_with_translations( $post_id, '_resource_block_costs' );
2373
-
2374
- return true;
2375
- }
2376
-
2377
  public function extra_conditions_to_filter_bookings( $extra_conditions ) {
2378
 
2379
  if ( isset( $_GET['post_type'] ) && $_GET['post_type'] == 'wc_booking' && ! isset( $_GET['post_status'] ) ) {
@@ -2391,6 +1437,7 @@ class WCML_Bookings {
2391
  public function show_pointer_info() {
2392
 
2393
  $pointer_ui = new WCML_Pointer_UI(
 
2394
  sprintf( __( 'You can translate the titles of your custom Resources on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
2395
  WCML_Tracking_Link::getWcmlBookingsDoc(),
2396
  'bookings_resources .woocommerce_bookable_resources #message'
@@ -2399,6 +1446,7 @@ class WCML_Bookings {
2399
  $pointer_ui->show();
2400
 
2401
  $pointer_ui = new WCML_Pointer_UI(
 
2402
  sprintf( __( 'You can translate the Person Type Name and Description on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
2403
  WCML_Tracking_Link::getWcmlBookingsDoc(),
2404
  'bookings_persons #persons-types>div.toolbar'
@@ -2726,8 +1774,24 @@ class WCML_Bookings {
2726
  }
2727
 
2728
  public function save_booking_data_to_translation( $post_id, $data, $job ){
2729
- $this->save_person_translation( $post_id, $data, $job );
2730
- $this->save_resource_translation( $post_id, $data, $job );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2731
  }
2732
 
2733
  /**
1
  <?php
2
 
3
  use WPML\FP\Maybe;
4
+ use WPML\FP\Str;
5
  use function WPML\FP\invoke;
6
  use function WPML\FP\pipe;
7
 
8
  /**
9
  * Class WCML_Bookings.
10
  */
11
+ class WCML_Bookings implements \IWPML_Action {
12
 
13
  const DOMAIN = 'woocommerce-bookings';
14
 
15
+ const PRIORITY_SAVE_POST_ACTION = 110;
16
+
17
  /**
18
  * @var WPML_Element_Translation_Package
19
  */
79
  add_filter( 'woocommerce_booking_reminder_notification', [ $this, 'translate_notification' ], 9 );
80
  add_filter( 'woocommerce_booking_cancelled_notification', [ $this, 'translate_notification' ], 9 );
81
 
82
+ add_action( 'save_post', [ $this, 'save_booking_action_handler' ], self::PRIORITY_SAVE_POST_ACTION );
83
+ add_action( 'wcml_bookings_resource_costs_updated', [ $this, 'sync_resource_costs_with_translations' ], 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
  add_action( 'wcml_before_sync_product_data', [ $this, 'sync_bookings' ], 10, 3 );
86
  add_action( 'wcml_before_sync_product', [ $this, 'sync_booking_data' ], 10, 2 );
87
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  add_filter(
89
  'wcml_cart_contents_not_changed',
90
  [
95
  3
96
  );
97
 
98
+ add_action( 'woocommerce_bookings_create_booking_page_add_order_item', [ $this, 'set_order_language_on_create_booking_page' ] );
 
99
 
 
 
 
 
 
 
 
 
 
100
  add_filter( 'get_booking_products_args', [ $this, 'filter_get_booking_products_args' ] );
 
 
 
101
 
102
  add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
103
  add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
134
  add_action( 'before_delete_post', [ $this, 'delete_bookings' ] );
135
  add_action( 'wp_trash_post', [ $this, 'trash_bookings' ] );
136
  add_action( 'wpml_translation_job_saved', [ $this, 'save_booking_data_to_translation' ], 10, 3 );
137
+ add_action( 'wpml_pro_translation_completed', [ $this, 'synchronize_bookings_on_translation_completed' ], 10, 3 );
138
 
139
  if ( is_admin() ) {
140
 
201
  }
202
  }
203
 
 
 
 
 
204
  add_filter( 'wpml_language_filter_extra_conditions_snippet', [ $this, 'extra_conditions_to_filter_bookings' ] );
205
 
 
 
206
  add_filter( 'wpml_tm_dashboard_translatable_types', [ $this, 'hide_bookings_type_on_tm_dashboard' ] );
207
 
208
  add_filter( 'wcml_add_to_cart_sold_individually', [ $this, 'add_to_cart_sold_individually' ], 10, 4 );
263
 
264
  $this->maybe_set_booking_language( $booking_id );
265
 
 
 
266
  $this->maybe_sync_updated_booking_meta( $booking_id );
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  // sync existing product bookings for translations.
270
  public function sync_bookings( $original_product_id, $product_id, $language ) {
271
  $all_bookings_for_product = $this->wpdb->get_results( $this->wpdb->prepare( "SELECT post_id as id FROM {$this->wpdb->postmeta} WHERE meta_key = '_booking_product_id' AND meta_value = %d", $original_product_id ) );
521
  return $new_person_id;
522
  }
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  public function sync_resource_costs_with_translations( $object_id, $meta_key, $check = false ) {
525
 
526
  $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
585
 
586
  }
587
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588
  public function localize_lock_fields_js() {
589
  wp_localize_script( 'wcml-bookings-js', 'lock_settings', [ 'lock_fields' => 1 ] );
590
  }
591
 
 
 
 
 
 
 
 
592
  public function filter_bundled_product_in_cart_contents( $cart_item, $key, $current_language ) {
593
 
594
  if ( $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['booking'] ) ) {
653
  return $cost;
654
  }
655
 
656
+ public function set_order_language_on_create_booking_page( $order_id ) {
657
+ update_post_meta( $order_id, 'wpml_language', $this->sitepress->get_current_language() );
658
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
659
 
660
  public function filter_get_booking_products_args( $args ) {
661
  if ( isset( $args['suppress_filters'] ) ) {
1134
 
1135
  }
1136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1137
  public function delete_bookings( $booking_id ) {
1138
 
1139
  if (
1221
  private function save_person_translation( $post_id, $data, $job ) {
1222
  $person_translations = [];
1223
 
1224
+ foreach ( $data as $value ) {
1225
 
1226
+ if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:person:' ) === 0 ) {
1227
 
1228
+ $exp = explode( ':', $value['field_type'] );
1229
 
1230
+ $person_id = $exp[2];
1231
+ $field = $exp[3];
1232
 
1233
+ $person_translations[ $person_id ][ $field ] = $value['data'];
 
1234
 
1235
+ }
1236
+ }
 
 
1237
 
1238
+ if ( $person_translations ) {
1239
 
1240
+ foreach ( $person_translations as $person_id => $pt ) {
1241
 
1242
+ $person_trid = $this->sitepress->get_element_trid( $person_id, 'post_bookable_person' );
1243
 
1244
+ $person_id_translated = apply_filters( 'translate_object_id', $person_id, 'bookable_person', false, $job->language_code );
1245
 
1246
+ if ( empty( $person_id_translated ) ) {
1247
 
1248
+ $person_post = [
1249
 
1250
+ 'post_type' => 'bookable_person',
1251
+ 'post_status' => 'publish',
1252
+ 'post_title' => $pt['name'],
1253
+ 'post_parent' => $post_id,
1254
+ 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '',
1255
 
1256
+ ];
1257
 
1258
+ $person_id_translated = wp_insert_post( $person_post );
1259
 
1260
+ $this->sitepress->set_element_language_details( $person_id_translated, 'post_bookable_person', $person_trid, $job->language_code );
1261
 
1262
+ } else {
1263
 
1264
+ $person_post = [
1265
+ 'ID' => $person_id_translated,
1266
+ 'post_title' => $pt['name'],
1267
+ 'post_excerpt' => isset( $pt['description'] ) ? $pt['description'] : '',
1268
+ ];
1269
 
1270
+ wp_update_post( $person_post );
 
 
 
 
 
1271
 
1272
+ }
1273
+ }
1274
+ }
1275
  }
1276
 
1277
  public function append_resources_to_translation_package( $package, $post ) {
1301
  private function save_resource_translation( $post_id, $data, $job ) {
1302
  $resource_translations = [];
1303
 
1304
+ foreach ( $data as $value ) {
 
 
 
 
1305
 
1306
+ if ( $value['finished'] && strpos( $value['field_type'], 'wc_bookings:resource:' ) === 0 ) {
1307
 
1308
+ $exp = explode( ':', $value['field_type'] );
 
1309
 
1310
+ $resource_id = $exp[2];
1311
+ $field = $exp[3];
1312
 
1313
+ $resource_translations[ $resource_id ][ $field ] = $value['data'];
 
1314
 
1315
+ }
1316
+ }
1317
 
1318
+ if ( $resource_translations ) {
1319
 
1320
+ foreach ( $resource_translations as $resource_id => $rt ) {
1321
 
1322
+ $resource_trid = $this->sitepress->get_element_trid( $resource_id, 'post_bookable_resource' );
1323
 
1324
+ $resource_id_translated = apply_filters( 'translate_object_id', $resource_id, 'bookable_resource', false, $job->language_code );
1325
 
1326
+ if ( empty( $resource_id_translated ) ) {
1327
 
1328
+ $resource_post = [
 
 
 
 
1329
 
1330
+ 'post_type' => 'bookable_resource',
1331
+ 'post_status' => 'publish',
1332
+ 'post_title' => $rt['name'],
1333
+ 'post_parent' => $post_id,
1334
+ ];
1335
 
1336
+ $resource_id_translated = wp_insert_post( $resource_post );
1337
 
1338
+ $this->sitepress->set_element_language_details( $resource_id_translated, 'post_bookable_resource', $resource_trid, $job->language_code );
 
 
 
 
 
 
1339
 
1340
+ $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) );
1341
+ $relationship = [
1342
+ 'product_id' => $post_id,
1343
+ 'resource_id' => $resource_id_translated,
1344
+ 'sort_order' => $sort_order,
1345
+ ];
1346
+ $this->wpdb->insert( $this->wpdb->prefix . 'wc_booking_relationships', $relationship );
1347
 
1348
+ } else {
 
 
 
1349
 
1350
+ $resource_post = [
1351
+ 'ID' => $resource_id_translated,
1352
+ 'post_title' => $rt['name'],
1353
+ ];
1354
 
1355
+ wp_update_post( $resource_post );
 
 
 
 
 
 
 
 
1356
 
1357
+ $sort_order = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT sort_order FROM {$this->wpdb->prefix}wc_booking_relationships WHERE resource_id=%d", $resource_id ) );
1358
+ $this->wpdb->update(
1359
+ $this->wpdb->prefix . 'wc_booking_relationships',
1360
+ [ 'sort_order' => $sort_order ],
1361
+ [
1362
+ 'product_id' => $post_id,
1363
+ 'resource_id' => $resource_id_translated,
1364
+ ]
1365
+ );
1366
 
1367
+ }
1368
+ }
1369
+ }
1370
  }
1371
 
1372
  public function wcml_js_lock_fields_ids( $ids ) {
1420
 
1421
  }
1422
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1423
  public function extra_conditions_to_filter_bookings( $extra_conditions ) {
1424
 
1425
  if ( isset( $_GET['post_type'] ) && $_GET['post_type'] == 'wc_booking' && ! isset( $_GET['post_status'] ) ) {
1437
  public function show_pointer_info() {
1438
 
1439
  $pointer_ui = new WCML_Pointer_UI(
1440
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
1441
  sprintf( __( 'You can translate the titles of your custom Resources on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
1442
  WCML_Tracking_Link::getWcmlBookingsDoc(),
1443
  'bookings_resources .woocommerce_bookable_resources #message'
1446
  $pointer_ui->show();
1447
 
1448
  $pointer_ui = new WCML_Pointer_UI(
1449
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
1450
  sprintf( __( 'You can translate the Person Type Name and Description on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
1451
  WCML_Tracking_Link::getWcmlBookingsDoc(),
1452
  'bookings_persons #persons-types>div.toolbar'
1774
  }
1775
 
1776
  public function save_booking_data_to_translation( $post_id, $data, $job ){
1777
+ if ( $this->is_booking( $job->original_doc_id ) ) {
1778
+ $this->save_person_translation( $post_id, $data, $job );
1779
+ $this->save_resource_translation( $post_id, $data, $job );
1780
+ }
1781
+ }
1782
+
1783
+ /**
1784
+ * @param int $new_post_id
1785
+ * @param array $fields
1786
+ * @param \stdClass $job
1787
+ */
1788
+ public function synchronize_bookings_on_translation_completed( $new_post_id, $fields, $job ) {
1789
+ if (
1790
+ Str::startsWith( 'post_', $job->original_post_type )
1791
+ && $this->is_booking( $job->original_doc_id )
1792
+ ) {
1793
+ $this->woocommerce_wpml->sync_product_data->synchronize_products( $new_post_id, get_post( $new_post_id ), true );
1794
+ }
1795
  }
1796
 
1797
  /**
compatibility/WcBulkStockManagement/Factory.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcBulkStockManagement;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Bulk_Stock_Management;
7
+
8
+ /**
9
+ * @see http://www.woothemes.com/products/bulk-stock-management/
10
+ */
11
+ class Factory extends ComponentFactory {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ return new WCML_Bulk_Stock_Management();
18
+ }
19
+ }
compatibility/{class-wcml-bulk-stock-management.php → WcBulkStockManagement/class-wcml-bulk-stock-management.php} RENAMED
@@ -5,8 +5,9 @@
5
  *
6
  * @author konrad
7
  */
8
- class WCML_Bulk_Stock_Management {
9
- public function __construct() {
 
10
  if ( is_admin() && isset( $_GET['page'] ) && $_GET['page'] == 'woocommerce-bulk-stock-management' ) {
11
  global $sitepress;
12
  remove_action( 'admin_enqueue_scripts', [ $sitepress, 'language_filter' ] );
5
  *
6
  * @author konrad
7
  */
8
+ class WCML_Bulk_Stock_Management implements \IWPML_Action {
9
+
10
+ public function add_hooks() {
11
  if ( is_admin() && isset( $_GET['page'] ) && $_GET['page'] == 'woocommerce-bulk-stock-management' ) {
12
  global $sitepress;
13
  remove_action( 'admin_enqueue_scripts', [ $sitepress, 'language_filter' ] );
compatibility/WcCheckoutAddons/Factory.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCheckoutAddons;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_Checkout_Addons;
8
+ use function WCML\functions\isStandAlone;
9
+
10
+ /**
11
+ * @see http://www.woocommerce.com/products/woocommerce-checkout-add-ons/
12
+ */
13
+ class Factory extends ComponentFactory implements IStandAloneAction {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ $hooks = [];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks();
23
+ }
24
+
25
+ if ( ! isStandAlone() ) {
26
+ $hooks[] = new WCML_Checkout_Addons();
27
+ }
28
+
29
+ return $hooks;
30
+ }
31
+ }
compatibility/WcCheckoutAddons/MulticurrencyHooks.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCheckoutAddons;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'option_wc_checkout_add_ons', [ $this, 'optionWcCheckoutAddOnsFilter' ] );
9
+ }
10
+
11
+ /**
12
+ * @param array|mixed $optionValue
13
+ *
14
+ * @return array|mixed
15
+ */
16
+ public function optionWcCheckoutAddOnsFilter( $optionValue ) {
17
+ $convertPrice = function( $index, $conf ) {
18
+ if (
19
+ isset( $conf['adjustment'], $conf['adjustment_type'] )
20
+ && 'fixed' === $conf['adjustment_type']
21
+ ) {
22
+ $conf['adjustment'] = apply_filters( 'wcml_raw_price_amount', $conf['adjustment'] );
23
+ }
24
+
25
+ return $conf;
26
+ };
27
+
28
+ return OptionIterator::apply( $convertPrice, $optionValue );
29
+ }
30
+ }
compatibility/WcCheckoutAddons/OptionIterator.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCheckoutAddons;
4
+
5
+ class OptionIterator {
6
+
7
+ /**
8
+ * @param callable $handler
9
+ * @param array|mixed $optionValue
10
+ *
11
+ * @return array|mixed
12
+ */
13
+ public static function apply( callable $handler, $optionValue ) {
14
+ if ( is_array( $optionValue ) ) {
15
+
16
+ foreach ( $optionValue as $addonId => $addonConf ) {
17
+ $addonConf = $handler( $addonId, $addonConf );
18
+
19
+ if ( isset( $addonConf['options'] ) ) {
20
+ foreach ( $addonConf['options'] as $index => $fields ) {
21
+ $addonConf['options'][ $index ] = $handler( $index, $fields );
22
+ }
23
+ }
24
+
25
+ $optionValue[ $addonId ] = $addonConf;
26
+ }
27
+ }
28
+
29
+ return $optionValue;
30
+ }
31
+ }
compatibility/WcCheckoutAddons/class-wcml-checkout-addons.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WCML\Compatibility\WcCheckoutAddons\OptionIterator;
4
+
5
+ /**
6
+ * Compatibility class for wc_checkout_addons plugin.
7
+ *
8
+ * @author konrad
9
+ */
10
+ class WCML_Checkout_Addons implements \IWPML_Action {
11
+
12
+ public function add_hooks() {
13
+ add_filter( 'option_wc_checkout_add_ons', [ $this, 'option_wc_checkout_add_ons' ] );
14
+ }
15
+
16
+ /**
17
+ * @param array|mixed $option_value
18
+ *
19
+ * @return array|mixed
20
+ */
21
+ public function option_wc_checkout_add_ons( $option_value ) {
22
+ return OptionIterator::apply( [ $this, 'handle_option_part' ], $option_value );
23
+ }
24
+
25
+ public function handle_option_part( $index, $conf ) {
26
+ $conf = $this->register_or_translate( 'label', $conf, $index );
27
+ $conf = $this->register_or_translate( 'description', $conf, $index );
28
+ return $conf;
29
+ }
30
+
31
+ private function register_or_translate( $element, $conf, $index ) {
32
+ if ( isset( $conf[ $element ] ) ) {
33
+ $string = $conf[ $element ];
34
+ $key = $index . '_' . $element . '_' . md5( $string );
35
+ if ( $this->is_default_language() ) {
36
+ do_action( 'wpml_register_single_string', 'wc_checkout_addons', $key, $string );
37
+ } else {
38
+ $conf[ $element ] = apply_filters( 'wpml_translate_single_string', $string, 'wc_checkout_addons', $key );
39
+ }
40
+ }
41
+ return $conf;
42
+ }
43
+
44
+ private function is_default_language() {
45
+ return apply_filters( 'wpml_current_language', null ) === apply_filters( 'wpml_default_language', null );
46
+ }
47
+ }
compatibility/WcCheckoutFieldEditor/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCheckoutFieldEditor;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Checkout_Field_Editor;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Checkout_Field_Editor();
15
+ }
16
+ }
compatibility/{class-wcml-checkout-field-editor.php → WcCheckoutFieldEditor/class-wcml-checkout-field-editor.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_Checkout_Field_Editor {
4
 
5
  protected $package, $billing, $shipping, $additional;
6
 
1
  <?php
2
 
3
+ class WCML_Checkout_Field_Editor implements \IWPML_Action {
4
 
5
  protected $package, $billing, $shipping, $additional;
6
 
compatibility/WcCompositeProducts/Factory.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCompositeProducts;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_Composite_Products;
8
+ use function WCML\functions\getSitePress;
9
+ use function WCML\functions\getWooCommerceWpml;
10
+ use function WCML\functions\isStandAlone;
11
+
12
+ /**
13
+ * @see https://woocommerce.com/products/composite-products/
14
+ */
15
+ class Factory extends ComponentFactory implements IStandAloneAction {
16
+
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ public function create() {
21
+ $hooks = [];
22
+
23
+ if ( wcml_is_multi_currency_on() ) {
24
+ $hooks[] = new MulticurrencyHooks( getWooCommerceWpml() );
25
+ }
26
+
27
+ if ( ! isStandAlone() ) {
28
+ $hooks[] = new WCML_Composite_Products( getSitePress() );
29
+ }
30
+
31
+ return $hooks;
32
+ }
33
+ }
compatibility/WcCompositeProducts/MulticurrencyHooks.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcCompositeProducts;
4
+
5
+ use WCML_Compatibility_Helper;
6
+
7
+ class MulticurrencyHooks implements \IWPML_Action {
8
+
9
+ const PRICE_FILTERS_PRIORITY_AFTER_COMPOSITE = 99;
10
+
11
+ /** @var \woocommerce_wpml $woocommerce_wpml */
12
+ private $woocommerce_wpml;
13
+
14
+ public function __construct( \woocommerce_wpml $woocommerce_wpml ) {
15
+ $this->woocommerce_wpml = $woocommerce_wpml;
16
+ }
17
+
18
+ public function add_hooks() {
19
+ if ( is_admin() ) {
20
+ add_action( 'wcml_after_save_custom_prices', [ $this, 'update_composite_custom_prices' ], 10, 4 );
21
+ } else {
22
+ add_filter( 'get_post_metadata', [ $this, 'filter_composite_product_cost' ], 10, 3 );
23
+ $this->add_price_rounding_filters();
24
+ }
25
+ }
26
+
27
+ /**
28
+ * @param int|string $productId
29
+ * @param string|float|int $productPrice
30
+ * @param array $customPrices
31
+ * @param string $code
32
+ *
33
+ * @return void
34
+ */
35
+ public function update_composite_custom_prices( $productId, $productPrice, $customPrices, $code ){
36
+ if( WCML_Compatibility_Helper::get_product_type( $productId ) === 'composite' ) {
37
+ update_post_meta( $productId, '_bto_base_regular_price' . '_' . $code, $customPrices['_regular_price' ] );
38
+ update_post_meta( $productId, '_bto_base_sale_price' . '_' . $code, $customPrices['_sale_price' ] );
39
+ update_post_meta( $productId, '_bto_base_price' . '_' . $code, $productPrice );
40
+ }
41
+ }
42
+
43
+ /**
44
+ * @param mixed $value
45
+ * @param int $objectId
46
+ * @param string $metaKey
47
+ *
48
+ * @return mixed
49
+ */
50
+ public function filter_composite_product_cost( $value, $objectId, $metaKey ) {
51
+ if ( in_array( $metaKey, [
52
+ '_bto_base_regular_price',
53
+ '_bto_base_sale_price',
54
+ '_bto_base_price'
55
+ ] ) ) {
56
+ $original_id = $this->woocommerce_wpml->products->get_original_product_id( $objectId );
57
+
58
+ $cost_status = get_post_meta( $original_id, '_wcml_custom_prices_status', true );
59
+
60
+ $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
61
+
62
+ if ( $currency === wcml_get_woocommerce_currency_option() ) {
63
+ return $value;
64
+ }
65
+
66
+ $cost = get_post_meta( $original_id, $metaKey . '_' . $currency, true );
67
+
68
+ if ( $cost_status && ! empty( $cost ) ) {
69
+ return $cost;
70
+ } else {
71
+ remove_filter( 'get_post_metadata', [ $this, 'filter_composite_product_cost' ], 10 );
72
+
73
+ $cost = get_post_meta( $original_id, $metaKey, true );
74
+
75
+ add_filter( 'get_post_metadata', [ $this, 'filter_composite_product_cost' ], 10, 4 );
76
+
77
+ if ( $cost ){
78
+ return $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
79
+ }
80
+ }
81
+ }
82
+
83
+ return $value;
84
+ }
85
+
86
+ public function add_price_rounding_filters() {
87
+ $filters = [
88
+ 'woocommerce_product_get_price',
89
+ 'woocommerce_product_get_sale_price',
90
+ 'woocommerce_product_get_regular_price',
91
+ 'woocommerce_product_variation_get_price',
92
+ 'woocommerce_product_variation_get_sale_price',
93
+ 'woocommerce_product_variation_get_regular_price'
94
+ ];
95
+
96
+ foreach( $filters as $filter ){
97
+ add_filter( $filter, [ $this, 'apply_rounding_rules' ], self::PRICE_FILTERS_PRIORITY_AFTER_COMPOSITE );
98
+ }
99
+ }
100
+
101
+ /**
102
+ * @param int|float|string $price
103
+ *
104
+ * @return int|float|string
105
+ */
106
+ public function apply_rounding_rules( $price ) {
107
+ if ( $price && is_composite_product() ) {
108
+ $current_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
109
+
110
+ if ( $current_currency !== wcml_get_woocommerce_currency_option() ) {
111
+ $price = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $price, $current_currency );
112
+ }
113
+ }
114
+
115
+ return $price;
116
+ }
117
+ }
compatibility/{class-wcml-composite-products.php → WcCompositeProducts/class-wcml-composite-products.php} RENAMED
@@ -1,38 +1,22 @@
1
  <?php
2
 
 
3
  use WPML\FP\Fns;
4
  use WPML\FP\Obj;
 
5
 
6
- use function WPML\FP\partial;
7
- use function WPML\FP\pipe;
8
 
9
- class WCML_Composite_Products extends WCML_Compatibility_Helper{
10
-
11
- const PRICE_FILTERS_PRIORITY_AFTER_COMPOSITE = 99;
12
 
13
  /**
14
  * @var SitePress
15
  */
16
  private $sitepress;
17
- /**
18
- * @var woocommerce_wpml
19
- */
20
- private $woocommerce_wpml;
21
- /**
22
- * @var WPML_Element_Translation_Package
23
- */
24
- private $tp;
25
 
26
- /**
27
- * WCML_Composite_Products constructor.
28
- * @param SitePress $sitepress
29
- * @param woocommerce_wpml $woocommerce_wpml
30
- * @param WPML_Element_Translation_Package $tp
31
- */
32
- public function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, WPML_Element_Translation_Package $tp ) {
33
- $this->sitepress = $sitepress;
34
- $this->woocommerce_wpml = $woocommerce_wpml;
35
- $this->tp = $tp;
36
  }
37
 
38
  public function add_hooks(){
@@ -42,11 +26,15 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
42
  add_filter( 'woocommerce_composite_component_options_query_args', array($this, 'wpml_composites_transients_cache_per_language'), 10, 3 );
43
  add_action( 'wcml_before_sync_product_data', array( $this, 'sync_composite_data_across_translations' ), 10, 2 );
44
  add_action( 'wpml_translation_job_saved', array( $this, 'save_composite_data_translation' ), 10, 3 );
 
45
  if( is_admin() ){
46
 
47
- add_action( 'wcml_gui_additional_box_html', array( $this, 'custom_box_html' ), 10, 3 );
48
- add_filter( 'wcml_gui_additional_box_data', array( $this, 'custom_box_html_data' ), 10, 4 );
49
- add_action( 'wcml_update_extra_fields', array( $this, 'update_component_strings' ), 10, 4 );
 
 
 
50
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'woocommerce_json_search_found_products' ) );
51
 
52
  add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_composite_data_translation_package' ), 10, 2 );
@@ -57,32 +45,11 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
57
  add_filter( 'wcml_after_load_lock_fields_js', array( $this, 'localize_lock_fields_js' ) );
58
  add_action( 'init', array( $this, 'load_assets' ) );
59
 
60
- add_action( 'wcml_after_save_custom_prices', array( $this, 'update_composite_custom_prices' ), 10, 4 );
61
-
62
  add_filter( 'wcml_do_not_display_custom_fields_for_product', array( $this, 'replace_tm_editor_custom_fields_with_own_sections' ) );
63
- }else{
64
- add_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10, 4 );
65
- $this->add_price_rounding_filters();
66
  }
67
 
68
  }
69
 
70
- public function add_price_rounding_filters(){
71
-
72
- $filters = array(
73
- 'woocommerce_product_get_price',
74
- 'woocommerce_product_get_sale_price',
75
- 'woocommerce_product_get_regular_price',
76
- 'woocommerce_product_variation_get_price',
77
- 'woocommerce_product_variation_get_sale_price',
78
- 'woocommerce_product_variation_get_regular_price'
79
- );
80
-
81
- foreach( $filters as $filter ){
82
- add_filter( $filter, array( $this, 'apply_rounding_rules' ), self::PRICE_FILTERS_PRIORITY_AFTER_COMPOSITE );
83
- }
84
- }
85
-
86
  public function woocommerce_composite_component_default_option($selected_value, $component_id, $object) {
87
 
88
  if( !empty( $selected_value ) )
@@ -166,7 +133,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
166
 
167
  }
168
 
169
- update_post_meta( $product_translation->element_id, '_bto_data', $composite_data );
170
 
171
  if ( $composite_scenarios_meta ) {
172
  // sync product ids
@@ -185,7 +152,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
185
  ->map( Obj::over( Obj::lensPath( [ 'scenario_actions', 'conditional_options', 'component_data' ] ), $translate_product_ids ) )
186
  ->toArray();
187
 
188
- update_post_meta( $product_translation->element_id, '_bto_scenario_data', $composite_scenarios_meta );
189
  }
190
  }
191
  }
@@ -193,6 +160,13 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
193
  }
194
  }
195
 
 
 
 
 
 
 
 
196
  public function custom_box_html( $obj, $product_id, $data ){
197
 
198
  if( $this->get_product_type( $product_id ) == 'composite' ){
@@ -248,6 +222,16 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
248
 
249
  }
250
 
 
 
 
 
 
 
 
 
 
 
251
  public function custom_box_html_data( $data, $product_id, $translation, $lang ){
252
 
253
  if( $this->get_product_type( $product_id ) == 'composite' ){
@@ -310,7 +294,16 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
310
  return $data;
311
  }
312
 
313
-
 
 
 
 
 
 
 
 
 
314
  public function update_component_strings( $original_product_id, $product_id, $data, $language ){
315
 
316
  $composite_data = $this->get_composite_data( $product_id );
@@ -327,7 +320,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
327
 
328
  }
329
 
330
- update_post_meta( $product_id, '_bto_data', $composite_data );
331
 
332
  $composite_scenarios_meta = $this->get_composite_scenarios_meta( $product_id );
333
  if( $composite_scenarios_meta ){
@@ -342,7 +335,7 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
342
  }
343
  }
344
 
345
- update_post_meta( $product_id, '_bto_scenario_data', $composite_scenarios_meta );
346
 
347
  return array(
348
  'components' => $composite_data,
@@ -350,92 +343,117 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
350
  );
351
  }
352
 
 
 
 
 
 
 
353
  public function append_composite_data_translation_package( $package, $post ){
354
-
355
- if( $post->post_type == 'product' ) {
356
-
357
- $composite_data = get_post_meta( $post->ID, '_bto_data', true );
358
-
359
- if( $composite_data ){
360
-
361
- $fields = array( 'title', 'description' );
362
-
363
- foreach( $composite_data as $component_id => $component ){
364
-
365
- foreach( $fields as $field ) {
366
- if ( !empty($component[$field]) ) {
367
-
368
- $package['contents']['wc_composite:' . $component_id . ':' . $field] = array(
369
- 'translate' => 1,
370
- 'data' => $this->tp->encode_field_data( $component[$field], 'base64' ),
371
- 'format' => 'base64'
372
- );
373
-
374
  }
375
  }
376
-
377
  }
 
378
 
379
- }
380
-
381
  }
382
 
383
  return $package;
 
384
 
 
 
 
 
 
 
 
 
 
 
385
  }
386
 
 
 
 
 
 
387
  public function save_composite_data_translation( $post_id, $data, $job ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
 
 
 
389
 
390
- $translated_composite_data = array();
391
- foreach( $data as $value){
392
-
393
- if( preg_match( '/wc_composite:([0-9]+):(.+)/', $value['field_type'], $matches ) ){
394
-
395
- $component_id = $matches[1];
396
- $field = $matches[2];
397
-
398
- $translated_composite_data[$component_id][$field] = $value['data'];
399
-
400
- }
401
-
402
- }
403
-
404
- if( $translated_composite_data ){
405
-
406
- $composite_data = get_post_meta( $job->original_doc_id, '_bto_data', true );
407
-
408
-
409
- foreach ( $composite_data as $component_id => $component ) {
410
-
411
- if( isset( $translated_composite_data[$component_id]['title'] ) ){
412
- $composite_data[$component_id]['title'] = $translated_composite_data[$component_id]['title'];
413
- }
414
-
415
- if( isset( $translated_composite_data[$component_id]['description'] ) ){
416
- $composite_data[$component_id]['description'] = $translated_composite_data[$component_id]['description'];
417
- }
418
 
419
- if ( $component['query_type'] == 'product_ids' ) {
 
 
 
 
 
 
420
 
421
- foreach ( $component['assigned_ids'] as $idx => $assigned_id ) {
422
- $composite_data[$component_id]['assigned_ids'][$idx] =
423
- apply_filters( 'wpml_object_id', $assigned_id, 'product', true, $job->language_code );
 
 
424
  }
425
 
426
- } elseif( $component['query_type'] == 'category_ids' ){
427
-
428
- foreach ( $component['assigned_category_ids'] as $idx => $assigned_id ) {
429
- $composite_data[$component_id]['assigned_category_ids'][$idx] =
430
- apply_filters( 'wpml_object_id', $assigned_id, 'product_cat', true, $job->language_code );
431
 
432
- }
433
-
434
- }
 
 
435
 
 
 
 
 
 
436
  }
437
-
438
- update_post_meta( $post_id, '_bto_data', $composite_data );
439
  }
440
  }
441
 
@@ -494,93 +512,17 @@ class WCML_Composite_Products extends WCML_Compatibility_Helper{
494
  }
495
 
496
  public function get_composite_scenarios_meta( $product_id ){
497
- return get_post_meta( $product_id, '_bto_scenario_data', true );
498
  }
499
 
500
  public function get_composite_data( $product_id ){
501
- return get_post_meta( $product_id, '_bto_data', true ) ?: [];
502
- }
503
-
504
-
505
- public function filter_composite_product_cost( $value, $object_id, $meta_key, $single ) {
506
-
507
- if ( in_array( $meta_key, array(
508
- '_bto_base_regular_price',
509
- '_bto_base_sale_price',
510
- '_bto_base_price'
511
- ) ) ) {
512
-
513
- if ( $this->woocommerce_wpml->settings['enable_multi_currency'] == WCML_MULTI_CURRENCIES_INDEPENDENT ) {
514
-
515
- $original_id = $this->woocommerce_wpml->products->get_original_product_id( $object_id );
516
-
517
- $cost_status = get_post_meta( $original_id, '_wcml_custom_prices_status', true );
518
-
519
- $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
520
-
521
- if ( $currency === wcml_get_woocommerce_currency_option() ) {
522
- return $value;
523
- }
524
-
525
- $cost = get_post_meta( $original_id, $meta_key . '_' . $currency, true );
526
-
527
- if ( $cost_status && !empty( $cost ) ) {
528
-
529
- return $cost;
530
-
531
- } else {
532
-
533
- remove_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10 );
534
-
535
- $cost = get_post_meta( $original_id, $meta_key, true );
536
-
537
- add_filter( 'get_post_metadata', array( $this, 'filter_composite_product_cost' ), 10, 4 );
538
-
539
- if( $cost ){
540
-
541
- $cost = $this->woocommerce_wpml->multi_currency->prices->convert_price_amount( $cost, $currency );
542
-
543
- return $cost;
544
- }
545
-
546
- }
547
-
548
- }
549
-
550
- }
551
-
552
- return $value;
553
- }
554
-
555
- public function update_composite_custom_prices( $product_id, $product_price, $custom_prices, $code ){
556
-
557
- if( $this->get_product_type( $product_id ) == 'composite' ){
558
-
559
- update_post_meta( $product_id, '_bto_base_regular_price'.'_'.$code, $custom_prices[ '_regular_price' ] );
560
- update_post_meta( $product_id, '_bto_base_sale_price'.'_'.$code, $custom_prices[ '_sale_price' ] );
561
- update_post_meta( $product_id, '_bto_base_price'.'_'.$code, $product_price );
562
-
563
- }
564
-
565
  }
566
 
567
  public function replace_tm_editor_custom_fields_with_own_sections( $fields ){
568
- $fields[] = '_bto_data';
569
- $fields[] = '_bto_scenario_data';
570
 
571
  return $fields;
572
  }
573
-
574
- public function apply_rounding_rules( $price ) {
575
-
576
- if ( $price && is_composite_product() && wcml_is_multi_currency_on() ) {
577
- $current_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
578
- if( $current_currency !== wcml_get_woocommerce_currency_option() ) {
579
- $price = $this->woocommerce_wpml->multi_currency->prices->apply_rounding_rules( $price, $current_currency );
580
- }
581
- }
582
-
583
- return $price;
584
- }
585
-
586
  }
1
  <?php
2
 
3
+ use WCML\Options\WPML;
4
  use WPML\FP\Fns;
5
  use WPML\FP\Obj;
6
+ use WPML\FP\Str;
7
 
8
+ class WCML_Composite_Products extends WCML_Compatibility_Helper implements \IWPML_Action {
 
9
 
10
+ const META_KEY_DATA = '_bto_data';
11
+ const META_KEY_SCENARIO = '_bto_scenario_data';
 
12
 
13
  /**
14
  * @var SitePress
15
  */
16
  private $sitepress;
 
 
 
 
 
 
 
 
17
 
18
+ public function __construct( SitePress $sitepress ) {
19
+ $this->sitepress = $sitepress;
 
 
 
 
 
 
 
 
20
  }
21
 
22
  public function add_hooks(){
26
  add_filter( 'woocommerce_composite_component_options_query_args', array($this, 'wpml_composites_transients_cache_per_language'), 10, 3 );
27
  add_action( 'wcml_before_sync_product_data', array( $this, 'sync_composite_data_across_translations' ), 10, 2 );
28
  add_action( 'wpml_translation_job_saved', array( $this, 'save_composite_data_translation' ), 10, 3 );
29
+
30
  if( is_admin() ){
31
 
32
+ if ( ! WPML::useAte() ) { // Legacy actions/filters for CTE
33
+ add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
34
+ add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
35
+ add_action( 'wcml_update_extra_fields', [ $this, 'update_component_strings' ], 10, 4 );
36
+ }
37
+
38
  add_filter( 'woocommerce_json_search_found_products', array( $this, 'woocommerce_json_search_found_products' ) );
39
 
40
  add_filter( 'wpml_tm_translation_job_data', array( $this, 'append_composite_data_translation_package' ), 10, 2 );
45
  add_filter( 'wcml_after_load_lock_fields_js', array( $this, 'localize_lock_fields_js' ) );
46
  add_action( 'init', array( $this, 'load_assets' ) );
47
 
 
 
48
  add_filter( 'wcml_do_not_display_custom_fields_for_product', array( $this, 'replace_tm_editor_custom_fields_with_own_sections' ) );
 
 
 
49
  }
50
 
51
  }
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  public function woocommerce_composite_component_default_option($selected_value, $component_id, $object) {
54
 
55
  if( !empty( $selected_value ) )
133
 
134
  }
135
 
136
+ update_post_meta( $product_translation->element_id, self::META_KEY_DATA, $composite_data );
137
 
138
  if ( $composite_scenarios_meta ) {
139
  // sync product ids
152
  ->map( Obj::over( Obj::lensPath( [ 'scenario_actions', 'conditional_options', 'component_data' ] ), $translate_product_ids ) )
153
  ->toArray();
154
 
155
+ update_post_meta( $product_translation->element_id, self::META_KEY_SCENARIO, $composite_scenarios_meta );
156
  }
157
  }
158
  }
160
  }
161
  }
162
 
163
+ /**
164
+ * @deprecated This method is used by CTE only.
165
+ *
166
+ * @param object $obj
167
+ * @param string|int $product_id
168
+ * @param mixed $data
169
+ */
170
  public function custom_box_html( $obj, $product_id, $data ){
171
 
172
  if( $this->get_product_type( $product_id ) == 'composite' ){
222
 
223
  }
224
 
225
+ /**
226
+ * @deprecated This method is used by CTE only.
227
+ *
228
+ * @param array $data
229
+ * @param string|int $bundle_id
230
+ * @param object $translation
231
+ * @param string $lang
232
+ *
233
+ * @return array
234
+ */
235
  public function custom_box_html_data( $data, $product_id, $translation, $lang ){
236
 
237
  if( $this->get_product_type( $product_id ) == 'composite' ){
294
  return $data;
295
  }
296
 
297
+ /**
298
+ * @deprecated This method is used by CTE only.
299
+ *
300
+ * @param string|int $original_product_id
301
+ * @param string|int $product_id
302
+ * @param array $data
303
+ * @param string $language
304
+ *
305
+ * @return array
306
+ */
307
  public function update_component_strings( $original_product_id, $product_id, $data, $language ){
308
 
309
  $composite_data = $this->get_composite_data( $product_id );
320
 
321
  }
322
 
323
+ update_post_meta( $product_id, self::META_KEY_DATA, $composite_data );
324
 
325
  $composite_scenarios_meta = $this->get_composite_scenarios_meta( $product_id );
326
  if( $composite_scenarios_meta ){
335
  }
336
  }
337
 
338
+ update_post_meta( $product_id, self::META_KEY_SCENARIO, $composite_scenarios_meta );
339
 
340
  return array(
341
  'components' => $composite_data,
343
  );
344
  }
345
 
346
+ /**
347
+ * @param array $package
348
+ * @param \stdClass|\WP_Post $post
349
+ *
350
+ * @return array
351
+ */
352
  public function append_composite_data_translation_package( $package, $post ){
353
+ if( 'product' === $post->post_type ) {
354
+ // $add_titles_and_descriptions :: (array, string, array) -> void
355
+ $add_fields_to_package = function( $data, $fields, $subtype ) use ( &$package ) {
356
+ if ( $data ) {
357
+ foreach( $data as $key => $meta ){
358
+ foreach( $fields as $field ) {
359
+ if ( ! empty( $meta[ $field ] ) ) {
360
+ $package['contents'][ self::get_field_name( $key, $field, $subtype ) ] = [
361
+ 'translate' => 1,
362
+ 'data' => base64_encode( $meta[ $field ] ),
363
+ 'format' => 'base64',
364
+ ];
365
+ }
 
 
 
 
 
 
 
366
  }
367
  }
 
368
  }
369
+ };
370
 
371
+ $add_fields_to_package( $this->get_composite_data( $post->ID ), [ 'title', 'description' ], '' );
372
+ $add_fields_to_package( $this->get_composite_scenarios_meta( $post->ID ), [ 'title', 'description' ], 'scenario' );
373
  }
374
 
375
  return $package;
376
+ }
377
 
378
+ /**
379
+ * @param string $component_id
380
+ * @param string $field
381
+ * @param string $subtype
382
+ *
383
+ * @return string
384
+ */
385
+ private static function get_field_name( $component_id, $field, $subtype ) {
386
+ $subtype = $subtype ? $subtype . ':' : $subtype;
387
+ return 'wc_composite:' . $subtype . $component_id . ':' . $field;
388
  }
389
 
390
+ /**
391
+ * @param string|int $post_id
392
+ * @param array $data
393
+ * @param object $job
394
+ */
395
  public function save_composite_data_translation( $post_id, $data, $job ){
396
+ if (
397
+ Str::startsWith( 'post_', $job->original_post_type )
398
+ && 'product' === get_post_type( $job->original_doc_id )
399
+ ) {
400
+ $composite_data = $this->get_composite_data( $job->original_doc_id );
401
+
402
+ if ( $composite_data ) {
403
+ $get_translation = function ( $name ) use ( $data ) {
404
+ return Obj::path( [ $name, 'data' ], $data );
405
+ };
406
+
407
+ // $apply_translations :: (array, array, string) -> array
408
+ $apply_translations = function ( $data, $fields, $subtype ) use ( $get_translation ) {
409
+ foreach ( $data as $key => $meta ) {
410
+ foreach ( $fields as $field ) {
411
+ $translation = $get_translation( self::get_field_name( $key, $field, $subtype ) );
412
+
413
+ if ( $translation ) {
414
+ $data[ $key ][ $field ] = $translation;
415
+ }
416
+ }
417
+ }
418
 
419
+ return $data;
420
+ };
421
 
422
+ // $adjust_ids :: (array, string) -> array
423
+ $adjust_ids = function ( $data, $lang ) {
424
+ foreach ( $data as $key => $meta ) {
425
+ $ids_key = $cpt = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
 
427
+ if ( 'product_ids' === $meta['query_type'] ) {
428
+ $ids_key = 'assigned_ids';
429
+ $cpt = 'product';
430
+ } elseif ( 'category_ids' === $meta['query_type'] ) {
431
+ $ids_key = 'assigned_category_ids';
432
+ $cpt = 'product_cat';
433
+ }
434
 
435
+ if ( $ids_key && $cpt ) {
436
+ foreach ( $meta[ $ids_key ] as $idx => $assigned_id ) {
437
+ $data[ $key ][ $ids_key ][ $idx ] = apply_filters( 'wpml_object_id', $assigned_id, $cpt, true, $lang );
438
+ }
439
+ }
440
  }
441
 
442
+ return $data;
443
+ };
 
 
 
444
 
445
+ update_post_meta(
446
+ $post_id,
447
+ self::META_KEY_DATA,
448
+ $adjust_ids( $apply_translations( $composite_data, [ 'title', 'description' ], '' ), $job->language_code )
449
+ );
450
 
451
+ update_post_meta(
452
+ $post_id,
453
+ self::META_KEY_SCENARIO,
454
+ $apply_translations( $this->get_composite_scenarios_meta( $job->original_doc_id ), [ 'title', 'description' ], 'scenario' )
455
+ );
456
  }
 
 
457
  }
458
  }
459
 
512
  }
513
 
514
  public function get_composite_scenarios_meta( $product_id ){
515
+ return get_post_meta( $product_id, self::META_KEY_SCENARIO, true );
516
  }
517
 
518
  public function get_composite_data( $product_id ){
519
+ return get_post_meta( $product_id, self::META_KEY_DATA, true ) ?: [];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  }
521
 
522
  public function replace_tm_editor_custom_fields_with_own_sections( $fields ){
523
+ $fields[] = self::META_KEY_DATA;
524
+ $fields[] = self::META_KEY_SCENARIO;
525
 
526
  return $fields;
527
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
528
  }
compatibility/WcDynamicPricing/Factory.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcDynamicPricing;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\isStandAlone;
9
+
10
+ /**
11
+ * @see https://woocommerce.com/products/dynamic-pricing/
12
+ */
13
+ class Factory extends ComponentFactory implements IStandAloneAction {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ $hooks = [];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks();
23
+ }
24
+
25
+ if ( ! isStandAlone() ) {
26
+ $hooks[] = new \WCML_Dynamic_Pricing( getSitePress() );
27
+ }
28
+
29
+ return $hooks;
30
+ }
31
+ }
compatibility/WcDynamicPricing/MulticurrencyHooks.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcDynamicPricing;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'wc_dynamic_pricing_load_modules', [ $this, 'filter_price' ] );
9
+ add_filter( 'woocommerce_dynamic_pricing_get_rule_amount', [ $this, 'woocommerce_dynamic_pricing_get_rule_amount' ], 10, 2 );
10
+ add_filter( 'dynamic_pricing_product_rules', [ $this, 'dynamic_pricing_product_rules' ] );
11
+ }
12
+
13
+ /**
14
+ * @param array $modules
15
+ *
16
+ * @return array
17
+ */
18
+ public function filter_price( $modules ) {
19
+
20
+ foreach ( $modules as $mod_key => $module ) {
21
+ if ( isset( $module->available_rulesets ) ) {
22
+ $available_rulesets = $module->available_rulesets;
23
+
24
+ foreach ( $available_rulesets as $rule_key => $available_ruleset ) {
25
+
26
+ if ( isset( $available_ruleset['rules'] ) && is_array( $available_ruleset['rules'] ) ) {
27
+ $rules = $available_ruleset['rules'];
28
+ foreach ( $rules as $r_key => $rule ) {
29
+ if ( 'fixed_product' === $rule['type'] ) {
30
+ $rules[ $r_key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $rule['amount'] );
31
+ }
32
+ }
33
+ $modules[ $mod_key ]->available_rulesets[ $rule_key ]['rules'] = $rules;
34
+
35
+ } elseif ( isset( $available_ruleset['type'] ) && 'fixed_product' === $available_ruleset['type'] ) {
36
+ $modules[ $mod_key ]->available_rulesets[ $rule_key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $available_ruleset['amount'] );
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ return $modules;
43
+ }
44
+
45
+ /**
46
+ * @param float $amount
47
+ * @param object $rule
48
+ *
49
+ * @return float
50
+ */
51
+ public function woocommerce_dynamic_pricing_get_rule_amount( $amount, $rule ) {
52
+
53
+ if ( 'price_discount' === $rule['type'] || 'fixed_price' === $rule['type'] ) {
54
+ $amount = apply_filters( 'wcml_raw_price_amount', $amount );
55
+ }
56
+
57
+ return $amount;
58
+ }
59
+
60
+ /**
61
+ * @param array $rules
62
+ *
63
+ * @return array
64
+ */
65
+ public function dynamic_pricing_product_rules( $rules ) {
66
+ if ( is_array( $rules ) ) {
67
+ foreach ( $rules as $r_key => $rule ) {
68
+ foreach ( $rule['rules'] as $key => $product_rule ) {
69
+ if ( 'price_discount' === $product_rule['type'] || 'fixed_price' === $product_rule['type'] ) {
70
+ $rules[ $r_key ]['rules'][ $key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $product_rule['amount'] );
71
+ }
72
+ }
73
+ }
74
+ }
75
+ return $rules;
76
+ }
77
+
78
+ }
compatibility/{class-wcml-dynamic-pricing.php → WcDynamicPricing/class-wcml-dynamic-pricing.php} RENAMED
@@ -5,7 +5,7 @@ use WPML\FP\Obj;
5
  /**
6
  * Class WCML_Dynamic_Pricing
7
  */
8
- class WCML_Dynamic_Pricing {
9
 
10
  /**
11
  * @var SitePress
@@ -22,52 +22,14 @@ class WCML_Dynamic_Pricing {
22
  }
23
 
24
  public function add_hooks() {
25
-
26
  if ( ! is_admin() ) {
27
  add_filter( 'woocommerce_dynamic_pricing_is_object_in_terms', [ $this, 'is_object_in_translated_terms' ], 10, 3 );
28
-
29
- add_filter( 'wc_dynamic_pricing_load_modules', [ $this, 'filter_price' ] );
30
  add_filter( 'wc_dynamic_pricing_load_modules', [ $this, 'translate_collector_args' ] );
31
  add_filter( 'woocommerce_dynamic_pricing_is_applied_to', [ $this, 'woocommerce_dynamic_pricing_is_applied_to' ], 10, 5 );
32
- add_filter( 'woocommerce_dynamic_pricing_get_rule_amount', [ $this, 'woocommerce_dynamic_pricing_get_rule_amount' ], 10, 2 );
33
- add_filter( 'dynamic_pricing_product_rules', [ $this, 'dynamic_pricing_product_rules' ] );
34
  } else {
35
  $this->hide_language_switcher_for_settings_page();
36
  }
37
  add_filter( 'woocommerce_product_get__pricing_rules', [ $this, 'translate_variations_in_rules' ] );
38
-
39
- }
40
-
41
- /**
42
- * @param array $modules
43
- *
44
- * @return array
45
- */
46
- public function filter_price( $modules ) {
47
-
48
- foreach ( $modules as $mod_key => $module ) {
49
- if ( isset( $module->available_rulesets ) ) {
50
- $available_rulesets = $module->available_rulesets;
51
-
52
- foreach ( $available_rulesets as $rule_key => $available_ruleset ) {
53
-
54
- if ( isset( $available_ruleset['rules'] ) && is_array( $available_ruleset['rules'] ) ) {
55
- $rules = $available_ruleset['rules'];
56
- foreach ( $rules as $r_key => $rule ) {
57
- if ( 'fixed_product' === $rule['type'] ) {
58
- $rules[ $r_key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $rule['amount'] );
59
- }
60
- }
61
- $modules[ $mod_key ]->available_rulesets[ $rule_key ]['rules'] = $rules;
62
-
63
- } elseif ( isset( $available_ruleset['type'] ) && 'fixed_product' === $available_ruleset['type'] ) {
64
- $modules[ $mod_key ]->available_rulesets[ $rule_key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $available_ruleset['amount'] );
65
- }
66
- }
67
- }
68
- }
69
-
70
- return $modules;
71
  }
72
 
73
  /**
@@ -76,7 +38,6 @@ class WCML_Dynamic_Pricing {
76
  * @return array
77
  */
78
  public function translate_collector_args( $modules ) {
79
-
80
  foreach ( $modules as $mod_key => $module ) {
81
  if ( isset( $module->available_advanced_rulesets ) ) {
82
  foreach ( $module->available_advanced_rulesets as $rule_key => $rule ) {
@@ -111,7 +72,6 @@ class WCML_Dynamic_Pricing {
111
  return is_object_in_term( $product_id, 'product_cat', $categories );
112
  }
113
 
114
-
115
  /**
116
  * @param bool $process_discounts
117
  * @param WC_Product $_product
@@ -190,7 +150,7 @@ class WCML_Dynamic_Pricing {
190
  return wpml_collect( $requirements[ $class_name ] )
191
  ->filter(
192
  function ( $property ) use ( $dynamic_pricing ) {
193
- return isset( $dynamic_pricing->$property ) && $dynamic_pricing->$property;
194
  }
195
  )
196
  ->count();
@@ -218,40 +178,6 @@ class WCML_Dynamic_Pricing {
218
  );
219
  }
220
 
221
- /**
222
- * @param float $amount
223
- * @param object $rule
224
- *
225
- * @return float
226
- */
227
- public function woocommerce_dynamic_pricing_get_rule_amount( $amount, $rule ) {
228
-
229
- if ( 'price_discount' === $rule['type'] || 'fixed_price' === $rule['type'] ) {
230
- $amount = apply_filters( 'wcml_raw_price_amount', $amount );
231
- }
232
-
233
- return $amount;
234
- }
235
-
236
-
237
- /**
238
- * @param array $rules
239
- *
240
- * @return array
241
- */
242
- public function dynamic_pricing_product_rules( $rules ) {
243
- if ( is_array( $rules ) ) {
244
- foreach ( $rules as $r_key => $rule ) {
245
- foreach ( $rule['rules'] as $key => $product_rule ) {
246
- if ( 'price_discount' === $product_rule['type'] || 'fixed_price' === $product_rule['type'] ) {
247
- $rules[ $r_key ]['rules'][ $key ]['amount'] = apply_filters( 'wcml_raw_price_amount', $product_rule['amount'] );
248
- }
249
- }
250
- }
251
- }
252
- return $rules;
253
- }
254
-
255
  /**
256
  * @param array $rules
257
  *
5
  /**
6
  * Class WCML_Dynamic_Pricing
7
  */
8
+ class WCML_Dynamic_Pricing implements \IWPML_Action {
9
 
10
  /**
11
  * @var SitePress
22
  }
23
 
24
  public function add_hooks() {
 
25
  if ( ! is_admin() ) {
26
  add_filter( 'woocommerce_dynamic_pricing_is_object_in_terms', [ $this, 'is_object_in_translated_terms' ], 10, 3 );
 
 
27
  add_filter( 'wc_dynamic_pricing_load_modules', [ $this, 'translate_collector_args' ] );
28
  add_filter( 'woocommerce_dynamic_pricing_is_applied_to', [ $this, 'woocommerce_dynamic_pricing_is_applied_to' ], 10, 5 );
 
 
29
  } else {
30
  $this->hide_language_switcher_for_settings_page();
31
  }
32
  add_filter( 'woocommerce_product_get__pricing_rules', [ $this, 'translate_variations_in_rules' ] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  }
34
 
35
  /**
38
  * @return array
39
  */
40
  public function translate_collector_args( $modules ) {
 
41
  foreach ( $modules as $mod_key => $module ) {
42
  if ( isset( $module->available_advanced_rulesets ) ) {
43
  foreach ( $module->available_advanced_rulesets as $rule_key => $rule ) {
72
  return is_object_in_term( $product_id, 'product_cat', $categories );
73
  }
74
 
 
75
  /**
76
  * @param bool $process_discounts
77
  * @param WC_Product $_product
150
  return wpml_collect( $requirements[ $class_name ] )
151
  ->filter(
152
  function ( $property ) use ( $dynamic_pricing ) {
153
+ return isset( $dynamic_pricing->$property ) && $dynamic_pricing->$property;
154
  }
155
  )
156
  ->count();
178
  );
179
  }
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  /**
182
  * @param array $rules
183
  *
compatibility/WcExporter/Factory.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcExporter;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_wcExporter;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+
10
+ /**
11
+ * @see https://br.wordpress.org/plugins/woocommerce-exporter/
12
+ */
13
+ class Factory extends ComponentFactory {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ return new WCML_wcExporter( getSitePress(), getWooCommerceWpml() );
20
+ }
21
+ }
compatibility/{class-wcml-wcexporter.php → WcExporter/class-wcml-wcexporter.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_wcExporter {
4
 
5
  /**
6
  * @var SitePress
1
  <?php
2
 
3
+ class WCML_wcExporter implements \IWPML_Action {
4
 
5
  /**
6
  * @var SitePress
compatibility/WcMemberships/Factory.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcMemberships;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+
7
+ class Factory extends ComponentFactory {
8
+
9
+ /**
10
+ * @inheritDoc
11
+ */
12
+ public function create() {
13
+ return new \WCML_WC_Memberships( new \WPML_WP_API() );
14
+ }
15
+ }
compatibility/{class-wcml-wc-memberships.php → WcMemberships/class-wcml-wc-memberships.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_WC_Memberships {
4
 
5
  /**
6
  * @var WPML_WP_API
1
  <?php
2
 
3
+ class WCML_WC_Memberships implements \IWPML_Action {
4
 
5
  /**
6
  * @var WPML_WP_API
compatibility/WcMixAndMatch/Factory.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcMixAndMatch;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ use function WCML\functions\getSitePress;
9
+ use function WCML\functions\isStandAlone;
10
+
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ if ( ! isStandAlone() ) {
24
+ $hooks[] = new \WCML_Mix_And_Match_Products( getSitePress() );
25
+ }
26
+
27
+ return $hooks;
28
+ }
29
+
30
+ }
compatibility/WcMixAndMatch/MulticurrencyHooks.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcMixAndMatch;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'wcml_price_custom_fields_filtered', [ $this, 'get_price_custom_fields' ], 10, 2 );
9
+ add_filter( 'wcml_update_custom_prices_values', [ $this, 'update_container_custom_prices_values' ], 10, 2 );
10
+ add_filter( 'wcml_after_save_custom_prices', [ $this, 'update_container_base_price' ], 10, 4 );
11
+ }
12
+
13
+ /**
14
+ * Add MNM price fields to list to be converted.
15
+ *
16
+ * @since 5.0.0
17
+ *
18
+ * @param array $custom_fields
19
+ * @return array
20
+ */
21
+ public function get_price_custom_fields( $custom_fields ) {
22
+ return array_merge(
23
+ $custom_fields,
24
+ [
25
+ '_mnm_base_regular_price',
26
+ '_mnm_base_sale_price',
27
+ '_mnm_base_price',
28
+ '_mnm_max_price',
29
+ '_mnm_max_regular_price',
30
+ ]
31
+ );
32
+ }
33
+
34
+ /**
35
+ * Swap the base price for the custom price in that currency.
36
+ *
37
+ * @since 5.0.0
38
+ *
39
+ * @param array $prices
40
+ * @param string $code
41
+ * @return array
42
+ */
43
+ public function update_container_custom_prices_values( $prices, $code ) {
44
+ foreach ( [
45
+ '_custom_regular_price' => '_mnm_base_regular_price',
46
+ '_custom_sale_price' => '_mnm_base_sale_price',
47
+ ] as $wc_price => $custom_price ) {
48
+ if ( isset( $_POST[ $wc_price ][ $code ] ) ) {
49
+ $prices[ $custom_price ] = wc_format_decimal( $_POST[ $wc_price ][ $code ] );
50
+ }
51
+ }
52
+
53
+ return $prices;
54
+ }
55
+
56
+ /**
57
+ * Save base price per currency.
58
+ *
59
+ * @since 5.0.0
60
+ *
61
+ * @param int $post_id
62
+ * @param string $product_price
63
+ * @param array $custom_prices
64
+ * @param string $code
65
+ */
66
+ public function update_container_base_price( $post_id, $product_price, $custom_prices, $code ) {
67
+
68
+ if ( isset( $custom_prices['_mnm_base_regular_price'] ) ) {
69
+ update_post_meta( $post_id, '_mnm_base_price_' . $code, $product_price );
70
+ }
71
+
72
+ }
73
+
74
+ }
compatibility/WcMixAndMatch/class-wcml-mix-and-match-products.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Mix and Match Products compatibility class.
4
+ *
5
+ * @version 5.0.0
6
+ */
7
+ class WCML_Mix_And_Match_Products implements \IWPML_Action {
8
+
9
+ /**
10
+ * @var SitePress
11
+ */
12
+ private $sitepress;
13
+
14
+ /**
15
+ * @param SitePress $sitepress
16
+ */
17
+ public function __construct( SitePress $sitepress ) {
18
+ $this->sitepress = $sitepress;
19
+ }
20
+
21
+ /**
22
+ * Attach callbacks.
23
+ *
24
+ * @since 5.0.0
25
+ */
26
+ public function add_hooks() {
27
+ // Support MNM 2.0 custom tables, cart syncing.
28
+ if ( is_callable( [ 'WC_MNM_Compatibility', 'is_db_version_gte' ] ) && WC_MNM_Compatibility::is_db_version_gte( '2.0' ) ) {
29
+ add_action( 'wcml_after_sync_product_data', [ $this, 'sync_allowed_contents' ], 10, 2 );
30
+ add_filter( 'wcml_cart_contents', [ $this, 'sync_cart' ], 10, 4 );
31
+ } else {
32
+ add_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10, 4 );
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Translate container data with translated values when the product is duplicated.
38
+ *
39
+ * Handles translating source products to the MNM custom table.
40
+ * Handles translating source categories as meta.
41
+ *
42
+ * @param int $container_id
43
+ * @param int $translated_container_id
44
+ */
45
+ public function sync_allowed_contents( $container_id, $translated_container_id ) {
46
+
47
+ if ( has_term( 'mix-and-match', 'product_type', $container_id ) ) {
48
+
49
+ $translated_child_items = [];
50
+ $lang = $this->sitepress->get_language_for_element( $translated_container_id, 'post_product' );
51
+
52
+ $original_product = wc_get_product( $container_id );
53
+ $translated_product = wc_get_product( $translated_container_id );
54
+
55
+ if ( $original_product ) {
56
+
57
+ $original_child_items = $original_product->get_child_items( 'edit' );
58
+
59
+ $translated_child_items = [];
60
+
61
+ // Translate child items.
62
+ if ( ! empty( $original_child_items ) ) {
63
+
64
+ foreach ( $original_child_items as $item_key => $original_child_item ) {
65
+
66
+ $translated_child_items[] = [
67
+ 'product_id' => apply_filters( 'wpml_object_id', $original_child_item->get_product_id(), 'product', false, $lang ),
68
+ 'variation_id' => apply_filters( 'wpml_object_id', $original_child_item->get_variation_id(), 'product_variation', false, $lang ),
69
+ ];
70
+
71
+ }
72
+ }
73
+
74
+ if ( $translated_product && ! empty( $translated_child_items ) ) {
75
+ $translated_product->set_child_items( $translated_child_items );
76
+ }
77
+
78
+ // Translate child source categories.
79
+ $original_child_cat_ids = $original_product->get_child_category_ids( 'edit' );
80
+ $translated_child_cat_ids = [];
81
+
82
+ foreach ( $original_child_cat_ids as $original_cat_id ) {
83
+ $translated_child_cat_ids[] = apply_filters( 'wpml_object_id', $original_cat_id, 'product_cat', true, $lang );
84
+ }
85
+
86
+ if ( $translated_product && ! empty( $translated_child_cat_ids ) ) {
87
+ $translated_product->set_child_category_ids( $translated_child_cat_ids );
88
+ }
89
+
90
+ // Save product.
91
+ $translated_product->save();
92
+
93
+ }
94
+ }
95
+
96
+ }
97
+
98
+ /**
99
+ * Update the cart contents to the new language
100
+ *
101
+ * @since 5.0.0
102
+ *
103
+ * @param array $new_cart_contents
104
+ * @param array $cart_contents
105
+ * @param string $key
106
+ * @param string $new_key
107
+ *
108
+ * @return array
109
+ */
110
+ public function sync_cart( $new_cart_contents, $cart_contents, $key, $new_key ) {
111
+ if ( ! function_exists( 'wc_mnm_is_container_cart_item' )
112
+ || ! function_exists( 'wc_mnm_get_child_cart_items' )
113
+ || ! function_exists( 'wc_mnm_maybe_is_child_cart_item' )
114
+ || ! function_exists( 'wc_mnm_get_cart_item_container' )
115
+ ) {
116
+ return $new_cart_contents;
117
+ }
118
+
119
+ $current_language = $this->sitepress->get_current_language();
120
+
121
+ // Translate container.
122
+ if ( wc_mnm_is_container_cart_item( $new_cart_contents[ $new_key ] ) ) {
123
+
124
+ $new_config = [];
125
+
126
+ // Translate config.
127
+ foreach ( $new_cart_contents[ $new_key ]['mnm_config'] as $id => $data ) {
128
+
129
+ $tr_product_id = apply_filters( 'wpml_object_id', $data['product_id'], 'product', false, $current_language );
130
+ $tr_variation_id = 0;
131
+
132
+ if ( isset( $data['variation_id'] ) && $data['variation_id'] ) {
133
+ $tr_variation_id = apply_filters( 'wpml_object_id', $data['variation_id'], 'product_variation', false, $current_language );
134
+ }
135
+
136
+ $tr_child_id = $tr_variation_id ? intval( $tr_variation_id ) : intval( $tr_product_id );
137
+
138
+ $new_config[ $tr_child_id ] = [
139
+ 'mnm_child_id' => $tr_child_id,
140
+ 'product_id' => intval( $tr_product_id ),
141
+ 'variation_id' => intval( $tr_variation_id ),
142
+ 'quantity' => $data['quantity'],
143
+ 'variation' => $data['variation'], // @todo: translate attributes
144
+ ];
145
+
146
+ }
147
+
148
+ if ( ! empty( $new_config ) ) {
149
+ $new_cart_contents[ $new_key ]['mnm_config'] = $new_config;
150
+ }
151
+
152
+ // Find all children and stash new container cart key. Need to direclty manipulate the wc()->cart as $cart_contents isn't persisted.
153
+ foreach ( wc_mnm_get_child_cart_items( $new_cart_contents[ $new_key ] ) as $child_key => $child_item ) {
154
+ WC()->cart->cart_contents[ $child_key ]['translated_mnm_container'] = $new_key;
155
+ }
156
+ }
157
+
158
+ // Translate children.
159
+ if ( wc_mnm_maybe_is_child_cart_item( $new_cart_contents[ $new_key ] ) ) {
160
+
161
+ // Update the child's container and remove the stashed version.
162
+ $new_cart_contents[ $new_key ]['mnm_container'] = $cart_contents[ $key ]['translated_mnm_container'];
163
+ unset( $cart_contents[ $key ]['translated_mnm_container'] );
164
+
165
+ $container_key = wc_mnm_get_cart_item_container( $new_cart_contents[ $new_key ], $new_cart_contents, true );
166
+
167
+ if ( $container_key ) {
168
+
169
+ // Swap keys in container's content array.
170
+ $remove_key = array_search( $key, $new_cart_contents[ $container_key ]['mnm_contents'] );
171
+ unset( $new_cart_contents[ $container_key ]['mnm_contents'][ $remove_key ] );
172
+ $new_cart_contents[ $container_key ]['mnm_contents'][] = $new_key;
173
+
174
+ }
175
+ }
176
+
177
+ return $new_cart_contents;
178
+ }
179
+
180
+ /**
181
+ * Translate the _mnm_data meta of child products.
182
+ *
183
+ * For Mix and Match 1.x data.
184
+ *
185
+ * @param string $meta_id
186
+ * @param int $post_id
187
+ * @param string $meta_key
188
+ * @param mixed $meta_value
189
+ */
190
+ public function sync_mnm_data( $meta_id, $post_id, $meta_key, $meta_value ) {
191
+ if ( '_mnm_data' !== $meta_key ) {
192
+ return;
193
+ }
194
+
195
+ global $sitepress, $woocommerce_wpml;
196
+
197
+ $post = get_post( $post_id );
198
+
199
+ // Skip auto-drafts, skip autosave.
200
+ if ( 'auto-draft' === $post->post_status || isset( $_POST['autosave'] ) ) {
201
+ return;
202
+ }
203
+
204
+ if ( 'product' === $post->post_type ) {
205
+ remove_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10 );
206
+
207
+ if ( $woocommerce_wpml->products->is_original_product( $post_id ) ) {
208
+ $original_product_id = $post_id;
209
+ } else {
210
+ $original_product_id = $woocommerce_wpml->products->get_original_product_id( $post_id );
211
+ }
212
+
213
+ $mnm_data = maybe_unserialize( get_post_meta( $original_product_id, '_mnm_data', true ) );
214
+ $product_trid = $sitepress->get_element_trid( $original_product_id, 'post_product' );
215
+ $product_translations = $sitepress->get_element_translations( $product_trid, 'post_product' );
216
+
217
+ foreach ( $product_translations as $product_translation ) {
218
+ if ( empty( $product_translation->original ) ) {
219
+ foreach ( $mnm_data as $key => $mnm_element ) {
220
+
221
+ $trnsl_prod = apply_filters( 'translate_object_id', $key, 'product', true, $product_translation->language_code );
222
+ $mnm_element['product_id'] = $trnsl_prod;
223
+ $mnm_data[ $trnsl_prod ] = $mnm_element;
224
+ unset( $mnm_data[ $key ] );
225
+ }
226
+
227
+ update_post_meta( $product_translation->element_id, '_mnm_data', $mnm_data );
228
+ }
229
+ }
230
+
231
+ add_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10, 4 );
232
+ }
233
+ }
234
+
235
+ }
compatibility/WcNameYourPrice/Factory.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcNameYourPrice;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://woocommerce.com/products/name-your-price/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+
26
+ }
compatibility/WcNameYourPrice/MulticurrencyHooks.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcNameYourPrice;
4
+
5
+ use WC_Name_Your_Price_Compatibility;
6
+
7
+ use function WCML\functions\getClientCurrency;
8
+
9
+ /**
10
+ * WooCommerce Name Your Price compatibility.
11
+ *
12
+ * @version 4.12.2
13
+ */
14
+ class MulticurrencyHooks implements \IWPML_Action {
15
+
16
+ public function add_hooks() {
17
+ // Price filters.
18
+ if ( ! is_admin() ) {
19
+ if ( is_callable( [ 'WC_Name_Your_Price_Compatibility', 'is_nyp_gte' ] ) && WC_Name_Your_Price_Compatibility::is_nyp_gte( '3.0' ) ) {
20
+ add_filter( 'wc_nyp_raw_suggested_price', [ $this, 'product_price_filter' ] );
21
+ add_filter( 'wc_nyp_raw_minimum_price', [ $this, 'product_price_filter' ] );
22
+ add_filter( 'wc_nyp_raw_maximum_price', [ $this, 'product_price_filter' ] );
23
+ } else {
24
+ add_filter( 'woocommerce_raw_suggested_price', [ $this, 'product_price_filter' ] );
25
+ add_filter( 'woocommerce_raw_minimum_price', [ $this, 'product_price_filter' ] );
26
+ add_filter( 'woocommerce_raw_maximum_price', [ $this, 'product_price_filter' ] );
27
+ }
28
+ }
29
+
30
+ // Cart currency switching.
31
+ add_filter( 'woocommerce_add_cart_item_data', [ $this, 'add_initial_currency' ] );
32
+ add_filter( 'woocommerce_get_cart_item_from_session', [ $this, 'filter_woocommerce_get_cart_item_from_session' ], 20, 2 );
33
+ }
34
+
35
+ /**
36
+ * @param float|int $price
37
+ * @param string|false $currency
38
+ *
39
+ * @return float|int
40
+ */
41
+ public function product_price_filter( $price, $currency = false ) {
42
+ return apply_filters( 'wcml_raw_price_amount', $price, $currency );
43
+ }
44
+
45
+ /**
46
+ * Store the initial currency when item is added.
47
+ *
48
+ * @param array $cart_item_data The Cart Item data.
49
+ *
50
+ * @return array
51
+ * @since 4.12.2
52
+ */
53
+ public function add_initial_currency( $cart_item_data ) {
54
+
55
+ if ( isset( $cart_item_data['nyp'] ) ) {
56
+ $cart_item_data['nyp_currency'] = get_woocommerce_currency();
57
+ $cart_item_data['nyp_original'] = $cart_item_data['nyp'];
58
+ }
59
+
60
+ return $cart_item_data;
61
+ }
62
+
63
+ /**
64
+ * Filter Name Your Price Cart prices.
65
+ *
66
+ * @param array $session_data The Session data.
67
+ * @param array $values The values.
68
+ *
69
+ * @return array
70
+ *
71
+ * @since 4.12.2
72
+ *
73
+ * @internal filter.
74
+ */
75
+ public function filter_woocommerce_get_cart_item_from_session( $session_data, $values ) {
76
+
77
+ // Preserve original currency.
78
+ if ( isset( $values['nyp_currency'] ) ) {
79
+ $session_data['nyp_currency'] = $values['nyp_currency'];
80
+ }
81
+
82
+ // Preserve original entered value.
83
+ if ( isset( $values['nyp_original'] ) ) {
84
+ $session_data['nyp_original'] = $values['nyp_original'];
85
+ }
86
+
87
+ $current_currency = getClientCurrency();
88
+
89
+ if ( isset( $session_data['nyp_currency'] ) && $session_data['nyp_currency'] !== $current_currency ) {
90
+
91
+ // Product is in the 'data'.
92
+ $product = $session_data['data'];
93
+
94
+ $price_in_current_currency = $this->product_price_filter( $session_data['nyp'], $current_currency );
95
+
96
+ // Set to price in current currency.
97
+ $product->set_price( $price_in_current_currency );
98
+ $product->set_regular_price( $price_in_current_currency );
99
+ $product->set_sale_price( $price_in_current_currency );
100
+
101
+ // Subscription-specific price and variable billing period.
102
+ if ( $product->is_type( [ 'subscription', 'subscription_variation' ] ) ) {
103
+ $product->update_meta_data( '_subscription_price', $price_in_current_currency );
104
+ }
105
+ }
106
+
107
+ return $session_data;
108
+ }
109
+
110
+ }
compatibility/WcOrderStatusManager/Factory.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcOrderStatusManager;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Order_Status_Manager;
7
+ use WP_Query;
8
+
9
+ class Factory extends ComponentFactory {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function create() {
15
+ return new WCML_Order_Status_Manager( new WP_Query() );
16
+ }
17
+ }
compatibility/{class-wcml-order-status-manager.php → WcOrderStatusManager/class-wcml-order-status-manager.php} RENAMED
@@ -3,7 +3,7 @@
3
  * Class WCML_Order_Status_Manager
4
  * compatibility class for WC Order Status Manager plugin.
5
  */
6
- class WCML_Order_Status_Manager {
7
  /**
8
  * WordPress query object.
9
  *
3
  * Class WCML_Order_Status_Manager
4
  * compatibility class for WC Order Status Manager plugin.
5
  */
6
+ class WCML_Order_Status_Manager implements \IWPML_Action {
7
  /**
8
  * WordPress query object.
9
  *
compatibility/WcPip/Factory.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcPip;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_Pip;
8
+ use function WCML\functions\isStandAlone;
9
+
10
+ /**
11
+ * @see https://woocommerce.com/products/print-invoices-packing-lists/
12
+ */
13
+ class Factory extends ComponentFactory implements IStandAloneAction {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ $hooks = [];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks();
23
+ }
24
+
25
+ if ( ! isStandAlone() ) {
26
+ $hooks[] = new WCML_Pip();
27
+ }
28
+
29
+ return $hooks;
30
+ }
31
+ }
compatibility/WcPip/Helper.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcPip;
4
+
5
+ class Helper {
6
+
7
+ /**
8
+ * @return false|int|string
9
+ */
10
+ public static function getPipOrderId() {
11
+ $order_id = false;
12
+
13
+ if ( isset( $_GET['wc_pip_action'] ) && isset( $_GET['order_id'] ) ) {
14
+ $order_id = $_GET['order_id'];
15
+ } elseif (
16
+ isset( $_POST['action'] ) &&
17
+ (
18
+ $_POST['action'] == 'wc_pip_order_send_email' ||
19
+ $_POST['action'] == 'wc_pip_send_email_packing_list'
20
+ ) &&
21
+ isset( $_POST['order_id'] )
22
+ ) {
23
+ $order_id = $_POST['order_id'];
24
+ }
25
+
26
+ return $order_id;
27
+ }
28
+ }
compatibility/WcPip/MulticurrencyHooks.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcPip;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
9
+ add_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
10
+ }
11
+
12
+ /**
13
+ * @param string $currencySymbol
14
+ *
15
+ * @return string
16
+ */
17
+ public function filter_pip_currency_symbol( $currencySymbol ) {
18
+ remove_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
19
+
20
+ $currency = self::getPipOrderCurrency();
21
+
22
+ if ( $currency ) {
23
+ $currencySymbol = get_woocommerce_currency_symbol( $currency );
24
+ }
25
+
26
+ add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
27
+
28
+ return $currencySymbol;
29
+ }
30
+
31
+ /**
32
+ * @param string $currency
33
+ *
34
+ * @return string
35
+ */
36
+ public function filter_pip_currency_position( $currency ) {
37
+ remove_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
38
+
39
+ $currency = self::getPipOrderCurrency( $currency );
40
+
41
+ add_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
42
+
43
+ return $currency;
44
+ }
45
+
46
+ /**
47
+ * @param string|false $currency
48
+ *
49
+ * @return string|false
50
+ */
51
+ private static function getPipOrderCurrency( $currency = false ) {
52
+ $pip_order_id = Helper::getPipOrderId();
53
+
54
+ if ( $pip_order_id && isset( WC()->order_factory ) ) {
55
+
56
+ $the_order = WC()->order_factory->get_order( $pip_order_id );
57
+
58
+ if ( $the_order ) {
59
+ $currency = $the_order->get_currency();
60
+
61
+ if ( ! $currency && isset( $_COOKIE['_wcml_order_currency'] ) ) {
62
+ $currency = $_COOKIE['_wcml_order_currency'];
63
+ }
64
+ }
65
+ }
66
+
67
+ return $currency;
68
+ }
69
+ }
compatibility/WcPip/class-wcml-pip.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WCML\Compatibility\WcPip\Helper;
4
+
5
+ class WCML_Pip implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'wcml_send_email_order_id', [ $this, 'wcml_send_email_order_id' ] );
9
+ add_action( 'wc_pip_print', [ $this, 'print_invoice_language' ], 10, 2 );
10
+ }
11
+
12
+ public function wcml_send_email_order_id( $order_id ) {
13
+ $pip_order_id = Helper::getPipOrderId();
14
+
15
+ if ( $pip_order_id ) {
16
+ $order_id = $pip_order_id;
17
+ }
18
+
19
+ return $order_id;
20
+ }
21
+
22
+ public function print_invoice_language( $type, $order_id ) {
23
+ $order_language = get_post_meta( $order_id, 'wpml_language', true );
24
+
25
+ if ( $order_language ) {
26
+ do_action( 'wpml_switch_language', $order_language );
27
+ }
28
+ }
29
+ }
compatibility/WcProductAddons/Factory.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductAddons;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+ use function WCML\functions\isStandAlone;
10
+
11
+ /**
12
+ * @see https://woocommerce.com/products/product-add-ons/
13
+ */
14
+ class Factory extends ComponentFactory implements IStandAloneAction {
15
+
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ public function create() {
20
+ $hooks = [
21
+ new SharedHooks(),
22
+ ];
23
+
24
+ if ( wcml_is_multi_currency_on() ) {
25
+ $hooks[] = new MulticurrencyHooks( getWooCommerceWpml() );
26
+ }
27
+
28
+ if ( ! isStandAlone() ) {
29
+ $hooks[] = new \WCML_Product_Addons( getSitePress() );
30
+ }
31
+
32
+ return $hooks;
33
+ }
34
+ }
compatibility/WcProductAddons/MulticurrencyHooks.php ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductAddons;
4
+
5
+ use WC_Product_Booking;
6
+ use WCML_Product_Addons;
7
+ use woocommerce_wpml;
8
+ use WPML_Twig_Template_Loader;
9
+
10
+ class MulticurrencyHooks implements \IWPML_Action {
11
+
12
+ const TEMPLATE_FOLDER = '/templates/compatibility/';
13
+ const DIALOG_TEMPLATE = 'product-addons-prices-dialog.twig';
14
+ const SETTINGS_TEMPLATE = 'product-addons-prices-settings.twig';
15
+ const PRICE_OPTION_KEY = '_product_addon_prices';
16
+
17
+ /** @var woocommerce_wpml $woocommerce_wpml */
18
+ private $woocommerce_wpml;
19
+
20
+ /**
21
+ * @param woocommerce_wpml $woocommerce_wpml
22
+ */
23
+ public function __construct( woocommerce_wpml $woocommerce_wpml ) {
24
+ $this->woocommerce_wpml = $woocommerce_wpml;
25
+ }
26
+
27
+ public function add_hooks() {
28
+ add_filter( 'get_product_addons_fields', [ $this, 'product_addons_price_filter' ], 10, 2 );
29
+ add_filter( 'wcml_cart_contents_not_changed', [ $this, 'filter_booking_addon_product_in_cart_contents' ], 20 );
30
+ add_filter( 'wcml_product_addons_global_updated', [ $this, 'onGlobalAddonsUpdated' ], 10, 2 );
31
+
32
+ if ( is_admin() ) {
33
+ add_action( 'woocommerce_product_addons_panel_start', [ $this, 'load_dialog_resources' ] );
34
+ add_action( 'woocommerce_product_addons_panel_option_row', [ $this, 'dialog_button_after_option_row' ], 10, 4 );
35
+ add_action( 'woocommerce_product_addons_panel_before_options', [ $this, 'dialog_button_before_options' ], 10, 3 );
36
+ add_action( 'wcml_before_sync_product', [ $this, 'update_custom_prices_values' ] );
37
+ add_action( 'save_post', [ $this, 'maybeUpdateCustomPricesValues' ], 10, 2 );
38
+ add_action( 'woocommerce_product_addons_global_edit_objects', [ $this, 'custom_prices_settings_block' ] );
39
+ }
40
+ }
41
+
42
+ public function maybeUpdateCustomPricesValues( $productId, $arg ) {
43
+ if ( 'product' === get_post_type( $productId ) ) {
44
+ $this->update_custom_prices_values( $productId );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * @param array $addons
50
+ * @param int $postId
51
+ *
52
+ * @return array
53
+ */
54
+ public function product_addons_price_filter( $addons, $postId ) {
55
+ foreach ( $addons as $addonId => $addon ) {
56
+
57
+ $addon_data = wpml_collect( $addon );
58
+
59
+ if ( $addon_data->offsetExists( 'price' ) && $addon_data->get( 'price' ) ) {
60
+ $addons[ $addonId ]['price'] = $this->converted_addon_price( $addon, $postId );
61
+ }
62
+
63
+ if ( $addon_data->offsetExists( 'options' ) ) {
64
+ foreach ( $addon_data->get( 'options' ) as $key => $option ) {
65
+ $addons[ $addonId ]['options'][ $key ]['price'] = $this->converted_addon_price( $option, $postId );
66
+ }
67
+ }
68
+ }
69
+
70
+ return $addons;
71
+ }
72
+
73
+ /**
74
+ * Special case for WC Bookings plugin - need add addon cost after re-calculating booking costs.
75
+ *
76
+ * @see https://onthegosystems.myjetbrains.com/youtrack/issue/wcml-1877
77
+ *
78
+ * @param array $cartItem
79
+ *
80
+ * @return array
81
+ */
82
+ public function filter_booking_addon_product_in_cart_contents( $cartItem ) {
83
+ $isBookingProductWithAddons = $cartItem['data'] instanceof WC_Product_Booking && isset( $cartItem['addons'] );
84
+
85
+ if ( $isBookingProductWithAddons ) {
86
+ $cost = $cartItem['data']->get_price();
87
+
88
+ foreach ( $cartItem['addons'] as $addon ) {
89
+ $cost += $addon['price'];
90
+ }
91
+
92
+ $cartItem['data']->set_price( $cost );
93
+ }
94
+
95
+ return $cartItem;
96
+ }
97
+
98
+ /**
99
+ * @param array $addon
100
+ * @param int $postId
101
+ *
102
+ * @return string
103
+ */
104
+ private function converted_addon_price( $addon, $postId ) {
105
+ $addonData = wpml_collect( $addon );
106
+
107
+ $isCustomPricesOn = $this->isProductCustomPricesOn( $postId );
108
+ $field = 'price_' . $this->woocommerce_wpml->multi_currency->get_client_currency();
109
+
110
+ if (
111
+ $isCustomPricesOn &&
112
+ $addonData->get( $field )
113
+ ) {
114
+ return $addonData->get( $field );
115
+ }
116
+
117
+ if ( wpml_collect( [ 'flat_fee', 'quantity_based' ] )->contains( $addonData->get( 'price_type' ) ) ) {
118
+ return apply_filters( 'wcml_raw_price_amount', $addonData->get( 'price' ) );
119
+ }
120
+
121
+ return $addonData->get( 'price' );
122
+ }
123
+
124
+ /**
125
+ * @param int|false $productId
126
+ *
127
+ * @return bool|mixed
128
+ */
129
+ private function isProductCustomPricesOn( $productId ) {
130
+ if ( $productId ) {
131
+ return get_post_meta( $productId, '_wcml_custom_prices_status', true );
132
+ }
133
+
134
+ if ( SharedHooks::isGlobalAddonEditPage() ) {
135
+ return $this->getGlobalAddonPricesStatus();
136
+ }
137
+
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * @return bool|mixed
143
+ */
144
+ private function getGlobalAddonPricesStatus() {
145
+ if ( isset( $_GET['edit'] ) ) {
146
+ return get_post_meta( $_GET['edit'], '_wcml_custom_prices_status', true );
147
+ } elseif ( isset( $_POST['_wcml_custom_prices'] ) ) {
148
+ return $_POST['_wcml_custom_prices'];
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+ public function load_dialog_resources() {
155
+ wp_enqueue_script( 'wcml-dialogs', WCML_PLUGIN_URL . '/res/js/dialogs' . WCML_JS_MIN . '.js', [ 'jquery-ui-dialog', 'underscore' ], WCML_VERSION );
156
+ }
157
+
158
+ /**
159
+ * @param \WP_Post|null $product
160
+ * @param array $productAddons
161
+ * @param int $loop
162
+ * @param array $option
163
+ */
164
+ public function dialog_button_after_option_row( $product, $productAddons, $loop, $option ) {
165
+ if ( $option ) {
166
+ $this->renderEditPriceElement( $this->getPricesDialogModel( $productAddons, $option, $loop, $this->isProductCustomPricesOn( $product ? $product->ID : false ) ) );
167
+ }
168
+ }
169
+
170
+ /**
171
+ * @param \WP_Post|null $product
172
+ * @param array $productAddons
173
+ * @param int $loop
174
+ */
175
+ public function dialog_button_before_options( $product, $productAddons, $loop ) {
176
+ $this->renderEditPriceElement( $this->getPricesDialogModel( [], $productAddons, $loop, $this->isProductCustomPricesOn( $product ? $product->ID : false ) ) );
177
+ }
178
+
179
+ /**
180
+ * @param int $metaId
181
+ * @param int $id
182
+ */
183
+ public function onGlobalAddonsUpdated( $metaId, $id ) {
184
+ $this->update_custom_prices_values( $id );
185
+ }
186
+
187
+ /**
188
+ * @param string|int $productId
189
+ */
190
+ public function update_custom_prices_values( $productId ) {
191
+ $this->saveGlobalAddonPricesSetting( $productId );
192
+ $productAddons = SharedHooks::getProductAddons( $productId );
193
+
194
+ if ( $productAddons ) {
195
+ $activeCurrencies = $this->woocommerce_wpml->multi_currency->get_currencies();
196
+
197
+ foreach ( $productAddons as $addonKey => $productAddon ) {
198
+
199
+ foreach ( $activeCurrencies as $code => $currency ) {
200
+ $priceOptionKey = self::PRICE_OPTION_KEY;
201
+
202
+ if ( in_array( $productAddon['type'], self::getOnePriceTypes(), true ) ) {
203
+ $productAddons = $this->updateSingleOptionPrices( $productAddons, $priceOptionKey, $addonKey, $code );
204
+ } else {
205
+ $productAddons = $this->updateMultipleOptionsPrices( $productAddons, $priceOptionKey, $addonKey, $code );
206
+ }
207
+ }
208
+ }
209
+
210
+ update_post_meta( $productId, WCML_Product_Addons::ADDONS_OPTION_KEY, $productAddons );
211
+ }
212
+ }
213
+
214
+ /**
215
+ * @param array $productAddons
216
+ * @param string $priceOptionKey
217
+ * @param string $addonKey
218
+ * @param string $code
219
+ *
220
+ * @return array
221
+ */
222
+ private function updateSingleOptionPrices( $productAddons, $priceOptionKey, $addonKey, $code ) {
223
+ if ( isset( $_POST[ $priceOptionKey ][ $addonKey ][ 'price_' . $code ][0] ) ) {
224
+ $productAddons[ $addonKey ][ 'price_' . $code ] = wc_format_decimal( $_POST[ $priceOptionKey ][ $addonKey ][ 'price_' . $code ][0] );
225
+ }
226
+
227
+ return $productAddons;
228
+ }
229
+
230
+ /**
231
+ * @param array $productAddons
232
+ * @param string $priceOptionKey
233
+ * @param string $addonKey
234
+ * @param string $code
235
+ *
236
+ * @return array
237
+ */
238
+ private function updateMultipleOptionsPrices( $productAddons, $priceOptionKey, $addonKey, $code ) {
239
+ $addon_data = wpml_collect( $productAddons[ $addonKey ] );
240
+
241
+ if ( $addon_data->offsetExists( 'options' ) ) {
242
+ foreach ( $addon_data->get( 'options' ) as $option_key => $option ) {
243
+ if ( isset( $_POST[ $priceOptionKey ][ $addonKey ][ 'price_' . $code ][ $option_key ] ) ) {
244
+ $productAddons[ $addonKey ]['options'][ $option_key ][ 'price_' . $code ] = wc_format_decimal( $_POST[ $priceOptionKey ][ $addonKey ][ 'price_' . $code ][ $option_key ] );
245
+ }
246
+ }
247
+ }
248
+
249
+ return $productAddons;
250
+ }
251
+
252
+ public function custom_prices_settings_block() {
253
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
254
+ echo $this->getTwigLoader()->get_template()->show( $this->getCustomPricesSettingsModel(), self::SETTINGS_TEMPLATE );
255
+ }
256
+
257
+ /**
258
+ * @param array $model
259
+ */
260
+ private function renderEditPriceElement( $model ) {
261
+ // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
262
+ echo $this->getTwigLoader()->get_template()->show( $model, self::DIALOG_TEMPLATE );
263
+ }
264
+
265
+ /**
266
+ * @return WPML_Twig_Template_Loader
267
+ */
268
+ private function getTwigLoader() {
269
+ return new WPML_Twig_Template_Loader( [ WCML_PLUGIN_PATH . SharedHooks::TEMPLATE_FOLDER ] );
270
+ }
271
+
272
+ /**
273
+ * @return array
274
+ */
275
+ private function getCustomPricesSettingsModel() {
276
+ return [
277
+ 'strings' => [
278
+ 'label' => __( 'Multi-currency settings', 'woocommerce-multilingual' ),
279
+ 'auto' => __( 'Calculate prices in other currencies automatically', 'woocommerce-multilingual' ),
280
+ 'manually' => __( 'Set prices in other currencies manually', 'woocommerce-multilingual' ),
281
+ ],
282
+ 'custom_prices_on' => $this->getGlobalAddonPricesStatus(),
283
+ 'nonce' => wp_create_nonce( 'wcml_save_custom_prices' ),
284
+ ];
285
+ }
286
+
287
+ /**
288
+ * @param array $productAddons
289
+ * @param array $option
290
+ * @param int $loop
291
+ * @param string|bool $customPricesOn
292
+ *
293
+ * @return array
294
+ */
295
+ private function getPricesDialogModel( $productAddons, $option, $loop, $customPricesOn ) {
296
+
297
+ $label = isset( $option['label'] ) ? $option['label'] : $option['name'];
298
+
299
+ return [
300
+ 'strings' => [
301
+ 'dialog_title' => __( 'Multi-currency settings', 'woocommerce-multilingual' ),
302
+ /* translators: %s is an option label */
303
+ 'description' => sprintf( __( 'Here you can set different prices for the %s in multiple currencies:', 'woocommerce-multilingual' ), '<strong>' . $label . '</strong>' ),
304
+ 'apply' => __( 'Apply', 'woocommerce-multilingual' ),
305
+ 'cancel' => __( 'Cancel', 'woocommerce-multilingual' ),
306
+ ],
307
+ 'custom_prices_on' => $customPricesOn,
308
+ 'dialog_id' => '_product_addon_option_' . md5( uniqid( $loop . $label ) ),
309
+ 'option_id' => isset( $productAddons[ $loop ]['options'] ) ? array_search( $option, $productAddons[ $loop ]['options'] ) : '',
310
+ 'addon_id' => $loop,
311
+ 'option_details' => $option,
312
+ 'default_currency' => wcml_get_woocommerce_currency_option(),
313
+ 'active_currencies' => $this->woocommerce_wpml->multi_currency->get_currencies(),
314
+ ];
315
+ }
316
+
317
+ /**
318
+ * @param int $productId
319
+ */
320
+ private function saveGlobalAddonPricesSetting( $productId ) {
321
+ if ( SharedHooks::isGlobalAddon( $productId ) ) {
322
+ $nonce = filter_var( isset( $_POST['_wcml_custom_prices_nonce'] ) ? $_POST['_wcml_custom_prices_nonce'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
323
+
324
+ if ( isset( $_POST['_wcml_custom_prices'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' ) ) {
325
+ update_post_meta( $productId, '_wcml_custom_prices_status', $_POST['_wcml_custom_prices'] );
326
+ }
327
+ }
328
+ }
329
+
330
+ /**
331
+ * @return array
332
+ */
333
+ private static function getOnePriceTypes() {
334
+ return [
335
+ 'custom_text',
336
+ 'custom_textarea',
337
+ 'file_upload',
338
+ 'input_multiplier',
339
+ ];
340
+ }
341
+ }
compatibility/WcProductAddons/SharedHooks.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductAddons;
4
+
5
+ use WPML\FP\Fns;
6
+
7
+ class SharedHooks implements \IWPML_Action {
8
+
9
+ const TEMPLATE_FOLDER = '/templates/compatibility/';
10
+ const ADDONS_OPTION_KEY = '_product_addons';
11
+
12
+ public function add_hooks() {
13
+ $withoutRecursion = Fns::withoutRecursion( Fns::noop() );
14
+
15
+ add_action( 'init', [ $this, 'loadAssets' ] );
16
+ add_action( 'updated_post_meta', $withoutRecursion( [ $this, 'triggerGlobalAddonUpdated' ] ), 10, 4 );
17
+ add_action( 'added_post_meta', $withoutRecursion( [ $this, 'triggerGlobalAddonUpdated' ] ), 10, 4 );
18
+ }
19
+
20
+ public function loadAssets() {
21
+ global $pagenow;
22
+
23
+ $isProductPage = 'post.php' === $pagenow && isset( $_GET['post'] );
24
+ $isProductNewPage = 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'];
25
+
26
+ if ( $isProductPage || $isProductNewPage || self::isGlobalAddonEditPage() ) {
27
+ wp_enqueue_script( 'wcml-product-addons', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-product-addons' . WCML_JS_MIN . '.js', [ 'jquery' ], WCML_VERSION );
28
+ wp_enqueue_style( 'wcml-product-addons', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-product-addons.css', [ 'wpml-dialog' ], WCML_VERSION );
29
+ }
30
+ }
31
+
32
+ /**
33
+ * @return bool
34
+ */
35
+ public static function isGlobalAddonEditPage() {
36
+ global $pagenow;
37
+
38
+ return 'edit.php' === $pagenow &&
39
+ isset( $_GET['post_type'] ) &&
40
+ 'product' === $_GET['post_type'] &&
41
+ isset( $_GET['page'] ) &&
42
+ ( 'global_addons' === $_GET['page'] || 'addons' === $_GET['page'] );
43
+ }
44
+
45
+ /**
46
+ * @param int $metaId
47
+ * @param int $id
48
+ * @param string $metaKey
49
+ * @param array $addons
50
+ */
51
+ public function triggerGlobalAddonUpdated( $metaId, $id, $metaKey, $addons ) {
52
+ if ( self::ADDONS_OPTION_KEY === $metaKey && self::isGlobalAddon( $id ) ) {
53
+ do_action( 'wcml_product_addons_global_updated', $metaId, $id, $metaKey, $addons );
54
+ }
55
+ }
56
+
57
+ /**
58
+ * @param int $postId
59
+ *
60
+ * @return bool
61
+ */
62
+ public static function isGlobalAddon( $postId ) {
63
+ return 'global_product_addon' === get_post_type( $postId );
64
+ }
65
+
66
+ /**
67
+ * @param string $productId
68
+ *
69
+ * @return array
70
+ */
71
+ public static function getProductAddons( $productId ) {
72
+ $data = get_post_meta( $productId, self::ADDONS_OPTION_KEY, true );
73
+ return $data ? maybe_unserialize( $data ) : [];
74
+ }
75
+ }
compatibility/WcProductAddons/class-wcml-product-addons.php ADDED
@@ -0,0 +1,397 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use WCML\Compatibility\WcProductAddons\SharedHooks;
4
+ use WCML\Options\WPML;
5
+ use WPML\FP\Obj;
6
+ use WPML\FP\Str;
7
+
8
+ /**
9
+ * Class WCML_Product_Addons
10
+ */
11
+ class WCML_Product_Addons implements \IWPML_Action {
12
+
13
+ const ADDONS_OPTION_KEY = SharedHooks::ADDONS_OPTION_KEY;
14
+
15
+ /**
16
+ * @var SitePress
17
+ */
18
+ public $sitepress;
19
+
20
+ /**
21
+ * WCML_Product_Addons constructor.
22
+ *
23
+ * @param SitePress $sitepress
24
+ * @param woocommerce_wpml $woocommerce_wpml
25
+ */
26
+ public function __construct( SitePress $sitepress ) {
27
+ $this->sitepress = $sitepress;
28
+ }
29
+
30
+ public function add_hooks() {
31
+ add_filter( 'get_product_addons_product_terms', [ $this, 'addons_product_terms' ] );
32
+ add_action( 'wcml_product_addons_global_updated', [ $this, 'register_addons_strings' ], 10, 4 );
33
+ add_action( 'woocommerce-product-addons_panel_start', [ $this, 'show_pointer_info' ] );
34
+
35
+ if ( WPML::useAte() ) {
36
+ add_action( 'wpml_pro_translation_completed', [ $this, 'save_addons_to_translation' ], 10, 3 );
37
+ }
38
+
39
+ if ( is_admin() ) {
40
+
41
+ if ( SharedHooks::isGlobalAddonEditPage() ) {
42
+ if ( ! isset( $_GET['edit'] ) ) {
43
+ add_action( 'admin_notices', [ $this, 'inf_translate_strings' ] );
44
+ }
45
+ }
46
+
47
+ if ( WPML::useAte() ) {
48
+ add_filter( 'wpml_tm_translation_job_data', [ $this, 'append_addons_to_translation_package' ], 10, 2 );
49
+ } else {
50
+ add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
51
+ add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 3 );
52
+ add_action( 'wcml_update_extra_fields', [ $this, 'addons_update' ], 10, 3 );
53
+ }
54
+
55
+ add_action( 'woocommerce_product_data_panels', [ $this, 'show_pointer_info' ] );
56
+
57
+ add_filter( 'wcml_do_not_display_custom_fields_for_product', [ $this, 'replace_tm_editor_custom_fields_with_own_sections' ] );
58
+ } else {
59
+ add_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10, 4 );
60
+ }
61
+
62
+ add_filter(
63
+ 'get_product_addons_global_query_args',
64
+ [
65
+ $this,
66
+ 'set_global_ids_in_query_args',
67
+ ]
68
+ );
69
+ }
70
+
71
+ /**
72
+ * @param $meta_id
73
+ * @param $id
74
+ * @param $meta_key
75
+ * @param $addons
76
+ */
77
+ public function register_addons_strings( $meta_id, $id, $meta_key, $addons ) {
78
+ if ( self::ADDONS_OPTION_KEY === $meta_key && 'global_product_addon' === get_post_type( $id ) ) {
79
+ foreach ( $addons as $addon ) {
80
+ $addon_data = wpml_collect( $addon );
81
+ $addon_type = $addon_data->get( 'type' );
82
+ $addon_position = $addon_data->get( 'position' );
83
+ // register name
84
+ do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_name', $addon_data->get( 'name' ) );
85
+ // register description
86
+ do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_description', $addon_data->get( 'description' ) );
87
+ // register options labels
88
+ if ( $addon_data->offsetExists( 'options' ) ) {
89
+ foreach ( $addon_data->get( 'options' ) as $key => $option ) {
90
+ do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_option_label_' . $key, wpml_collect( $option )->get( 'label' ) );
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * @param $null
99
+ * @param $object_id
100
+ * @param $meta_key
101
+ * @param $single
102
+ *
103
+ * @return array
104
+ */
105
+ public function translate_addons_strings( $null, $object_id, $meta_key, $single ) {
106
+
107
+ if ( self::ADDONS_OPTION_KEY === $meta_key && 'global_product_addon' === get_post_type( $object_id ) ) {
108
+
109
+ remove_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10 );
110
+ $addons = get_post_meta( $object_id, $meta_key, true );
111
+ add_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10, 4 );
112
+
113
+ if ( is_array( $addons ) ) {
114
+ foreach ( $addons as $key => $addon ) {
115
+ $addon_data = wpml_collect( $addon );
116
+ $addon_type = $addon_data->get( 'type' );
117
+ $addon_position = $addon_data->get( 'position' );
118
+ // register name
119
+ $addons[ $key ]['name'] = apply_filters( 'wpml_translate_single_string', $addon_data->get( 'name' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_name' );
120
+ // register description
121
+ $addons[ $key ]['description'] = apply_filters( 'wpml_translate_single_string', $addon_data->get( 'description' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_description' );
122
+ // register options labels
123
+ if ( $addon_data->offsetExists( 'options' ) ) {
124
+ foreach ( $addon['options'] as $opt_key => $option ) {
125
+ $addons[ $key ]['options'][ $opt_key ]['label'] = apply_filters( 'wpml_translate_single_string', wpml_collect( $option )->get( 'label' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_option_label_' . $opt_key );
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ return [ 0 => $addons ];
132
+ }
133
+
134
+ return $null;
135
+
136
+ }
137
+
138
+ /**
139
+ * @param $product_terms
140
+ *
141
+ * @return array
142
+ */
143
+ public function addons_product_terms( $product_terms ) {
144
+ foreach ( $product_terms as $key => $product_term ) {
145
+ $product_terms[ $key ] = apply_filters( 'translate_object_id', $product_term, 'product_cat', true, $this->sitepress->get_default_language() );
146
+ }
147
+
148
+ return $product_terms;
149
+ }
150
+
151
+ public function inf_translate_strings() {
152
+
153
+ $pointer_ui = new WCML_Pointer_UI(
154
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
155
+ sprintf( __( 'You can translate strings related to global add-ons on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=wc_product_addons_strings' ) . '">', '</a>' ),
156
+ WCML_Tracking_Link::getWcmlProductAddonsDoc(),
157
+ 'wpbody-content .woocommerce>h2'
158
+ );
159
+
160
+ $pointer_ui->show();
161
+ }
162
+
163
+ /**
164
+ * @param array $package
165
+ * @param \WP_Post $post
166
+ *
167
+ * @return array
168
+ */
169
+ public function append_addons_to_translation_package( $package, $post ) {
170
+ if ( 'product' === $post->post_type ) {
171
+ $add_field = function( $name, $value ) use ( &$package ) {
172
+ if ( $value ) {
173
+ $package['contents'][ $name ] = [
174
+ 'translate' => 1,
175
+ 'data' => base64_encode( $value ),
176
+ 'format' => 'base64',
177
+ ];
178
+ }
179
+ };
180
+
181
+ foreach ( SharedHooks::getProductAddons( $post->ID ) as $addon_id => $addon_data ) {
182
+ $add_field( self::get_job_field_name( $addon_id, 'name' ), Obj::prop( 'name', $addon_data ) );
183
+ $add_field( self::get_job_field_name( $addon_id, 'description' ), Obj::prop( 'description', $addon_data ) );
184
+
185
+ foreach ( (array) Obj::prop( 'options', $addon_data ) as $option_id => $option ) {
186
+ $add_field( self::get_job_field_name( $addon_id, $option_id ), Obj::prop( 'label', $option ) );
187
+ }
188
+ }
189
+ }
190
+
191
+ return $package;
192
+ }
193
+
194
+ /**
195
+ * @param int $post_id
196
+ * @param array $fields
197
+ * @param object $job
198
+ */
199
+ public function save_addons_to_translation( $post_id, $fields, $job ) {
200
+ if (
201
+ Str::startsWith( 'post_', $job->original_post_type )
202
+ && 'product' === get_post_type( $post_id )
203
+ ) {
204
+ $get_translation = function( $field_name ) use ( $fields ) {
205
+ return Obj::path( [ $field_name, 'data' ], $fields );
206
+ };
207
+
208
+ $addons = SharedHooks::getProductAddons( $post_id );
209
+
210
+ foreach ( $addons as $addon_id => $addon_data ) {
211
+ if ( isset( $addons[ $addon_id ]['name'] ) ) {
212
+ $addons[ $addon_id ]['name'] = $get_translation( self::get_job_field_name( $addon_id, 'name' ) );
213
+ $addons[ $addon_id ]['description'] = $get_translation( self::get_job_field_name( $addon_id, 'description' ) );
214
+ }
215
+
216
+ foreach ( (array) Obj::prop( 'options', $addon_data ) as $option_id => $option ) {
217
+ if ( isset( $addons[ $addon_id ]['options'][ $option_id ]['label'] ) ) {
218
+ $addons[ $addon_id ]['options'][ $option_id ]['label'] = $get_translation( self::get_job_field_name( $addon_id, $option_id ) );
219
+ }
220
+ }
221
+ }
222
+
223
+ update_post_meta( $post_id, self::ADDONS_OPTION_KEY, $addons );
224
+ }
225
+ }
226
+
227
+ /**
228
+ * @param int $addon_id
229
+ * @param int|string $name_or_id
230
+ *
231
+ * @return string
232
+ */
233
+ private static function get_job_field_name( $addon_id, $name_or_id ) {
234
+ return is_numeric( $name_or_id )
235
+ ? 'addon_' . $addon_id . '_option_' . $name_or_id . '_label'
236
+ : 'addon_' . $addon_id . '_' . $name_or_id;
237
+ }
238
+
239
+ /**
240
+ * @deprecated This method is used by CTE only.
241
+ *
242
+ * @param $obj
243
+ * @param $product_id
244
+ * @param $data
245
+ */
246
+ public function custom_box_html( $obj, $product_id, $data ) {
247
+
248
+ $product_addons = SharedHooks::getProductAddons( $product_id );
249
+
250
+ if ( ! empty( $product_addons ) ) {
251
+ foreach ( $product_addons as $addon_id => $product_addon ) {
252
+ $addon_data = wpml_collect( $product_addon );
253
+
254
+ /* translators: %s is a product addon name */
255
+ $addons_section = new WPML_Editor_UI_Field_Section( sprintf( __( 'Product Add-ons Group "%s"', 'woocommerce-multilingual' ), $addon_data->get( 'name' ) ) );
256
+
257
+ $group = new WPML_Editor_UI_Field_Group( '', true );
258
+ $addon_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_name', __( 'Name', 'woocommerce-multilingual' ), $data, false );
259
+ $group->add_field( $addon_field );
260
+ $addon_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_description', __( 'Description', 'woocommerce-multilingual' ), $data, false );
261
+ $group->add_field( $addon_field );
262
+
263
+ $addons_section->add_field( $group );
264
+
265
+ if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
266
+
267
+ $labels_group = new WPML_Editor_UI_Field_Group( __( 'Options', 'woocommerce-multilingual' ), true );
268
+
269
+ foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
270
+ $option_label_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_option_' . $option_id . '_label', __( 'Label', 'woocommerce-multilingual' ), $data, false );
271
+ $labels_group->add_field( $option_label_field );
272
+ }
273
+ $addons_section->add_field( $labels_group );
274
+ }
275
+ $obj->add_field( $addons_section );
276
+ }
277
+ }
278
+ }
279
+
280
+ /**
281
+ * @deprecated This method is used by CTE only.
282
+ *
283
+ * @param $data
284
+ * @param $product_id
285
+ * @param $translation
286
+ *
287
+ * @return mixed
288
+ */
289
+ public function custom_box_html_data( $data, $product_id, $translation ) {
290
+
291
+ $product_addons = SharedHooks::getProductAddons( $product_id );
292
+
293
+ if ( ! empty( $product_addons ) ) {
294
+ foreach ( $product_addons as $addon_id => $product_addon ) {
295
+ $addon_data = wpml_collect( $product_addon );
296
+ $data[ 'addon_' . $addon_id . '_name' ] = [ 'original' => $addon_data->get( 'name' ) ];
297
+ $data[ 'addon_' . $addon_id . '_description' ] = [ 'original' => $addon_data->get( 'description' ) ];
298
+ if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
299
+ foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
300
+ $data[ 'addon_' . $addon_id . '_option_' . $option_id . '_label' ] = [ 'original' => wpml_collect( $option )->get( 'label' ) ];
301
+ }
302
+ }
303
+ }
304
+
305
+ if ( $translation ) {
306
+ $translated_product_addons = SharedHooks::getProductAddons( $translation->ID );
307
+ if ( ! empty( $translated_product_addons ) ) {
308
+ foreach ( $translated_product_addons as $addon_id => $transalted_product_addon ) {
309
+ $translated_addon_data = wpml_collect( $transalted_product_addon );
310
+ $data[ 'addon_' . $addon_id . '_name' ]['translation'] = $translated_addon_data->get( 'name' );
311
+ $data[ 'addon_' . $addon_id . '_description' ]['translation'] = $translated_addon_data->get( 'description' );
312
+ if ( $translated_addon_data->offsetExists( 'options' ) && $translated_addon_data->get( 'options' ) ) {
313
+ foreach ( $translated_addon_data->get( 'options' ) as $option_id => $option ) {
314
+ $data[ 'addon_' . $addon_id . '_option_' . $option_id . '_label' ]['translation'] = wpml_collect( $option )->get( 'label' );
315
+ }
316
+ }
317
+ }
318
+ }
319
+ }
320
+ }
321
+
322
+ return $data;
323
+ }
324
+
325
+ /**
326
+ * @deprecated This method is used by CTE only.
327
+ *
328
+ * @param $original_product_id
329
+ * @param $product_id
330
+ * @param $data
331
+ */
332
+ public function addons_update( $original_product_id, $product_id, $data ) {
333
+
334
+ $product_addons = SharedHooks::getProductAddons( $original_product_id );
335
+
336
+ if ( ! empty( $product_addons ) ) {
337
+
338
+ foreach ( $product_addons as $addon_id => $product_addon ) {
339
+ $addon_data = wpml_collect( $product_addon );
340
+ $product_addons[ $addon_id ]['name'] = $data[ md5( 'addon_' . $addon_id . '_name' ) ];
341
+ $product_addons[ $addon_id ]['description'] = $data[ md5( 'addon_' . $addon_id . '_description' ) ];
342
+
343
+ if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
344
+ foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
345
+ $product_addons[ $addon_id ]['options'][ $option_id ]['label'] = $data[ md5( 'addon_' . $addon_id . '_option_' . $option_id . '_label' ) ];
346
+ }
347
+ }
348
+ }
349
+ }
350
+
351
+ update_post_meta( $product_id, self::ADDONS_OPTION_KEY, $product_addons );
352
+ }
353
+
354
+ public function show_pointer_info() {
355
+
356
+ $pointer_ui = new WCML_Pointer_UI(
357
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
358
+ sprintf( __( 'You can translate the Group Name, Group Description and every Option Label of your product add-on on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
359
+ WCML_Tracking_Link::getWcmlProductAddonsDoc(),
360
+ 'product_addons_data>p'
361
+ );
362
+
363
+ $pointer_ui->show();
364
+ }
365
+
366
+ public function replace_tm_editor_custom_fields_with_own_sections( $fields ) {
367
+ $fields[] = self::ADDONS_OPTION_KEY;
368
+
369
+ return $fields;
370
+ }
371
+
372
+ public function set_global_ids_in_query_args( $args ) {
373
+
374
+ if ( ! is_archive() ) {
375
+
376
+ remove_filter( 'get_terms_args', [ $this->sitepress, 'get_terms_args_filter' ], 10 );
377
+ remove_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1 );
378
+ remove_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ], 10 );
379
+
380
+ $matched_addons_ids = get_posts( $args );
381
+ if ( is_object( reset( $matched_addons_ids ) ) ) {
382
+ $matched_addons_ids = wp_list_pluck( $matched_addons_ids, 'ID' );
383
+ }
384
+
385
+ if ( $matched_addons_ids ) {
386
+ $args['include'] = $matched_addons_ids;
387
+ unset( $args['tax_query'] );
388
+ }
389
+
390
+ add_filter( 'get_terms_args', [ $this->sitepress, 'get_terms_args_filter' ], 10, 2 );
391
+ add_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1 );
392
+ add_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ], 10, 3 );
393
+ }
394
+
395
+ return $args;
396
+ }
397
+ }
compatibility/WcProductBundles/Factory.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductBundles;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_Product_Bundles;
8
+ use WCML_WC_Product_Bundles_Items;
9
+ use function WCML\functions\getSitePress;
10
+ use function WCML\functions\getWooCommerceWpml;
11
+ use function WCML\functions\isStandAlone;
12
+
13
+ class Factory extends ComponentFactory implements IStandAloneAction {
14
+
15
+ /**
16
+ * @inheritDoc
17
+ */
18
+ public function create() {
19
+ $hooks = [];
20
+
21
+ if ( wcml_is_multi_currency_on() ) {
22
+ $hooks[] = new MulticurrencyHooks();
23
+ }
24
+
25
+ if ( ! isStandAlone() ) {
26
+ $hooks[] = new WCML_Product_Bundles( getSitePress(), getWooCommerceWpml(), new WCML_WC_Product_Bundles_Items(), self::getWpdb() );
27
+ }
28
+
29
+ return $hooks;
30
+ }
31
+ }
compatibility/WcProductBundles/MulticurrencyHooks.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductBundles;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
+
7
+ public function add_hooks() {
8
+ add_filter( 'wcml_price_custom_fields_filtered', [ $this, 'getPriceCustomFields' ], 10, 2 );
9
+ add_filter( 'wcml_update_custom_prices_values', [ $this, 'updateBundlesCustomPricesValues' ], 10, 2 );
10
+ add_action( 'wcml_after_save_custom_prices', [ $this, 'updateBundlesBasePrice' ], 10, 4 );
11
+ }
12
+
13
+ /**
14
+ * @param array $customFields
15
+ *
16
+ * @return array
17
+ */
18
+ public function getPriceCustomFields( $customFields ) {
19
+ return array_merge(
20
+ $customFields,
21
+ [
22
+ '_wc_pb_base_regular_price',
23
+ '_wc_pb_base_sale_price',
24
+ '_wc_pb_base_price',
25
+ '_wc_sw_max_price',
26
+ '_wc_sw_max_regular_price',
27
+ ]
28
+ );
29
+ }
30
+
31
+ /**
32
+ * @param array $prices
33
+ * @param string $code
34
+ *
35
+ * @return array
36
+ */
37
+ public function updateBundlesCustomPricesValues( $prices, $code ) {
38
+ // phpcs:disable
39
+ if ( isset( $_POST['_custom_regular_price'][ $code ] ) ) {
40
+ $prices['_wc_pb_base_regular_price'] = wc_format_decimal( $_POST['_custom_regular_price'][ $code ] );
41
+ }
42
+
43
+ if ( isset( $_POST['_custom_sale_price'][ $code ] ) ) {
44
+ $prices['_wc_pb_base_sale_price'] = wc_format_decimal( $_POST['_custom_sale_price'][ $code ] );
45
+ }
46
+
47
+ return $prices;
48
+ // phpcs:enable
49
+ }
50
+
51
+ /**
52
+ * @param int|string $postId
53
+ * @param string $productPrice
54
+ * @param array $customPrices
55
+ * @param string $code
56
+ *
57
+ * @return void
58
+ */
59
+ public function updateBundlesBasePrice( $postId, $productPrice, $customPrices, $code ) {
60
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
61
+ if ( isset( $customPrices['_wc_pb_base_regular_price'] ) ) {
62
+ update_post_meta( $postId, '_wc_pb_base_price_' . $code, $productPrice );
63
+ }
64
+ }
65
+ }
compatibility/{class-wcml-product-bundles.php → WcProductBundles/class-wcml-product-bundles.php} RENAMED
@@ -1,8 +1,15 @@
1
  <?php
2
 
 
 
3
  use WPML\FP\Obj;
 
4
 
5
- class WCML_Product_Bundles {
 
 
 
 
6
 
7
  /**
8
  * @var WPML_Element_Translation_Package
@@ -33,15 +40,21 @@ class WCML_Product_Bundles {
33
  * WCML_Product_Bundles constructor.
34
  */
35
  public function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, $product_bundles_items, wpdb $wpdb ) {
36
-
37
  $this->sitepress = $sitepress;
38
  $this->woocommerce_wpml = $woocommerce_wpml;
39
  $this->product_bundles_items = $product_bundles_items;
40
  $this->wpdb = $wpdb;
 
41
 
 
42
  add_action( 'woocommerce_get_cart_item_from_session', [ $this, 'resync_bundle' ], 5, 3 );
43
  add_filter( 'woocommerce_cart_loaded_from_session', [ $this, 'resync_bundle_clean' ], 10 );
44
- add_action( 'wpml_translation_job_saved', [ $this, 'save_bundle_data_translation' ], 10, 3 );
 
 
 
 
 
45
 
46
  if ( is_admin() ) {
47
  $this->tp = new WPML_Element_Translation_Package();
@@ -56,11 +69,13 @@ class WCML_Product_Bundles {
56
  2
57
  );
58
 
59
- add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
60
- add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
 
 
 
61
 
62
  add_action( 'wcml_after_duplicate_product_post_meta', [ $this, 'sync_bundled_ids' ], 10, 2 );
63
- add_action( 'wcml_update_extra_fields', [ $this, 'bundle_update' ], 10, 4 );
64
 
65
  add_action( 'wp_insert_post', [ $this, 'sync_product_bundle_meta_with_translations' ], 10 );
66
 
@@ -69,17 +84,15 @@ class WCML_Product_Bundles {
69
  add_action( 'woocommerce_before_delete_bundled_item', [ $this, 'delete_bundled_item_relationship' ] );
70
  }
71
 
72
- // product bundle using separate custom fields for prices.
73
- if ( wcml_is_multi_currency_on() ) {
74
- add_filter( 'wcml_price_custom_fields_filtered', [ $this, 'get_price_custom_fields' ], 10, 2 );
75
- add_filter( 'wcml_update_custom_prices_values', [ $this, 'update_bundles_custom_prices_values' ], 10, 2 );
76
- add_filter( 'wcml_after_save_custom_prices', [ $this, 'update_bundles_base_price' ], 10, 4 );
77
- }
78
-
79
  add_action( 'init', [ $this, 'upgrade_bundles_items_relationships' ] );
80
-
81
  }
82
 
 
 
 
 
 
83
  private function get_product_bundle_data( $bundle_id ) {
84
  $product_bundle_data = [];
85
 
@@ -91,7 +104,12 @@ class WCML_Product_Bundles {
91
  return $product_bundle_data;
92
  }
93
 
 
 
 
 
94
  private function save_product_bundle_data( $bundle_id, $product_bundle_data ) {
 
95
 
96
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
97
 
@@ -106,6 +124,15 @@ class WCML_Product_Bundles {
106
 
107
  }
108
 
 
 
 
 
 
 
 
 
 
109
  public function sync_product_bundle_meta( $bundle_id, $translated_bundle_id ) {
110
 
111
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
@@ -179,27 +206,45 @@ class WCML_Product_Bundles {
179
  }
180
 
181
  public function sync_product_bundle_meta_with_translations( $bundle_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
182
 
183
- if ( $this->is_bundle_product( $bundle_id ) ) {
 
 
 
184
 
185
- $trid = $this->sitepress->get_element_trid( $bundle_id, 'post_product' );
186
- $translations = $this->sitepress->get_element_translations( $trid, 'post_product' );
187
- $original_bundle_id = null;
188
 
189
- foreach ( $translations as $language => $translation ) {
190
- if ( $translation->original ) {
191
- $original_bundle_id = $translation->element_id;
192
- break;
193
- }
194
- }
195
 
196
- foreach ( $translations as $language => $translation ) {
197
- if ( $original_bundle_id && $translation->element_id !== $original_bundle_id ) {
198
- $this->sync_product_bundle_meta( $original_bundle_id, $translation->element_id );
199
- }
200
- }
 
201
  }
202
 
 
 
 
 
 
 
 
 
 
203
  }
204
 
205
  /**
@@ -257,8 +302,8 @@ class WCML_Product_Bundles {
257
  }
258
 
259
  /**
260
- * @param array $item_id
261
- * @param string $language
262
  *
263
  * @return string
264
  */
@@ -292,7 +337,17 @@ class WCML_Product_Bundles {
292
 
293
  }
294
 
295
- // Add Bundles Box to WCML Translation GUI.
 
 
 
 
 
 
 
 
 
 
296
  public function custom_box_html( $obj, $bundle_id, $data ) {
297
 
298
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
@@ -357,6 +412,16 @@ class WCML_Product_Bundles {
357
 
358
  }
359
 
 
 
 
 
 
 
 
 
 
 
360
  public function custom_box_html_data( $data, $bundle_id, $translation, $lang ) {
361
 
362
  $bundle_data = $this->get_product_bundle_data( $bundle_id );
@@ -403,6 +468,17 @@ class WCML_Product_Bundles {
403
  return $data;
404
  }
405
 
 
 
 
 
 
 
 
 
 
 
 
406
  public function append_bundle_data_translation_package( $package, $post ) {
407
 
408
  if ( $post->post_type == 'product' ) {
@@ -418,7 +494,7 @@ class WCML_Product_Bundles {
418
  $product_id = $this->get_product_id_for_item_id( $item_id );
419
  foreach ( $fields as $field ) {
420
  if ( $product_data[ 'override_' . $field ] == 'yes' && ! empty( $product_data[ $field ] ) ) {
421
- $package['contents'][ 'product_bundles:' . $product_id . ':' . $item_id . ':' . $field ] = [
422
  'translate' => 1,
423
  'data' => $this->tp->encode_field_data( $product_data[ $field ], 'base64' ),
424
  'format' => 'base64',
@@ -427,15 +503,99 @@ class WCML_Product_Bundles {
427
  }
428
  }
429
  }
 
 
 
 
 
 
 
 
 
 
430
  }
431
 
432
  return $package;
433
 
434
  }
435
 
436
- // Update Bundled products title and description after saving the translation.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  public function bundle_update( $bundle_id, $translated_bundle_id, $data, $lang ) {
 
 
 
 
438
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  $bundle_data = $this->get_product_bundle_data( $bundle_id );
440
  $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id );
441
 
@@ -453,7 +613,7 @@ class WCML_Product_Bundles {
453
  foreach ( $bundle_data as $item_id => $bundle_item_data ) {
454
 
455
  $product_id = $this->get_product_id_for_item_id( $item_id );
456
- $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $lang );
457
 
458
  if ( $translated_product_id ) {
459
 
@@ -480,29 +640,28 @@ class WCML_Product_Bundles {
480
  );
481
 
482
  $translated_item_id = $this->wpdb->insert_id;
483
- $this->set_translated_item_id_relationship( $item_id, $translated_item_id, $lang );
484
  }
485
 
486
- $translated_item_id = $this->get_item_id_for_language( $item_id, $lang );
487
 
488
- // $this->product_bundles_items->copy_item_data( $item_id, $translated_item_id );
489
- if ( isset( $data[ md5( 'bundle_' . $product_id . '_title' ) ] ) ) {
490
- $translated_bundle_data[ $translated_item_id ]['title'] = $data[ md5( 'bundle_' . $product_id . '_title' ) ];
491
- $translated_bundle_data[ $translated_item_id ]['override_title'] = $bundle_item_data['override_title'];
492
- }
493
 
494
- if ( isset( $data[ md5( 'bundle_' . $product_id . '_desc' ) ] ) ) {
495
- $translated_bundle_data[ $translated_item_id ]['description'] = $data[ md5( 'bundle_' . $product_id . '_desc' ) ];
496
- $translated_bundle_data[ $translated_item_id ]['override_description'] = $bundle_item_data['override_description'];
 
497
  }
498
 
499
  if ( isset( $bundle_item_data['allowed_variations'] ) ) {
500
  if ( is_array( $bundle_item_data['allowed_variations'] ) ) {
501
- $translated_bundle_data[ $translated_item_id ]['allowed_variations'] =
502
- $this->translate_allowed_variations( $bundle_item_data['allowed_variations'], $lang );
503
  } else {
504
- $translated_bundle_data[ $translated_item_id ]['allowed_variations'] =
505
- $bundle_item_data['allowed_variations'];
506
  }
507
  }
508
  }
@@ -692,6 +851,13 @@ class WCML_Product_Bundles {
692
  }
693
  }
694
 
 
 
 
 
 
 
 
695
  public function save_bundle_data_translation( $translated_bundle_id, $data, $job ) {
696
 
697
  if ( $this->is_bundle_product( $translated_bundle_id ) ) {
@@ -780,50 +946,6 @@ class WCML_Product_Bundles {
780
  return $translated_item_id;
781
  }
782
 
783
- /**
784
- * @param array $custom_fields
785
- *
786
- * @return array
787
- */
788
- public function get_price_custom_fields( $custom_fields ) {
789
-
790
- $custom_fields = array_merge(
791
- $custom_fields,
792
- [
793
- '_wc_pb_base_regular_price',
794
- '_wc_pb_base_sale_price',
795
- '_wc_pb_base_price',
796
- '_wc_sw_max_price',
797
- '_wc_sw_max_regular_price',
798
- ]
799
- );
800
-
801
- return $custom_fields;
802
- }
803
-
804
-
805
- public function update_bundles_custom_prices_values( $prices, $code ) {
806
-
807
- if ( isset( $_POST['_custom_regular_price'][ $code ] ) ) {
808
- $prices['_wc_pb_base_regular_price'] = wc_format_decimal( $_POST['_custom_regular_price'][ $code ] );
809
- }
810
-
811
- if ( isset( $_POST['_custom_sale_price'][ $code ] ) ) {
812
- $prices['_wc_pb_base_sale_price'] = wc_format_decimal( $_POST['_custom_sale_price'][ $code ] );
813
- }
814
-
815
- return $prices;
816
-
817
- }
818
-
819
- public function update_bundles_base_price( $post_id, $product_price, $custom_prices, $code ) {
820
-
821
- if ( isset( $custom_prices['_wc_pb_base_regular_price'] ) ) {
822
- update_post_meta( $post_id, '_wc_pb_base_price_' . $code, $product_price );
823
- }
824
-
825
- }
826
-
827
  public function is_bundle_product( $product_id ) {
828
 
829
  $product = wc_get_product( $product_id );
@@ -904,4 +1026,13 @@ class WCML_Product_Bundles {
904
 
905
  }
906
 
 
 
 
 
 
 
 
 
 
907
  }
1
  <?php
2
 
3
+ use WCML\Options\WPML;
4
+ use WPML\FP\Fns;
5
  use WPML\FP\Obj;
6
+ use WPML\FP\Str;
7
 
8
+ class WCML_Product_Bundles implements \IWPML_Action {
9
+
10
+ const META_SELL_IDS = '_wc_pb_bundle_sell_ids';
11
+ const META_SELLS_TITLE = '_wc_pb_bundle_sells_title';
12
+ const META_SELLS_DISCOUNT = '_wc_pb_bundle_sells_discount';
13
 
14
  /**
15
  * @var WPML_Element_Translation_Package
40
  * WCML_Product_Bundles constructor.
41
  */
42
  public function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml, $product_bundles_items, wpdb $wpdb ) {
 
43
  $this->sitepress = $sitepress;
44
  $this->woocommerce_wpml = $woocommerce_wpml;
45
  $this->product_bundles_items = $product_bundles_items;
46
  $this->wpdb = $wpdb;
47
+ }
48
 
49
+ public function add_hooks() {
50
  add_action( 'woocommerce_get_cart_item_from_session', [ $this, 'resync_bundle' ], 5, 3 );
51
  add_filter( 'woocommerce_cart_loaded_from_session', [ $this, 'resync_bundle_clean' ], 10 );
52
+
53
+ if ( WPML::useAte() ) {
54
+ add_action( 'wpml_pro_translation_completed', [ $this, 'save_product_bundles_to_translation' ], 10, 3 );
55
+ } else { // Legacy action for CTE
56
+ add_action( 'wpml_translation_job_saved', [ $this, 'save_bundle_data_translation' ], 10, 3 );
57
+ }
58
 
59
  if ( is_admin() ) {
60
  $this->tp = new WPML_Element_Translation_Package();
69
  2
70
  );
71
 
72
+ if ( ! WPML::useAte() ) { // Legacy actions/filters for CTE
73
+ add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
74
+ add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 4 );
75
+ add_action( 'wcml_update_extra_fields', [ $this, 'bundle_update' ], 10, 4 );
76
+ }
77
 
78
  add_action( 'wcml_after_duplicate_product_post_meta', [ $this, 'sync_bundled_ids' ], 10, 2 );
 
79
 
80
  add_action( 'wp_insert_post', [ $this, 'sync_product_bundle_meta_with_translations' ], 10 );
81
 
84
  add_action( 'woocommerce_before_delete_bundled_item', [ $this, 'delete_bundled_item_relationship' ] );
85
  }
86
 
 
 
 
 
 
 
 
87
  add_action( 'init', [ $this, 'upgrade_bundles_items_relationships' ] );
88
+ add_filter( 'wpml_custom_field_values_for_post_signature', [ __CLASS__, 'adjust_bundle_sells_product_signature' ], 10, 2 );
89
  }
90
 
91
+ /**
92
+ * @param string|int $bundle_id
93
+ *
94
+ * @return array
95
+ */
96
  private function get_product_bundle_data( $bundle_id ) {
97
  $product_bundle_data = [];
98
 
104
  return $product_bundle_data;
105
  }
106
 
107
+ /**
108
+ * @param string|int $bundle_id
109
+ * @param array $product_bundle_data
110
+ */
111
  private function save_product_bundle_data( $bundle_id, $product_bundle_data ) {
112
+ self::flush_bundle_cache( $bundle_id );
113
 
114
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
115
 
124
 
125
  }
126
 
127
+ /**
128
+ * @see \WC_Product_Bundle::get_bundled_data_items
129
+ *
130
+ * @param string|int $bundle_id
131
+ */
132
+ private static function flush_bundle_cache( $bundle_id ) {
133
+ wp_cache_delete( WC_Cache_Helper::get_cache_prefix( 'bundled_data_items' ) . $bundle_id, 'bundled_data_items' );
134
+ }
135
+
136
  public function sync_product_bundle_meta( $bundle_id, $translated_bundle_id ) {
137
 
138
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
206
  }
207
 
208
  public function sync_product_bundle_meta_with_translations( $bundle_id ) {
209
+ /**
210
+ * @return array {
211
+ * @var int $original_bundle_id
212
+ * @var \WPML\Collect\Support\Collection $translations_only
213
+ * }
214
+ */
215
+ $get_original_id_and_translations = Fns::memorize( function() use ( $bundle_id ) {
216
+ $trid = $this->sitepress->get_element_trid( $bundle_id, 'post_product' );
217
+ $translations = wpml_collect( $this->sitepress->get_element_translations( $trid, 'post_product' ) );
218
+ $original_bundle_id = (int) $translations->filter( Obj::prop( 'original' ) )
219
+ ->map( Obj::prop( 'element_id' ) )
220
+ ->first();
221
 
222
+ $translations_only = $translations
223
+ ->reject( function( $translation ) use ( $original_bundle_id ) {
224
+ return (int) $translation->element_id === $original_bundle_id;
225
+ } );
226
 
227
+ return [ $original_bundle_id, $translations_only ];
228
+ } );
 
229
 
 
 
 
 
 
 
230
 
231
+ if ( $this->is_bundle_product( $bundle_id ) ) {
232
+ list( $original_bundle_id, $translations_only ) = $get_original_id_and_translations();
233
+
234
+ $translations_only->each( function( $translation ) use ( $original_bundle_id ) {
235
+ $this->sync_product_bundle_meta( $original_bundle_id, $translation->element_id );
236
+ } );
237
  }
238
 
239
+ $bundle_sell_ids = get_post_meta( $bundle_id, self::META_SELL_IDS, true );
240
+
241
+ if ( $bundle_sell_ids ) {
242
+ list( $original_bundle_id, $translations_only ) = $get_original_id_and_translations();
243
+
244
+ $translations_only->each( function( $translation ) use ( $original_bundle_id ) {
245
+ $this->sync_bundle_sells( $original_bundle_id, $translation->element_id, $translation->language_code );
246
+ } );
247
+ }
248
  }
249
 
250
  /**
302
  }
303
 
304
  /**
305
+ * @param int|string $item_id
306
+ * @param string $language
307
  *
308
  * @return string
309
  */
337
 
338
  }
339
 
340
+ /**
341
+ * @deprecated This method is used by CTE only.
342
+ *
343
+ * Add Bundles Box to WCML Translation GUI.
344
+ *
345
+ * @param object $obj
346
+ * @param string|int $bundle_id
347
+ * @param mixed $data
348
+ *
349
+ * @return false|void
350
+ */
351
  public function custom_box_html( $obj, $bundle_id, $data ) {
352
 
353
  $bundle_items = $this->product_bundles_items->get_items( $bundle_id );
412
 
413
  }
414
 
415
+ /**
416
+ * @deprecated This method is used by CTE only.
417
+ *
418
+ * @param array $data
419
+ * @param string|int $bundle_id
420
+ * @param object $translation
421
+ * @param string $lang
422
+ *
423
+ * @return mixed
424
+ */
425
  public function custom_box_html_data( $data, $bundle_id, $translation, $lang ) {
426
 
427
  $bundle_data = $this->get_product_bundle_data( $bundle_id );
468
  return $data;
469
  }
470
 
471
+ /**
472
+ * @param int|string $product_id
473
+ * @param int|string $item_id
474
+ * @param string $field
475
+ *
476
+ * @return string
477
+ */
478
+ private static function get_job_field_name( $product_id, $item_id, $field ) {
479
+ return 'product_bundles:' . $product_id . ':' . $item_id . ':' . $field;
480
+ }
481
+
482
  public function append_bundle_data_translation_package( $package, $post ) {
483
 
484
  if ( $post->post_type == 'product' ) {
494
  $product_id = $this->get_product_id_for_item_id( $item_id );
495
  foreach ( $fields as $field ) {
496
  if ( $product_data[ 'override_' . $field ] == 'yes' && ! empty( $product_data[ $field ] ) ) {
497
+ $package['contents'][ self::get_job_field_name( $product_id, $item_id, $field ) ] = [
498
  'translate' => 1,
499
  'data' => $this->tp->encode_field_data( $product_data[ $field ], 'base64' ),
500
  'format' => 'base64',
503
  }
504
  }
505
  }
506
+
507
+ $bundle_sell = get_post_meta( $post->ID, self::META_SELLS_TITLE, true );
508
+
509
+ if ( $bundle_sell ) {
510
+ $package['contents'][ self::META_SELLS_TITLE ] = [
511
+ 'translate' => 1,
512
+ 'data' => $this->tp->encode_field_data( $bundle_sell ),
513
+ 'format' => 'base64',
514
+ ];
515
+ }
516
  }
517
 
518
  return $package;
519
 
520
  }
521
 
522
+ /**
523
+ * @param string|int $translated_bundle_id
524
+ * @param array $fields
525
+ * @param object $job
526
+ */
527
+ public function save_product_bundles_to_translation( $translated_bundle_id, $fields, $job ) {
528
+ $bundle_id = $job->original_doc_id;
529
+
530
+ if (
531
+ Str::startsWith( 'post_', $job->original_post_type )
532
+ && 'product' === get_post_type( $bundle_id )
533
+ ) {
534
+ // $get_field_translation :: (string, string, string) -> string
535
+ $get_field_translation = function( $product_id, $item_id, $field ) use ( $fields ) {
536
+ return Obj::path( [ self::get_job_field_name( $product_id, $item_id, $field ), 'data' ], $fields );
537
+ };
538
+
539
+ $this->apply_translation( $bundle_id, $translated_bundle_id, $get_field_translation, $job->language_code );
540
+ $this->sync_bundle_sells( $bundle_id, $translated_bundle_id, $job->language_code, Obj::path( [ self::META_SELLS_TITLE, 'data' ], $fields ) );
541
+ }
542
+ }
543
+
544
+ private function sync_bundle_sells( $bundle_id, $translated_bundle_id, $language_code, $translated_title = null ) {
545
+ // $transpose_post_meta :: (string, callable) -> void
546
+ $transpose_post_meta = function( $meta_name, callable $transpose ) use ( $bundle_id, $translated_bundle_id ) {
547
+ $value = get_post_meta( $bundle_id, $meta_name, true );
548
+
549
+ if ( $value ) {
550
+ update_post_meta( $translated_bundle_id, $meta_name, $transpose( $value ) );
551
+ } else {
552
+ delete_post_meta( $translated_bundle_id, $meta_name );
553
+ }
554
+ };
555
+
556
+ // $convert_product_ids :: array -> array
557
+ $convert_product_ids = Fns::map( function( $id ) use ( $language_code ) {
558
+ return $this->sitepress->get_object_id( $id, 'product', true, $language_code );
559
+ } );
560
+
561
+ $transpose_post_meta( self::META_SELL_IDS, $convert_product_ids );
562
+ $transpose_post_meta( self::META_SELLS_DISCOUNT, Fns::identity() );
563
+
564
+ if ( $translated_title ) {
565
+ $transpose_post_meta( self::META_SELLS_TITLE, Fns::always( $translated_title ) );
566
+ }
567
+ }
568
+
569
+ /**
570
+ * @deprecated This method is used by CTE only.
571
+ *
572
+ * Update Bundled products title and description after saving the translation.
573
+ *
574
+ * @param string|int $bundle_id
575
+ * @param string|int $translated_bundle_id
576
+ * @param array $data
577
+ * @param string $lang
578
+ *
579
+ * @return array|void
580
+ */
581
  public function bundle_update( $bundle_id, $translated_bundle_id, $data, $lang ) {
582
+ // $get_field_translation :: (string, string, string, string) -> string
583
+ $get_field_translation = function( $product_id, $item_id, $field, $field_alias ) use ( $data ) {
584
+ return Obj::prop( md5( 'bundle_' . $product_id . '_' . $field_alias ), $data );
585
+ };
586
 
587
+ return $this->apply_translation( $bundle_id, $translated_bundle_id, $get_field_translation, $lang );
588
+ }
589
+
590
+ /**
591
+ * @param string|int $bundle_id
592
+ * @param string|int $translated_bundle_id
593
+ * @param callable $get_field_translation (int, int, string) -> string
594
+ * @param string $target_lang
595
+ *
596
+ * @return array|void
597
+ */
598
+ private function apply_translation( $bundle_id, $translated_bundle_id, callable $get_field_translation, $target_lang ) {
599
  $bundle_data = $this->get_product_bundle_data( $bundle_id );
600
  $translated_bundle_data = $this->get_product_bundle_data( $translated_bundle_id );
601
 
613
  foreach ( $bundle_data as $item_id => $bundle_item_data ) {
614
 
615
  $product_id = $this->get_product_id_for_item_id( $item_id );
616
+ $translated_product_id = apply_filters( 'translate_object_id', $product_id, get_post_type( $product_id ), false, $target_lang );
617
 
618
  if ( $translated_product_id ) {
619
 
640
  );
641
 
642
  $translated_item_id = $this->wpdb->insert_id;
643
+ $this->set_translated_item_id_relationship( $item_id, $translated_item_id, $target_lang );
644
  }
645
 
646
+ $translated_item_id = $this->get_item_id_for_language( $item_id, $target_lang );
647
 
648
+ foreach ( [
649
+ 'title' => 'title',
650
+ 'description' => 'desc',
651
+ ] as $field => $field_alias ) {
652
+ $field_translation = $get_field_translation( $product_id, $item_id, $field, $field_alias );
653
 
654
+ if ( $field_translation ) {
655
+ $translated_bundle_data[ $translated_item_id ][ $field ] = $field_translation;
656
+ $translated_bundle_data[ $translated_item_id ][ "override_$field" ] = $bundle_item_data[ "override_$field" ];
657
+ }
658
  }
659
 
660
  if ( isset( $bundle_item_data['allowed_variations'] ) ) {
661
  if ( is_array( $bundle_item_data['allowed_variations'] ) ) {
662
+ $translated_bundle_data[ $translated_item_id ]['allowed_variations'] = $this->translate_allowed_variations( $bundle_item_data['allowed_variations'], $target_lang );
 
663
  } else {
664
+ $translated_bundle_data[ $translated_item_id ]['allowed_variations'] = $bundle_item_data['allowed_variations'];
 
665
  }
666
  }
667
  }
851
  }
852
  }
853
 
854
+ /**
855
+ * @deprecated This method is used by CTE only.
856
+ *
857
+ * @param string|int $translated_bundle_id
858
+ * @param array $data
859
+ * @param object $job
860
+ */
861
  public function save_bundle_data_translation( $translated_bundle_id, $data, $job ) {
862
 
863
  if ( $this->is_bundle_product( $translated_bundle_id ) ) {
946
  return $translated_item_id;
947
  }
948
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
949
  public function is_bundle_product( $product_id ) {
950
 
951
  $product = wc_get_product( $product_id );
1026
 
1027
  }
1028
 
1029
+ /**
1030
+ * @param array $values
1031
+ * @param int $postId
1032
+ *
1033
+ * @return array
1034
+ */
1035
+ public static function adjust_bundle_sells_product_signature( $values, $postId ) {
1036
+ return Obj::assoc( self::META_SELLS_TITLE, get_post_meta( $postId, self::META_SELLS_TITLE, true ), $values );
1037
+ }
1038
  }
compatibility/{includes → WcProductBundles}/class-wcml-wc-product-bundles-items.php RENAMED
File without changes
compatibility/WcProductTypeColumn/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcProductTypeColumn;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_WC_Product_Type_Column;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_WC_Product_Type_Column();
15
+ }
16
+ }
compatibility/{class-wcml-wc-product-type-column.php → WcProductTypeColumn/class-wcml-wc-product-type-column.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_WC_Product_Type_Column {
4
 
5
  public function add_hooks() {
6
 
1
  <?php
2
 
3
+ class WCML_WC_Product_Type_Column implements \IWPML_Action {
4
 
5
  public function add_hooks() {
6
 
compatibility/WcShowSingleVariations/Factory.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcShowSingleVariations;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_JCK_WSSV;
7
+
8
+ /**
9
+ * @see https://iconicwp.com/products/woocommerce-show-single-variations/
10
+ */
11
+ class Factory extends ComponentFactory {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ return new WCML_JCK_WSSV();
18
+ }
19
+ }
compatibility/{class-wcml-jck-wssv.php → WcShowSingleVariations/class-wcml-jck-wssv.php} RENAMED
@@ -1,11 +1,10 @@
1
  <?php
2
 
3
- class WCML_JCK_WSSV {
4
 
5
  private $transient_name = 'jck_wssv_term_counts';
6
 
7
- public function __construct() {
8
-
9
  add_filter( 'pre_transient_' . $this->transient_name, [ $this, 'get_language_specific_transient' ] );
10
  add_filter( 'set_transient_' . $this->transient_name, [ $this, 'set_language_specific_transient' ], 10, 2 );
11
  }
1
  <?php
2
 
3
+ class WCML_JCK_WSSV implements \IWPML_Action {
4
 
5
  private $transient_name = 'jck_wssv_term_counts';
6
 
7
+ public function add_hooks() {
 
8
  add_filter( 'pre_transient_' . $this->transient_name, [ $this, 'get_language_specific_transient' ] );
9
  add_filter( 'set_transient_' . $this->transient_name, [ $this, 'set_language_specific_transient' ], 10, 2 );
10
  }
compatibility/WcSubscriptions/Factory.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcSubscriptions;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+ use WCML_WC_Subscriptions;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+ use function WCML\functions\isStandAlone;
10
+
11
+ /**
12
+ * @see https://www.woocommerce.com/products/woocommerce-subscriptions/
13
+ */
14
+ class Factory extends ComponentFactory implements IStandAloneAction {
15
+
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ public function create() {
20
+ $hooks = [
21
+ new SharedHooks(),
22
+ ];
23
+
24
+ if ( wcml_is_multi_currency_on() ) {
25
+ $hooks[] = new MulticurrencyHooks( getWooCommerceWpml(), self::getWpdb() );
26
+ }
27
+
28
+ if ( ! isStandAlone() ) {
29
+ $hooks[] = new WCML_WC_Subscriptions( getWooCommerceWpml(), self::getWpdb() );
30
+ }
31
+
32
+ return $hooks;
33
+ }
34
+ }
compatibility/WcSubscriptions/MulticurrencyHooks.php ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcSubscriptions;
4
+
5
+ use WC_Product;
6
+ use WC_Product_Subscription_Variation;
7
+ use WC_Product_Variable_Subscription;
8
+ use WCML\Utilities\DB;
9
+ use WCML_Custom_Prices_UI;
10
+ use woocommerce_wpml;
11
+ use wpdb;
12
+ use function WPML\FP\tap as tap;
13
+
14
+ class MulticurrencyHooks implements \IWPML_Action {
15
+
16
+ /** @var woocommerce_wpml $woocommerce_wpml */
17
+ private $woocommerce_wpml;
18
+
19
+ /** @var wpdb $wpdb */
20
+ private $wpdb;
21
+
22
+ /** @var bool $newSubscription */
23
+ private $newSubscription = false;
24
+
25
+ /** @var bool $proratingPrice */
26
+ private $proratingPrice = false;
27
+
28
+ public function __construct( woocommerce_wpml $woocommerce_wpml, wpdb $wpdb ) {
29
+ $this->woocommerce_wpml = $woocommerce_wpml;
30
+ $this->wpdb = $wpdb;
31
+ }
32
+
33
+ public function add_hooks() {
34
+ add_action( 'init', [ $this, 'init' ], 9 );
35
+
36
+ add_filter( 'wcml_custom_prices_fields', [ $this, 'set_prices_fields' ], 10, 2 );
37
+ add_filter( 'wcml_custom_prices_strings', [ $this, 'set_labels_for_prices_fields' ], 10, 2 );
38
+ add_filter( 'wcml_custom_prices_fields_labels', [ $this, 'set_labels_for_prices_fields' ], 10, 2 );
39
+ add_filter( 'wcml_update_custom_prices_values', [ $this, 'update_custom_prices_values' ], 10, 3 );
40
+ add_action( 'wcml_after_custom_prices_block', [ $this, 'new_subscription_prices_block' ] );
41
+
42
+ add_filter( 'woocommerce_subscriptions_product_price', [ $this, 'woocommerce_subscription_price_from' ], 10, 2 );
43
+ }
44
+
45
+ public function init() {
46
+ if ( ! is_admin() ) {
47
+ add_filter( 'woocommerce_subscriptions_product_sign_up_fee', [ $this, 'subscriptions_product_sign_up_fee_filter' ], 10, 2 );
48
+ $this->maybe_force_client_currency_for_subscription();
49
+ }
50
+
51
+ add_filter( 'wcs_switch_proration_new_price_per_day', tap( [ $this, 'set_prorating_price' ] ) );
52
+ }
53
+
54
+ /**
55
+ * Set a flag when we are prorating the price (upgrades/downgrades).
56
+ * We do this to skip currency conversion in the sign_up_fee because
57
+ * when switching subscription it has already been converted.
58
+ */
59
+ public function set_prorating_price() {
60
+ $this->proratingPrice = true;
61
+ }
62
+
63
+ /**
64
+ * Filter Subscription Sign-up fee cost
65
+ *
66
+ * @param string $subscriptionSignUpFee
67
+ * @param WC_Product $product
68
+ *
69
+ * @return string
70
+ */
71
+ public function subscriptions_product_sign_up_fee_filter( $subscriptionSignUpFee, $product ) {
72
+ if ( $product && ! $this->proratingPrice ) {
73
+ $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
74
+
75
+ if ( wcml_get_woocommerce_currency_option() !== $currency ) {
76
+ $productId = $product->get_id();
77
+
78
+ if ( $product instanceof WC_Product_Variable_Subscription ) {
79
+ $productId = $product->get_meta( '_min_price_variation_id', true );
80
+ }
81
+
82
+ $originalProductId = $this->woocommerce_wpml->products->get_original_product_id( $productId );
83
+
84
+ if ( get_post_meta( $originalProductId, '_wcml_custom_prices_status', true ) ) {
85
+ $subscriptionSignUpFee = get_post_meta( $originalProductId, '_subscription_sign_up_fee_' . $currency, true );
86
+ } else {
87
+ $subscriptionSignUpFee = apply_filters( 'wcml_raw_price_amount', $subscriptionSignUpFee );
88
+ }
89
+ }
90
+ }
91
+
92
+ return $subscriptionSignUpFee;
93
+ }
94
+
95
+ /**
96
+ * Force client currency for resubscribe subscription
97
+ */
98
+ public function maybe_force_client_currency_for_subscription() {
99
+ $subscriptionId = false;
100
+ $getData = wpml_collect( $_GET );
101
+
102
+ if ( $getData->has( 'resubscribe' ) ) {
103
+ $subscriptionId = (int) $getData->get( 'resubscribe' );
104
+ } elseif ( $getData->has( 'subscription_renewal_early' ) ) {
105
+ $subscriptionId = (int) $getData->get( 'subscription_renewal_early' );
106
+ } elseif ( is_cart() || is_checkout() ) {
107
+ $resubscribeCartItem = wcs_cart_contains_resubscribe();
108
+ if ( $resubscribeCartItem ) {
109
+ $subscriptionId = $resubscribeCartItem['subscription_resubscribe']['subscription_id'];
110
+ } else {
111
+ $earlyRenewalCartItem = wcs_cart_contains_early_renewal();
112
+ if ( $earlyRenewalCartItem ) {
113
+ $subscriptionId = $earlyRenewalCartItem['subscription_renewal']['subscription_renewal_early'];
114
+ }
115
+ }
116
+ }
117
+
118
+ if ( $subscriptionId ) {
119
+ $subscriptionCurrency = get_post_meta( $subscriptionId, '_order_currency', true );
120
+ if ( $subscriptionCurrency && $this->woocommerce_wpml->multi_currency->get_client_currency() !== $subscriptionCurrency ) {
121
+ $this->woocommerce_wpml->multi_currency->set_client_currency( $subscriptionCurrency );
122
+ }
123
+ }
124
+ }
125
+
126
+ /**
127
+ * @param array $fields
128
+ * @param int|string $productId
129
+ *
130
+ * @return array
131
+ */
132
+ public function set_prices_fields( $fields, $productId ) {
133
+ if ( $this->isSubscriptionsProduct( $productId ) || $this->newSubscription ) {
134
+ $fields[] = '_subscription_sign_up_fee';
135
+ }
136
+
137
+ return $fields;
138
+ }
139
+
140
+ /**
141
+ * @param array $labels
142
+ * @param int|string $productId
143
+ *
144
+ * @return array
145
+ */
146
+ public function set_labels_for_prices_fields( $labels, $productId ) {
147
+ if ( $this->isSubscriptionsProduct( $productId ) || $this->newSubscription ) {
148
+ $labels['_regular_price'] = __( 'Subscription Price', 'woocommerce-multilingual' );
149
+ $labels['_subscription_sign_up_fee'] = __( 'Sign-up Fee', 'woocommerce-multilingual' );
150
+ }
151
+
152
+ return $labels;
153
+ }
154
+
155
+ /**
156
+ * @param array $prices
157
+ * @param string $code
158
+ * @param int|string|false $variationId
159
+ *
160
+ * @return array
161
+ */
162
+ public function update_custom_prices_values( $prices, $code, $variationId = false ) {
163
+ if ( isset( $_POST['_custom_subscription_sign_up_fee'][ $code ] ) ) {
164
+ $prices['_subscription_sign_up_fee'] = wc_format_decimal( $_POST['_custom_subscription_sign_up_fee'][ $code ] );
165
+ }
166
+
167
+ if ( $variationId && isset( $_POST['_custom_variation_subscription_sign_up_fee'][ $code ][ $variationId ] ) ) {
168
+ $prices['_subscription_sign_up_fee'] = wc_format_decimal( $_POST['_custom_variation_subscription_sign_up_fee'][ $code ][ $variationId ] );
169
+ }
170
+
171
+ return $prices;
172
+ }
173
+
174
+ /**
175
+ * @param int|string $productId
176
+ *
177
+ * @return void
178
+ */
179
+ public function new_subscription_prices_block( $productId ) {
180
+ if ( 'new' === $productId ) {
181
+ $this->newSubscription = true;
182
+ echo '<div class="wcml_prices_if_subscription" style="display: none">';
183
+ $custom_prices_ui = new WCML_Custom_Prices_UI( $this->woocommerce_wpml, 'new' );
184
+ $custom_prices_ui->show();
185
+ echo '</div>';
186
+ ?>
187
+ <script>
188
+ jQuery(function($) {
189
+ jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new_subscription]').attr( 'id', '_wcml_custom_prices[new_subscription]');
190
+ jQuery('.wcml_prices_if_subscription .wcml_custom_prices_options_block>label').attr('for', '_wcml_custom_prices[new_subscription]');
191
+ jQuery('.wcml_prices_if_subscription .wcml_schedule_input').each( function(){
192
+ jQuery(this).attr('name', jQuery(this).attr('name')+'_subscription');
193
+ });
194
+
195
+ jQuery('.options_group>.wcml_custom_prices_block .wcml_custom_prices_input:first-child').click();
196
+ jQuery('.options_group>.wcml_custom_prices_block .wcml_schedule_options .wcml_schedule_input:first-child').click();
197
+
198
+ jQuery(document).on('change', 'select#product-type', function () {
199
+ if (jQuery(this).val() == 'subscription') {
200
+ jQuery('.wcml_prices_if_subscription').show();
201
+ jQuery('.options_group>.wcml_custom_prices_block').hide();
202
+ } else if (jQuery(this).val() != 'variable-subscription') {
203
+ jQuery('.wcml_prices_if_subscription').hide();
204
+ jQuery('.options_group>.wcml_custom_prices_block').show();
205
+ }
206
+ });
207
+
208
+ jQuery(document).on('click', '#publish', function () {
209
+ if ( jQuery('.wcml_prices_if_subscription').is( ':visible' ) ) {
210
+ jQuery('.options_group>.wcml_custom_prices_block').remove();
211
+ jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new]');
212
+ jQuery('.wcml_prices_if_subscription .wcml_schedule_input').each( function(){
213
+ jQuery(this).attr('name', jQuery(this).attr('name').replace('_subscription','') );
214
+ });
215
+ }else{
216
+ jQuery('.wcml_prices_if_subscription').remove();
217
+ }
218
+ });
219
+ });
220
+ </script>
221
+ <?php
222
+ }
223
+ }
224
+
225
+ /**
226
+ * @param int|string $productId
227
+ *
228
+ * @return bool
229
+ */
230
+ private function isSubscriptionsProduct( $productId ) {
231
+ $variationTermTaxonomyIds = $this->wpdb->get_col( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.slug IN ( 'subscription', 'variable-subscription' ) AND tt.taxonomy = 'product_type'" );
232
+
233
+ if ( get_post_type( $productId ) == 'product_variation' ) {
234
+ $productId = wp_get_post_parent_id( $productId );
235
+ }
236
+
237
+ return (bool) $this->wpdb->get_var(
238
+ $this->wpdb->prepare(
239
+ "SELECT count(object_id) FROM {$this->wpdb->term_relationships}
240
+ WHERE object_id = %d AND term_taxonomy_id IN (" . DB::prepareIn( $variationTermTaxonomyIds, '%d' ) . ')',
241
+ $productId
242
+ )
243
+ );
244
+ }
245
+
246
+ /**
247
+ * @param string $price
248
+ * @param WC_Product|WC_Product_Subscription_Variation $product
249
+ *
250
+ * @return string
251
+ */
252
+ public function woocommerce_subscription_price_from( $price, $product ) {
253
+ if ( $product instanceof WC_Product_Subscription_Variation ) {
254
+ $customPricesOn = get_post_meta( $product->get_id(), '_wcml_custom_prices_status', true );
255
+
256
+ if ( $customPricesOn ) {
257
+ $price = get_post_meta( $product->get_id(), '_price_' . $this->woocommerce_wpml->multi_currency->get_client_currency(), true );
258
+ } else {
259
+ $price = apply_filters( 'wcml_raw_price_amount', $price );
260
+ }
261
+ }
262
+
263
+ return $price;
264
+ }
265
+ }
compatibility/WcSubscriptions/SharedHooks.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcSubscriptions;
4
+
5
+ use WC_Cart;
6
+
7
+ class SharedHooks implements \IWPML_Action {
8
+
9
+ /** @var WC_Cart[]|null $recurring_carts */
10
+ private $recurring_carts;
11
+
12
+ public function add_hooks() {
13
+ add_action( 'init', [ $this, 'init' ], 9 );
14
+ }
15
+
16
+ public function init() {
17
+ if ( ! is_admin() ) {
18
+ add_action( 'woocommerce_before_calculate_totals', [ $this, 'maybe_backup_recurring_carts' ], 1 );
19
+ add_action( 'woocommerce_after_calculate_totals', [ $this, 'maybe_restore_recurring_carts' ], 200 );
20
+ }
21
+ }
22
+
23
+ /**
24
+ * @param WC_Cart $cart
25
+ */
26
+ public function maybe_backup_recurring_carts( $cart ) {
27
+ if ( ! empty( $cart->recurring_carts ) ) {
28
+ $this->recurring_carts = $cart->recurring_carts;
29
+ }
30
+ }
31
+
32
+ /**
33
+ * @param WC_Cart $cart
34
+ */
35
+ public function maybe_restore_recurring_carts( $cart ) {
36
+ if ( ! empty( $this->recurring_carts ) ) {
37
+ $cart->recurring_carts = $this->recurring_carts;
38
+ $this->recurring_carts = null;
39
+ }
40
+ }
41
+ }
compatibility/WcSubscriptions/class-wcml-wc-subscriptions.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WCML_WC_Subscriptions implements \IWPML_Action {
4
+
5
+ /** @var woocommerce_wpml */
6
+ private $woocommerce_wpml;
7
+
8
+ /** @var wpdb */
9
+ private $wpdb;
10
+
11
+ public function __construct( woocommerce_wpml $woocommerce_wpml, wpdb $wpdb ) {
12
+ $this->woocommerce_wpml = $woocommerce_wpml;
13
+ $this->wpdb = $wpdb;
14
+ }
15
+
16
+ public function add_hooks() {
17
+ add_action( 'init', [ $this, 'init' ], 9 );
18
+ add_filter( 'wcml_variation_term_taxonomy_ids', [ $this, 'wcml_variation_term_taxonomy_ids' ] );
19
+ add_filter( 'woocommerce_subscription_lengths', [ $this, 'woocommerce_subscription_lengths' ], 10, 2 );
20
+
21
+ add_filter( 'wcml_register_endpoints_query_vars', [ $this, 'register_endpoint' ], 10, 3 );
22
+ add_filter( 'wcml_endpoint_permalink_filter', [ $this, 'endpoint_permalink_filter' ], 10, 2 );
23
+
24
+ add_action( 'woocommerce_subscriptions_product_options_pricing', [ $this, 'show_pointer_info' ] );
25
+ add_action( 'woocommerce_variable_subscription_pricing', [ $this, 'show_pointer_info' ] );
26
+
27
+ add_filter( 'wcml_xliff_allowed_variations_types', [ $this, 'set_allowed_variations_types_in_xliff' ] );
28
+
29
+ // Add language links to email settings
30
+ add_filter( 'wcml_emails_options_to_translate', [ $this, 'translate_email_options' ] );
31
+ add_filter( 'wcml_emails_section_name_prefix', [ $this, 'email_option_section_prefix' ], 10, 2 );
32
+ }
33
+
34
+ public function init() {
35
+ if ( ! is_admin() ) {
36
+ add_filter( 'wcs_get_subscription', [ $this, 'filter_subscription_items' ] );
37
+ }
38
+
39
+ // Translate emails
40
+ add_filter( 'woocommerce_generated_manual_renewal_order_renewal_notification', [ $this, 'translate_renewal_notification' ], 9 );
41
+ add_filter( 'woocommerce_order_status_failed_renewal_notification', [ $this, 'translate_renewal_notification' ], 9 );
42
+ }
43
+
44
+ public function wcml_variation_term_taxonomy_ids( $get_variation_term_taxonomy_ids ) {
45
+
46
+ $get_variation_term_taxonomy_id = $this->wpdb->get_var( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.slug = 'variable-subscription'" );
47
+
48
+ if ( ! empty( $get_variation_term_taxonomy_id ) ) {
49
+ $get_variation_term_taxonomy_ids[] = $get_variation_term_taxonomy_id;
50
+ }
51
+
52
+ return $get_variation_term_taxonomy_ids;
53
+ }
54
+
55
+ public function woocommerce_subscription_lengths( $subscription_ranges, $subscription_period ) {
56
+
57
+ if ( is_array( $subscription_ranges ) ) {
58
+ foreach ( $subscription_ranges as $period => $ranges ) {
59
+ if ( is_array( $ranges ) ) {
60
+ foreach ( $ranges as $range ) {
61
+ if ( $range == '9 months' ) {
62
+ $breakpoint = true;
63
+ }
64
+ $new_subscription_ranges[ $period ][] = apply_filters( 'wpml_translate_single_string', $range, 'wc_subscription_ranges', $range );
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ return isset( $new_subscription_ranges ) ? $new_subscription_ranges : $subscription_ranges;
71
+ }
72
+
73
+ public function register_endpoint( $query_vars, $wc_vars, $obj ) {
74
+
75
+ $query_vars['view-subscription'] = $obj->get_endpoint_translation( 'view-subscription', isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );
76
+ $query_vars['subscriptions'] = $obj->get_endpoint_translation( 'subscriptions', isset( $wc_vars['subscriptions'] ) ? $wc_vars['subscriptions'] : 'subscriptions' );
77
+ return $query_vars;
78
+ }
79
+
80
+ public function endpoint_permalink_filter( $endpoint, $key ) {
81
+
82
+ if ( $key == 'view-subscription' ) {
83
+ return 'view-subscription';
84
+ }
85
+
86
+ return $endpoint;
87
+ }
88
+
89
+ public function show_pointer_info() {
90
+
91
+ $pointer_ui = new WCML_Pointer_UI(
92
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
93
+ sprintf( __( 'You can translate strings related to subscription products on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce_subscriptions' ) . '">', '</a>' ),
94
+ WCML_Tracking_Link::getWcmlSubscriptionsDoc(),
95
+ 'general_product_data .subscription_pricing',
96
+ 'prepend'
97
+ );
98
+
99
+ $pointer_ui->show();
100
+ }
101
+
102
+ /**
103
+ * @param array $allowed_types
104
+ *
105
+ * @return array
106
+ */
107
+ public function set_allowed_variations_types_in_xliff( $allowed_types ) {
108
+
109
+ $allowed_types[] = 'variable-subscription';
110
+ $allowed_types[] = 'subscription_variation';
111
+
112
+ return $allowed_types;
113
+ }
114
+
115
+ /**
116
+ * Translate strings of renewal notifications
117
+ *
118
+ * @param integer $order_id Order ID
119
+ */
120
+ public function translate_renewal_notification( $order_id ) {
121
+
122
+ if ( isset( WC()->mailer()->emails['WCS_Email_Customer_Renewal_Invoice'] ) ) {
123
+ $this->woocommerce_wpml->emails->refresh_email_lang( $order_id );
124
+
125
+ $WCS_Email_Customer_Renewal_Invoice = WC()->mailer()->emails['WCS_Email_Customer_Renewal_Invoice'];
126
+ $WCS_Email_Customer_Renewal_Invoice->heading = __( $WCS_Email_Customer_Renewal_Invoice->heading, 'woocommerce-subscriptions' );
127
+ $WCS_Email_Customer_Renewal_Invoice->subject = __( $WCS_Email_Customer_Renewal_Invoice->subject, 'woocommerce-subscriptions' );
128
+
129
+ add_filter( 'woocommerce_email_get_option', [ $this, 'translate_heading_subject' ], 10, 4 );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Translate custom heading and subject for renewal notification
135
+ *
136
+ * @param string $return_value original string
137
+ * @param WCS_Email_Customer_Renewal_Invoice $obj Object of email class
138
+ * @param string $value Original value from setting
139
+ * @param string $key Name of the key
140
+ * @return string Translated value or original value incase of not translated
141
+ */
142
+ public function translate_heading_subject( $return_value, $obj, $value, $key ) {
143
+
144
+ if ( $obj instanceof WCS_Email_Customer_Renewal_Invoice ) {
145
+ if ( $key == 'subject' || $key == 'heading' ) {
146
+ $translated_admin_string = $this->woocommerce_wpml->emails->getStringTranslation( 'admin_texts_woocommerce_customer_renewal_invoice_settings', '[woocommerce_customer_renewal_invoice_settings]' . $key );
147
+ return empty( $translated_admin_string ) ? $return_value : $translated_admin_string;
148
+ }
149
+ }
150
+
151
+ return $return_value;
152
+ }
153
+
154
+ /**
155
+ * Add customer renewal invoice option to translate
156
+ *
157
+ * @param array $emails_options list of option to translate
158
+ * @return array $emails_options
159
+ */
160
+ public function translate_email_options( $emails_options ) {
161
+
162
+ if ( is_array( $emails_options ) ) {
163
+ $emails_options[] = 'woocommerce_customer_renewal_invoice_settings';
164
+ }
165
+
166
+ return $emails_options;
167
+ }
168
+
169
+ /**
170
+ * Change section name prefix to add language links
171
+ *
172
+ * @param string $section_prefix section prefix
173
+ * @param string $emails_option current option name
174
+ * @return string $section_prefix
175
+ */
176
+ public function email_option_section_prefix( $section_prefix, $emails_option ) {
177
+
178
+ if ( $emails_option === 'woocommerce_customer_renewal_invoice_settings' ) {
179
+ return 'wcs_email_';
180
+ }
181
+
182
+ return $section_prefix;
183
+ }
184
+
185
+ /**
186
+ * @param mixed $subscription
187
+ *
188
+ * @return mixed
189
+ */
190
+ public function filter_subscription_items( $subscription ) {
191
+
192
+ if ( $subscription instanceof WC_Subscription ) {
193
+ $this->woocommerce_wpml->orders->adjust_order_item_in_language( $subscription->get_items() );
194
+ }
195
+
196
+ return $subscription;
197
+ }
198
+ }
compatibility/WcSwatches/Factory.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcSwatches;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Variation_Swatches_And_Photos;
7
+ use function WCML\functions\getWooCommerceWpml;
8
+
9
+ class Factory extends ComponentFactory {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function create() {
15
+ return new WCML_Variation_Swatches_And_Photos( getWooCommerceWpml() );
16
+ }
17
+ }
compatibility/{class-wcml-variation-swatches-and-photos.php → WcSwatches/class-wcml-variation-swatches-and-photos.php} RENAMED
@@ -3,7 +3,7 @@
3
  /**
4
  * Compatibility class for Variation Swatches and Photos plugin
5
  */
6
- class WCML_Variation_Swatches_And_Photos {
7
 
8
  /** @var woocommerce_wpml */
9
  private $woocommerce_wpml;
3
  /**
4
  * Compatibility class for Variation Swatches and Photos plugin
5
  */
6
+ class WCML_Variation_Swatches_And_Photos implements \IWPML_Action {
7
 
8
  /** @var woocommerce_wpml */
9
  private $woocommerce_wpml;
compatibility/WcTabManager/Factory.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WcTabManager;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Tab_Manager;
7
+ use function WCML\functions\getSitePress;
8
+ use function WCML\functions\getWooCommerceWpml;
9
+
10
+ class Factory extends ComponentFactory {
11
+
12
+ /**
13
+ * @inheritDoc
14
+ */
15
+ public function create() {
16
+ return new WCML_Tab_Manager( getSitePress(), self::getWooCommerce(), getWooCommerceWpml(), self::getWpdb(), self::getElementTranslationPackage() );
17
+ }
18
+ }
compatibility/{class-wcml-tab-manager.php → WcTabManager/class-wcml-tab-manager.php} RENAMED
@@ -3,7 +3,7 @@
3
  /**
4
  * Class WCML_Tab_Manager
5
  */
6
- class WCML_Tab_Manager {
7
  /**
8
  * @var WPML_Element_Translation_Package
9
  */
@@ -714,6 +714,7 @@ class WCML_Tab_Manager {
714
  public function show_pointer_info() {
715
 
716
  $pointer_ui = new WCML_Pointer_UI(
 
717
  sprintf( __( 'You can translate your custom product tabs on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
718
  WCML_Tracking_Link::getWcmlTabManagerDoc(),
719
  'woocommerce_product_tabs>p'
3
  /**
4
  * Class WCML_Tab_Manager
5
  */
6
+ class WCML_Tab_Manager implements \IWPML_Action {
7
  /**
8
  * @var WPML_Element_Translation_Package
9
  */
714
  public function show_pointer_info() {
715
 
716
  $pointer_ui = new WCML_Pointer_UI(
717
+ /* translators: %1$s and %2$s are opening and closing HTML link tags */
718
  sprintf( __( 'You can translate your custom product tabs on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
719
  WCML_Tracking_Link::getWcmlTabManagerDoc(),
720
  'woocommerce_product_tabs>p'
compatibility/WooVariationsTable/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WooVariationsTable;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use function WCML\functions\getSitePress;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new \WCML_Woo_Var_Table( getSitePress()->get_current_language() );
15
+ }
16
+ }
compatibility/{class-wcml-woo-var-table.php → WooVariationsTable/class-wcml-woo-var-table.php} RENAMED
@@ -3,7 +3,7 @@
3
  * Woo Variations table Compatibility class
4
  */
5
 
6
- class WCML_Woo_Var_Table {
7
 
8
  /**
9
  * @var string
3
  * Woo Variations table Compatibility class
4
  */
5
 
6
+ class WCML_Woo_Var_Table implements \IWPML_Action {
7
 
8
  /**
9
  * @var string
compatibility/WoobeBulkEditor/Factory.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WoobeBulkEditor;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Woobe;
7
+ use function WCML\functions\getSitePress;
8
+
9
+ class Factory extends ComponentFactory {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function create() {
15
+ return new WCML_Woobe( getSitePress(), self::getPostTranslations() );
16
+ }
17
+ }
compatibility/{class-wcml-woobe.php → WoobeBulkEditor/class-wcml-woobe.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- class WCML_Woobe {
4
 
5
  /**
6
  * @var SitePress
1
  <?php
2
 
3
+ class WCML_Woobe implements \IWPML_Action {
4
 
5
  /**
6
  * @var SitePress
compatibility/WoofWcProductFilter/Factory.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WoofWcProductFilter;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://wordpress.org/plugins/woocommerce-products-filter/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+
26
+ }
compatibility/{class-wcml-woof-woocommerce-product-filter.php → WoofWcProductFilter/MulticurrencyHooks.php} RENAMED
@@ -1,8 +1,8 @@
1
  <?php
2
 
3
- namespace WCML\Compatibility\WOOF;
4
 
5
- class WooCommerceProductFilter {
6
  /**
7
  * @var string
8
  */
@@ -19,12 +19,10 @@ class WooCommerceProductFilter {
19
  /**
20
  * Registers hooks.
21
  */
22
- public function addHooks() {
23
- if ( wcml_is_multi_currency_on() ) {
24
- add_action( 'init', [ $this, 'setupCurrencies' ] );
25
- add_filter( 'woof_get_meta_query', [ $this, 'priceInDefaultCurrency' ], 10, 1 );
26
- add_filter( 'wcml_exchange_rates', [ $this, 'storeExchangeRates' ], 10, 1 );
27
- }
28
  }
29
 
30
  /**
@@ -74,15 +72,14 @@ class WooCommerceProductFilter {
74
  * @return bool
75
  */
76
  private function priceIsInSwitchedCurrency() {
77
- $multicurrencyOn = wcml_is_multi_currency_on();
78
- return $multicurrencyOn && $this->currentCurrency !== $this->defaultCurrency;
79
  }
80
 
81
  /**
82
  * Checks if meta data has a correct format.
83
  *
84
- * @param $index
85
- * @param $meta
86
  *
87
  * @return bool
88
  */
1
  <?php
2
 
3
+ namespace WCML\Compatibility\WoofWcProductFilter;
4
 
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
  /**
7
  * @var string
8
  */
19
  /**
20
  * Registers hooks.
21
  */
22
+ public function add_hooks() {
23
+ add_action( 'init', [ $this, 'setupCurrencies' ] );
24
+ add_filter( 'woof_get_meta_query', [ $this, 'priceInDefaultCurrency' ], 10, 1 );
25
+ add_filter( 'wcml_exchange_rates', [ $this, 'storeExchangeRates' ], 10, 1 );
 
 
26
  }
27
 
28
  /**
72
  * @return bool
73
  */
74
  private function priceIsInSwitchedCurrency() {
75
+ return $this->currentCurrency !== $this->defaultCurrency;
 
76
  }
77
 
78
  /**
79
  * Checks if meta data has a correct format.
80
  *
81
+ * @param int $index
82
+ * @param array $meta
83
  *
84
  * @return bool
85
  */
compatibility/WpBakery/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WpBakery;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_Wpb_Vc;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_Wpb_Vc();
15
+ }
16
+ }
compatibility/{class-wcml-wpb-vc.php → WpBakery/class-wcml-wpb-vc.php} RENAMED
@@ -3,7 +3,7 @@
3
  * WPBakery Page Builder ( formerly Visual Composer ) Compatibility class
4
  */
5
 
6
- class WCML_Wpb_Vc {
7
 
8
  public function add_hooks() {
9
 
3
  * WPBakery Page Builder ( formerly Visual Composer ) Compatibility class
4
  */
5
 
6
+ class WCML_Wpb_Vc implements \IWPML_Action {
7
 
8
  public function add_hooks() {
9
 
compatibility/WpFastestCache/Factory.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WpFastestCache;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://wordpress.org/plugins/wp-fastest-cache/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+ }
compatibility/{class-wcml-wpfastest-cache.php → WpFastestCache/MulticurrencyHooks.php} RENAMED
@@ -1,6 +1,8 @@
1
  <?php
2
 
3
- class WCML_WpFastest_Cache {
 
 
4
 
5
  public function add_hooks() {
6
  add_filter(
1
  <?php
2
 
3
+ namespace WCML\Compatibility\WpFastestCache;
4
+
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
 
7
  public function add_hooks() {
8
  add_filter(
compatibility/WpSeo/Factory.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\WpSeo;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML_WPSEO;
7
+
8
+ class Factory extends ComponentFactory {
9
+
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ public function create() {
14
+ return new WCML_WPSEO();
15
+ }
16
+ }
compatibility/{class-wcml-wpseo.php → WpSeo/class-wcml-wpseo.php} RENAMED
@@ -1,10 +1,10 @@
1
  <?php
2
 
3
- class WCML_WPSEO {
4
 
5
  private $updated_post_id;
6
 
7
- public function __construct() {
8
 
9
  add_filter( 'wcml_product_content_label', [ $this, 'wpseo_custom_field_label' ], 10, 2 );
10
 
1
  <?php
2
 
3
+ class WCML_WPSEO implements \IWPML_Action {
4
 
5
  private $updated_post_id;
6
 
7
+ public function add_hooks() {
8
 
9
  add_filter( 'wcml_product_content_label', [ $this, 'wpseo_custom_field_label' ], 10, 2 );
10
 
compatibility/YikesCustomProductTabs/Factory.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\YikesCustomProductTabs;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use function WCML\functions\getSitePress;
7
+ use function WCML\functions\getWooCommerceWpml;
8
+
9
+ class Factory extends ComponentFactory {
10
+
11
+ /**
12
+ * @inheritDoc
13
+ */
14
+ public function create() {
15
+ return new \WCML_YIKES_Custom_Product_Tabs( getWooCommerceWpml(), getSitePress(), self::getElementTranslationPackage() );
16
+ }
17
+ }
compatibility/{class-wcml-yikes-custom-product-tabs.php → YikesCustomProductTabs/class-wcml-yikes-custom-product-tabs.php} RENAMED
@@ -3,7 +3,7 @@
3
  /**
4
  * Class WCML_YIKES_Custom_Product_Tabs
5
  */
6
- class WCML_YIKES_Custom_Product_Tabs {
7
 
8
  const CUSTOM_TABS_FIELD = 'yikes_woo_products_tabs';
9
 
@@ -237,6 +237,7 @@ class WCML_YIKES_Custom_Product_Tabs {
237
 
238
  public function show_pointer_info() {
239
 
 
240
  $a = __( 'You can translate your custom product tabs on the %s', 'woocommerce-multilingual' );
241
  $b = __( 'WooCommerce product translation page', 'woocommerce-multilingual' );
242
  $link = '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">' . $b . '</a>';
3
  /**
4
  * Class WCML_YIKES_Custom_Product_Tabs
5
  */
6
+ class WCML_YIKES_Custom_Product_Tabs implements \IWPML_Action {
7
 
8
  const CUSTOM_TABS_FIELD = 'yikes_woo_products_tabs';
9
 
237
 
238
  public function show_pointer_info() {
239
 
240
+ /* translators: %s is an HTML link pointing to WooCommerce product translation page */
241
  $a = __( 'You can translate your custom product tabs on the %s', 'woocommerce-multilingual' );
242
  $b = __( 'WooCommerce product translation page', 'woocommerce-multilingual' );
243
  $link = '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">' . $b . '</a>';
compatibility/YithWcQuickView/Factory.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace WCML\Compatibility\YithWcQuickView;
4
+
5
+ use WCML\Compatibility\ComponentFactory;
6
+ use WCML\StandAlone\IStandAloneAction;
7
+
8
+ /**
9
+ * @see https://wordpress.org/plugins/yith-woocommerce-quick-view/
10
+ */
11
+ class Factory extends ComponentFactory implements IStandAloneAction {
12
+
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ public function create() {
17
+ $hooks = [];
18
+
19
+ if ( wcml_is_multi_currency_on() ) {
20
+ $hooks[] = new MulticurrencyHooks();
21
+ }
22
+
23
+ return $hooks;
24
+ }
25
+ }
compatibility/{class-wcml-yith-wcqv.php → YithWcQuickView/MulticurrencyHooks.php} RENAMED
@@ -1,18 +1,21 @@
1
  <?php
2
 
3
- class WCML_YITH_WCQV {
4
 
5
- public function add_hooks() {
6
 
 
7
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'ajax_action_needs_multi_currency' ] );
8
-
9
  }
10
 
 
 
 
 
 
11
  public function ajax_action_needs_multi_currency( $actions ) {
12
-
13
  $actions[] = 'yith_load_product_quick_view';
14
 
15
  return $actions;
16
  }
17
-
18
  }
1
  <?php
2
 
3
+ namespace WCML\Compatibility\YithWcQuickView;
4
 
5
+ class MulticurrencyHooks implements \IWPML_Action {
6
 
7
+ public function add_hooks() {
8
  add_filter( 'wcml_multi_currency_ajax_actions', [ $this, 'ajax_action_needs_multi_currency' ] );
 
9
  }
10
 
11
+ /**
12
+ * @param array $actions
13
+ *
14
+ * @return array
15
+ */
16
  public function ajax_action_needs_multi_currency( $actions ) {
 
17
  $actions[] = 'yith_load_product_quick_view';
18
 
19
  return $actions;
20
  }
 
21
  }
compatibility/class-wcml-checkout-addons.php DELETED
@@ -1,61 +0,0 @@
1
- <?php
2
- /**
3
- * Compatibility class for wc_checkout_addons plugin.
4
- *
5
- * @author konrad
6
- */
7
- class WCML_Checkout_Addons {
8
-
9
- public function add_hooks() {
10
- add_filter( 'option_wc_checkout_add_ons', [ $this, 'option_wc_checkout_add_ons' ], 10, 2 );
11
- }
12
-
13
- public function option_wc_checkout_add_ons( $option_value, $option_name = null ) {
14
- if ( is_array( $option_value ) ) {
15
- foreach ( $option_value as $addon_id => $addon_conf ) {
16
- $addon_conf = $this->handle_option_part( $addon_id, $addon_conf );
17
- if ( isset( $addon_conf['options'] ) ) {
18
- foreach ( $addon_conf['options'] as $index => $fields ) {
19
- $addon_conf['options'][ $index ] = $this->handle_option_part( $index, $fields );
20
- }
21
- }
22
- $option_value[ $addon_id ] = $addon_conf;
23
- }
24
- }
25
-
26
- return $option_value;
27
- }
28
-
29
- private function handle_option_part( $index, $conf ) {
30
- $conf = $this->register_or_translate( 'label', $conf, $index );
31
- $conf = $this->register_or_translate( 'description', $conf, $index );
32
- $conf = $this->adjust_price( $conf );
33
- return $conf;
34
- }
35
-
36
- private function register_or_translate( $element, $conf, $index ) {
37
- if ( isset( $conf[ $element ] ) ) {
38
- $string = $conf[ $element ];
39
- $key = $index . '_' . $element . '_' . md5( $string );
40
- if ( $this->is_default_language() ) {
41
- do_action( 'wpml_register_single_string', 'wc_checkout_addons', $key, $string );
42
- } else {
43
- $conf[ $element ] = apply_filters( 'wpml_translate_single_string', $string, 'wc_checkout_addons', $key );
44
- }
45
- }
46
- return $conf;
47
- }
48
-
49
- private function adjust_price( $conf ) {
50
- if ( isset( $conf['adjustment'], $conf['adjustment_type'] )
51
- && $conf['adjustment_type'] === 'fixed'
52
- && ! $this->is_default_language() ) {
53
- $conf['adjustment'] = apply_filters( 'wcml_raw_price_amount', $conf['adjustment'] );
54
- }
55
- return $conf;
56
- }
57
-
58
- private function is_default_language() {
59
- return apply_filters( 'wpml_current_language', null ) === apply_filters( 'wpml_default_language', null );
60
- }
61
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-compatibility-helper.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  class WCML_Compatibility_Helper {
4
 
5
- public function get_product_type( $product_id ) {
6
 
7
  if ( $terms = wp_get_object_terms( $product_id, 'product_type' ) ) {
8
  $product_type = sanitize_title( current( $terms )->name );
2
 
3
  class WCML_Compatibility_Helper {
4
 
5
+ public static function get_product_type( $product_id ) {
6
 
7
  if ( $terms = wp_get_object_terms( $product_id, 'product_type' ) ) {
8
  $product_type = sanitize_title( current( $terms )->name );
compatibility/class-wcml-litespeed-cache.php DELETED
@@ -1,26 +0,0 @@
1
- <?php
2
-
3
- class WCML_LiteSpeed_Cache {
4
-
5
- public function add_hooks() {
6
- // LiteSpeed_Cache_API::vary is available since 2.6.
7
- if ( method_exists( 'LiteSpeed_Cache_API', 'v' ) && LiteSpeed_Cache_API::v( '2.6' ) ) {
8
- add_filter( 'wcml_client_currency', [ $this, 'apply_client_currency' ] );
9
- add_action( 'wcml_set_client_currency', [ $this, 'set_client_currency' ] );
10
- }
11
- }
12
-
13
- public function set_client_currency( $currency ) {
14
- $this->apply_client_currency( $currency );
15
-
16
- LiteSpeed_Cache_API::force_vary();
17
- }
18
-
19
- public function apply_client_currency( $currency ) {
20
- LiteSpeed_Cache_API::vary( 'wcml_currency', $currency, wcml_get_woocommerce_currency_option() );
21
-
22
- return $currency;
23
- }
24
-
25
- }
26
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-mix-and-match-products.php DELETED
@@ -1,53 +0,0 @@
1
- <?php
2
-
3
- class WCML_Mix_and_Match_Products {
4
-
5
- public function __construct() {
6
- add_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10, 4 );
7
- }
8
-
9
- public function sync_mnm_data( $meta_id, $post_id, $meta_key, $meta_value ) {
10
- if ( '_mnm_data' !== $meta_key ) {
11
- return;
12
- }
13
-
14
- global $sitepress, $woocommerce_wpml;
15
-
16
- $post = get_post( $post_id );
17
-
18
- // Skip auto-drafts, skip autosave.
19
- if ( 'auto-draft' === $post->post_status || isset( $_POST['autosave'] ) ) {
20
- return;
21
- }
22
-
23
- if ( 'product' === $post->post_type ) {
24
- remove_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10 );
25
-
26
- if ( $woocommerce_wpml->products->is_original_product( $post_id ) ) {
27
- $original_product_id = $post_id;
28
- } else {
29
- $original_product_id = $woocommerce_wpml->products->get_original_product_id( $post_id );
30
- }
31
-
32
- $mnm_data = maybe_unserialize( get_post_meta( $original_product_id, '_mnm_data', true ) );
33
- $product_trid = $sitepress->get_element_trid( $original_product_id, 'post_product' );
34
- $product_translations = $sitepress->get_element_translations( $product_trid, 'post_product' );
35
-
36
- foreach ( $product_translations as $product_translation ) {
37
- if ( empty( $product_translation->original ) ) {
38
- foreach ( $mnm_data as $key => $mnm_element ) {
39
-
40
- $trnsl_prod = apply_filters( 'translate_object_id', $key, 'product', true, $product_translation->language_code );
41
- $mnm_element['product_id'] = $trnsl_prod;
42
- $mnm_data[ $trnsl_prod ] = $mnm_element;
43
- unset( $mnm_data[ $key ] );
44
- }
45
-
46
- update_post_meta( $product_translation->element_id, '_mnm_data', $mnm_data );
47
- }
48
- }
49
-
50
- add_action( 'updated_post_meta', [ $this, 'sync_mnm_data' ], 10, 4 );
51
- }
52
- }
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-pip.php DELETED
@@ -1,104 +0,0 @@
1
- <?php
2
-
3
- class WCML_Pip {
4
-
5
- public function __construct() {
6
-
7
- add_filter( 'wcml_send_email_order_id', [ $this, 'wcml_send_email_order_id' ] );
8
- add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
9
- add_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
10
- add_action( 'wc_pip_print', [ $this, 'print_invoice_language' ], 10, 3 );
11
-
12
- }
13
-
14
- public function wcml_send_email_order_id( $order_id ) {
15
-
16
- $pip_order_id = $this->get_pip_order_id();
17
-
18
- if ( $pip_order_id ) {
19
- $order_id = $pip_order_id;
20
- }
21
-
22
- return $order_id;
23
-
24
- }
25
-
26
- public function filter_pip_currency_symbol( $currency_symbol ) {
27
-
28
- remove_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
29
-
30
- $currency = $this->get_pip_order_currency();
31
-
32
- if ( $currency ) {
33
- $currency_symbol = get_woocommerce_currency_symbol( $currency );
34
- }
35
-
36
- add_filter( 'woocommerce_currency_symbol', [ $this, 'filter_pip_currency_symbol' ] );
37
-
38
- return $currency_symbol;
39
- }
40
-
41
- public function filter_pip_currency_position( $currency ) {
42
-
43
- remove_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
44
-
45
- $currency = $this->get_pip_order_currency( $currency );
46
-
47
- add_filter( 'wcml_filter_currency_position', [ $this, 'filter_pip_currency_position' ] );
48
-
49
- return $currency;
50
-
51
- }
52
-
53
- public function get_pip_order_id() {
54
-
55
- $order_id = false;
56
-
57
- if ( isset( $_GET['wc_pip_action'] ) && isset( $_GET['order_id'] ) ) {
58
- $order_id = $_GET['order_id'];
59
- } elseif (
60
- isset( $_POST['action'] ) &&
61
- (
62
- $_POST['action'] == 'wc_pip_order_send_email' ||
63
- $_POST['action'] == 'wc_pip_send_email_packing_list'
64
- ) &&
65
- isset( $_POST['order_id'] )
66
- ) {
67
- $order_id = $_POST['order_id'];
68
- }
69
-
70
- return $order_id;
71
- }
72
-
73
- public function get_pip_order_currency( $currency = false ) {
74
-
75
- $pip_order_id = $this->get_pip_order_id();
76
-
77
- if ( $pip_order_id && isset( WC()->order_factory ) ) {
78
-
79
- $the_order = WC()->order_factory->get_order( $pip_order_id );
80
-
81
- if ( $the_order ) {
82
- $currency = $the_order->get_currency();
83
-
84
- if ( ! $currency && isset( $_COOKIE['_wcml_order_currency'] ) ) {
85
- $currency = $_COOKIE['_wcml_order_currency'];
86
- }
87
- }
88
- }
89
-
90
- return $currency;
91
-
92
- }
93
-
94
- public function print_invoice_language( $type, $order_id, $order_ids ) {
95
-
96
- $order_language = get_post_meta( $order_id, 'wpml_language', true );
97
-
98
- if ( $order_language ) {
99
- do_action( 'wpml_switch_language', $order_language );
100
- }
101
-
102
- }
103
-
104
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-product-addons.php DELETED
@@ -1,664 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Class WCML_Product_Addons
5
- */
6
- class WCML_Product_Addons {
7
-
8
- const TEMPLATE_FOLDER = '/templates/compatibility/';
9
- const DIALOG_TEMPLATE = 'product-addons-prices-dialog.twig';
10
- const SETTINGS_TEMPLATE = 'product-addons-prices-settings.twig';
11
- const PRICE_OPTION_KEY = '_product_addon_prices';
12
-
13
- /**
14
- * @var SitePress
15
- */
16
- public $sitepress;
17
- /**
18
- * @var woocommerce_wpml
19
- */
20
- private $woocommerce_wpml;
21
- /**
22
- * @var int
23
- */
24
- private $multi_currency_mode;
25
-
26
- /**
27
- * WCML_Product_Addons constructor.
28
- *
29
- * @param SitePress $sitepress
30
- * @param woocommerce_wpml $woocommerce_wpml
31
- */
32
- public function __construct( SitePress $sitepress, woocommerce_wpml $woocommerce_wpml ) {
33
- $this->sitepress = $sitepress;
34
- $this->woocommerce_wpml = $woocommerce_wpml;
35
- $this->multi_currency_mode = $woocommerce_wpml->settings['enable_multi_currency'];
36
- }
37
-
38
- public function add_hooks() {
39
-
40
- add_action( 'init', [ $this, 'load_assets' ] );
41
- add_filter( 'get_product_addons_product_terms', [ $this, 'addons_product_terms' ] );
42
- add_filter( 'get_product_addons_fields', [ $this, 'product_addons_price_filter' ], 10, 2 );
43
-
44
- add_action( 'updated_post_meta', [ $this, 'register_addons_strings' ], 10, 4 );
45
- add_action( 'added_post_meta', [ $this, 'register_addons_strings' ], 10, 4 );
46
-
47
- add_action( 'woocommerce-product-addons_panel_start', [ $this, 'show_pointer_info' ] );
48
-
49
- if ( is_admin() ) {
50
-
51
- if ( $this->is_global_addon_edit_page() ) {
52
- if ( ! isset( $_GET['edit'] ) ) {
53
- add_action( 'admin_notices', [ $this, 'inf_translate_strings' ] );
54
- }
55
- }
56
-
57
- add_action( 'wcml_gui_additional_box_html', [ $this, 'custom_box_html' ], 10, 3 );
58
- add_filter( 'wcml_gui_additional_box_data', [ $this, 'custom_box_html_data' ], 10, 3 );
59
- add_action( 'wcml_update_extra_fields', [ $this, 'addons_update' ], 10, 3 );
60
-
61
- add_action( 'woocommerce_product_data_panels', [ $this, 'show_pointer_info' ] );
62
-
63
- add_filter( 'wcml_do_not_display_custom_fields_for_product', [ $this, 'replace_tm_editor_custom_fields_with_own_sections' ] );
64
-
65
- if ( $this->is_multi_currency_on() ) {
66
- add_action( 'woocommerce_product_addons_panel_start', [ $this, 'load_dialog_resources' ] );
67
- add_action( 'woocommerce_product_addons_panel_option_row', [ $this, 'dialog_button_after_option_row' ], 10, 4 );
68
- add_action( 'woocommerce_product_addons_panel_before_options', [ $this, 'dialog_button_before_options' ], 10, 3 );
69
- add_action( 'wcml_before_sync_product', [ $this, 'update_custom_prices_values' ] );
70
- add_action( 'woocommerce_product_addons_global_edit_objects', [ $this, 'custom_prices_settings_block' ] );
71
- }
72
- } else {
73
- add_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10, 4 );
74
- }
75
-
76
- add_filter(
77
- 'wcml_cart_contents_not_changed',
78
- [
79
- $this,
80
- 'filter_booking_addon_product_in_cart_contents',
81
- ],
82
- 20
83
- );
84
-
85
- add_filter(
86
- 'get_product_addons_global_query_args',
87
- [
88
- $this,
89
- 'set_global_ids_in_query_args',
90
- ]
91
- );
92
- }
93
-
94
-
95
- private function is_global_addon_edit_page() {
96
- global $pagenow;
97
-
98
- return 'edit.php' === $pagenow &&
99
- isset( $_GET['post_type'] ) &&
100
- 'product' === $_GET['post_type'] &&
101
- isset( $_GET['page'] ) &&
102
- ( 'global_addons' === $_GET['page'] || 'addons' === $_GET['page'] );
103
- }
104
-
105
- /**
106
- * @param string $product_id
107
- *
108
- * @return array
109
- */
110
- private function get_product_addons( $product_id ) {
111
- return maybe_unserialize( get_post_meta( $product_id, '_product_addons', true ) );
112
- }
113
-
114
- /**
115
- * @param $meta_id
116
- * @param $id
117
- * @param $meta_key
118
- * @param $addons
119
- */
120
- public function register_addons_strings( $meta_id, $id, $meta_key, $addons ) {
121
- if ( '_product_addons' === $meta_key && 'global_product_addon' === get_post_type( $id ) ) {
122
- $this->update_custom_prices_values( $id );
123
- foreach ( $addons as $addon ) {
124
- $addon_data = wpml_collect( $addon );
125
- $addon_type = $addon_data->get( 'type' );
126
- $addon_position = $addon_data->get( 'position' );
127
- // register name
128
- do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_name', $addon_data->get( 'name' ) );
129
- // register description
130
- do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_description', $addon_data->get( 'description' ) );
131
- // register options labels
132
- if ( $addon_data->offsetExists( 'options' ) ) {
133
- foreach ( $addon_data->get( 'options' ) as $key => $option ) {
134
- do_action( 'wpml_register_single_string', 'wc_product_addons_strings', $id . '_addon_' . $addon_type . '_' . $addon_position . '_option_label_' . $key, wpml_collect( $option )->get( 'label' ) );
135
- }
136
- }
137
- }
138
- }
139
- }
140
-
141
- /**
142
- * @param $null
143
- * @param $object_id
144
- * @param $meta_key
145
- * @param $single
146
- *
147
- * @return array
148
- */
149
- public function translate_addons_strings( $null, $object_id, $meta_key, $single ) {
150
-
151
- if ( '_product_addons' === $meta_key && 'global_product_addon' === get_post_type( $object_id ) ) {
152
-
153
- remove_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10 );
154
- $addons = get_post_meta( $object_id, $meta_key, true );
155
- add_filter( 'get_post_metadata', [ $this, 'translate_addons_strings' ], 10, 4 );
156
-
157
- if ( is_array( $addons ) ) {
158
- foreach ( $addons as $key => $addon ) {
159
- $addon_data = wpml_collect( $addon );
160
- $addon_type = $addon_data->get( 'type' );
161
- $addon_position = $addon_data->get( 'position' );
162
- // register name
163
- $addons[ $key ]['name'] = apply_filters( 'wpml_translate_single_string', $addon_data->get( 'name' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_name' );
164
- // register description
165
- $addons[ $key ]['description'] = apply_filters( 'wpml_translate_single_string', $addon_data->get( 'description' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_description' );
166
- // register options labels
167
- if ( $addon_data->offsetExists( 'options' ) ) {
168
- foreach ( $addon['options'] as $opt_key => $option ) {
169
- $addons[ $key ]['options'][ $opt_key ]['label'] = apply_filters( 'wpml_translate_single_string', wpml_collect( $option )->get( 'label' ), 'wc_product_addons_strings', $object_id . '_addon_' . $addon_type . '_' . $addon_position . '_option_label_' . $opt_key );
170
- }
171
- }
172
- }
173
- }
174
-
175
- return [ 0 => $addons ];
176
- }
177
-
178
- return $null;
179
-
180
- }
181
-
182
- /**
183
- * @param $addons
184
- * @param $post_id
185
- *
186
- * @return mixed
187
- */
188
- public function product_addons_price_filter( $addons, $post_id ) {
189
-
190
- if ( $this->is_multi_currency_on() ) {
191
-
192
- foreach ( $addons as $add_id => $addon ) {
193
-
194
- $addon_data = wpml_collect( $addon );
195
-
196
- if ( $addon_data->offsetExists( 'price' ) && $addon_data->get( 'price' ) ) {
197
- $addons[ $add_id ]['price'] = $this->converted_addon_price( $addon, $post_id );
198
- }
199
-
200
- if ( $addon_data->offsetExists( 'options' ) ) {
201
- foreach ( $addon_data->get( 'options' ) as $key => $option ) {
202
- $addons[ $add_id ]['options'][ $key ]['price'] = $this->converted_addon_price( $option, $post_id );
203
- }
204
- }
205
- }
206
- }
207
-
208
- return $addons;
209
- }
210
-
211
- /**
212
- * @param array $addon
213
- * @param int $post_id
214
- *
215
- * @return string
216
- */
217
- private function converted_addon_price( $addon, $post_id ) {
218
-
219
- $addonData = wpml_collect( $addon );
220
-
221
- $is_custom_prices_on = $this->is_product_custom_prices_on( $post_id );
222
- $field = 'price_' . $this->woocommerce_wpml->multi_currency->get_client_currency();
223
-
224
- if (
225
- $is_custom_prices_on &&
226
- $addonData->get( $field )
227
- ) {
228
- return $addonData->get( $field );
229
- }
230
-
231
- if ( wpml_collect( [ 'flat_fee', 'quantity_based' ] )->contains( $addonData->get( 'price_type' ) ) ) {
232
- return apply_filters( 'wcml_raw_price_amount', $addonData->get( 'price' ) );
233
- }
234
-
235
- return $addonData->get( 'price' );
236
- }
237
-
238
- /**
239
- * @param $product_terms
240
- *
241
- * @return array
242
- */
243
- public function addons_product_terms( $product_terms ) {
244
- foreach ( $product_terms as $key => $product_term ) {
245
- $product_terms[ $key ] = apply_filters( 'translate_object_id', $product_term, 'product_cat', true, $this->sitepress->get_default_language() );
246
- }
247
-
248
- return $product_terms;
249
- }
250
-
251
- public function inf_translate_strings() {
252
-
253
- $pointer_ui = new WCML_Pointer_UI(
254
- sprintf( __( 'You can translate strings related to global add-ons on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=wc_product_addons_strings' ) . '">', '</a>' ),
255
- WCML_Tracking_Link::getWcmlProductAddonsDoc(),
256
- 'wpbody-content .woocommerce>h2'
257
- );
258
-
259
- $pointer_ui->show();
260
- }
261
-
262
- /**
263
- * @param $obj
264
- * @param $product_id
265
- * @param $data
266
- */
267
- public function custom_box_html( $obj, $product_id, $data ) {
268
-
269
- $product_addons = $this->get_product_addons( $product_id );
270
-
271
- if ( ! empty( $product_addons ) ) {
272
- foreach ( $product_addons as $addon_id => $product_addon ) {
273
- $addon_data = wpml_collect( $product_addon );
274
-
275
- $addons_section = new WPML_Editor_UI_Field_Section( sprintf( __( 'Product Add-ons Group "%s"', 'woocommerce-multilingual' ), $addon_data->get( 'name' ) ) );
276
-
277
- $group = new WPML_Editor_UI_Field_Group( '', true );
278
- $addon_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_name', __( 'Name', 'woocommerce-multilingual' ), $data, false );
279
- $group->add_field( $addon_field );
280
- $addon_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_description', __( 'Description', 'woocommerce-multilingual' ), $data, false );
281
- $group->add_field( $addon_field );
282
-
283
- $addons_section->add_field( $group );
284
-
285
- if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
286
-
287
- $labels_group = new WPML_Editor_UI_Field_Group( __( 'Options', 'woocommerce-multilingual' ), true );
288
-
289
- foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
290
- $option_label_field = new WPML_Editor_UI_Single_Line_Field( 'addon_' . $addon_id . '_option_' . $option_id . '_label', __( 'Label', 'woocommerce-multilingual' ), $data, false );
291
- $labels_group->add_field( $option_label_field );
292
- }
293
- $addons_section->add_field( $labels_group );
294
- }
295
- $obj->add_field( $addons_section );
296
- }
297
- }
298
- }
299
-
300
- /**
301
- * @param $data
302
- * @param $product_id
303
- * @param $translation
304
- *
305
- * @return mixed
306
- */
307
- public function custom_box_html_data( $data, $product_id, $translation ) {
308
-
309
- $product_addons = $this->get_product_addons( $product_id );
310
-
311
- if ( ! empty( $product_addons ) ) {
312
- foreach ( $product_addons as $addon_id => $product_addon ) {
313
- $addon_data = wpml_collect( $product_addon );
314
- $data[ 'addon_' . $addon_id . '_name' ] = [ 'original' => $addon_data->get( 'name' ) ];
315
- $data[ 'addon_' . $addon_id . '_description' ] = [ 'original' => $addon_data->get( 'description' ) ];
316
- if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
317
- foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
318
- $data[ 'addon_' . $addon_id . '_option_' . $option_id . '_label' ] = [ 'original' => wpml_collect( $option )->get( 'label' ) ];
319
- }
320
- }
321
- }
322
-
323
- if ( $translation ) {
324
- $translated_product_addons = $this->get_product_addons( $translation->ID );
325
- if ( ! empty( $translated_product_addons ) ) {
326
- foreach ( $translated_product_addons as $addon_id => $transalted_product_addon ) {
327
- $translated_addon_data = wpml_collect( $transalted_product_addon );
328
- $data[ 'addon_' . $addon_id . '_name' ]['translation'] = $translated_addon_data->get( 'name' );
329
- $data[ 'addon_' . $addon_id . '_description' ]['translation'] = $translated_addon_data->get( 'description' );
330
- if ( $translated_addon_data->offsetExists( 'options' ) && $translated_addon_data->get( 'options' ) ) {
331
- foreach ( $translated_addon_data->get( 'options' ) as $option_id => $option ) {
332
- $data[ 'addon_' . $addon_id . '_option_' . $option_id . '_label' ]['translation'] = wpml_collect( $option )->get( 'label' );
333
- }
334
- }
335
- }
336
- }
337
- }
338
- }
339
-
340
- return $data;
341
- }
342
-
343
- /**
344
- * @param $original_product_id
345
- * @param $product_id
346
- * @param $data
347
- */
348
- public function addons_update( $original_product_id, $product_id, $data ) {
349
-
350
- $product_addons = $this->get_product_addons( $original_product_id );
351
-
352
- if ( ! empty( $product_addons ) ) {
353
-
354
- foreach ( $product_addons as $addon_id => $product_addon ) {
355
- $addon_data = wpml_collect( $product_addon );
356
- $product_addons[ $addon_id ]['name'] = $data[ md5( 'addon_' . $addon_id . '_name' ) ];
357
- $product_addons[ $addon_id ]['description'] = $data[ md5( 'addon_' . $addon_id . '_description' ) ];
358
-
359
- if ( $addon_data->offsetExists( 'options' ) && $addon_data->get( 'options' ) ) {
360
- foreach ( $addon_data->get( 'options' ) as $option_id => $option ) {
361
- $product_addons[ $addon_id ]['options'][ $option_id ]['label'] = $data[ md5( 'addon_' . $addon_id . '_option_' . $option_id . '_label' ) ];
362
- }
363
- }
364
- }
365
- }
366
-
367
- update_post_meta( $product_id, '_product_addons', $product_addons );
368
- }
369
-
370
- public function show_pointer_info() {
371
-
372
- $pointer_ui = new WCML_Pointer_UI(
373
- sprintf( __( 'You can translate the Group Name, Group Description and every Option Label of your product add-on on the %1$sWooCommerce product translation page%2$s', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=wpml-wcml' ) . '">', '</a>' ),
374
- WCML_Tracking_Link::getWcmlProductAddonsDoc(),
375
- 'product_addons_data>p'
376
- );
377
-
378
- $pointer_ui->show();
379
- }
380
-
381
- public function replace_tm_editor_custom_fields_with_own_sections( $fields ) {
382
- $fields[] = '_product_addons';
383
-
384
- return $fields;
385
- }
386
-
387
- // special case for WC Bookings plugin - need add addon cost after re-calculating booking costs #wcml-1877
388
- public function filter_booking_addon_product_in_cart_contents( $cart_item ) {
389
-
390
- $is_booking_product_with_addons = $cart_item['data'] instanceof WC_Product_Booking && isset( $cart_item['addons'] );
391
-
392
- if ( $this->is_multi_currency_on() && $is_booking_product_with_addons ) {
393
- $cost = $cart_item['data']->get_price();
394
-
395
- foreach ( $cart_item['addons'] as $addon ) {
396
- $cost += $addon['price'];
397
- }
398
-
399
- $cart_item['data']->set_price( $cost );
400
- }
401
-
402
- return $cart_item;
403
- }
404
-
405
- public function set_global_ids_in_query_args( $args ) {
406
-
407
- if ( ! is_archive() ) {
408
-
409
- remove_filter( 'get_terms_args', [ $this->sitepress, 'get_terms_args_filter' ], 10 );
410
- remove_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1 );
411
- remove_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ], 10 );
412
-
413
- $matched_addons_ids = wp_list_pluck( get_posts( $args ), 'ID' );
414
-
415
- if ( $matched_addons_ids ) {
416
- $args['include'] = $matched_addons_ids;
417
- unset( $args['tax_query'] );
418
- }
419
-
420
- add_filter( 'get_terms_args', [ $this->sitepress, 'get_terms_args_filter' ], 10, 2 );
421
- add_filter( 'get_term', [ $this->sitepress, 'get_term_adjust_id' ], 1 );
422
- add_filter( 'terms_clauses', [ $this->sitepress, 'terms_clauses' ], 10, 3 );
423
- }
424
-
425
- return $args;
426
- }
427
-
428
- /**
429
- * @return bool
430
- */
431
- private function is_multi_currency_on() {
432
- return $this->multi_currency_mode === $this->sitepress->get_wp_api()->constant( 'WCML_MULTI_CURRENCIES_INDEPENDENT' );
433
- }
434
-
435
- public function load_dialog_resources() {
436
- wp_enqueue_script( 'wcml-dialogs', WCML_PLUGIN_URL . '/res/js/dialogs' . WCML_JS_MIN . '.js', [ 'jquery-ui-dialog', 'underscore' ], WCML_VERSION );
437
- }
438
-
439
- /**
440
- * @param WP_Post|null $product
441
- * @param array $product_addons
442
- * @param int $loop
443
- * @param array $option
444
- */
445
- public function dialog_button_after_option_row( $product, $product_addons, $loop, $option ) {
446
- if ( $option ) {
447
- $this->render_edit_price_element( $this->get_prices_dialog_model( $product_addons, $option, $loop, $this->is_product_custom_prices_on( $product ? $product->ID : false ) ) );
448
- }
449
-
450
- }
451
-
452
- /**
453
- * @param WP_Post|null $product
454
- * @param array $product_addons
455
- * @param int $loop
456
- */
457
- public function dialog_button_before_options( $product, $product_addons, $loop ) {
458
- $this->render_edit_price_element( $this->get_prices_dialog_model( [], $product_addons, $loop, $this->is_product_custom_prices_on( $product ? $product->ID : false ) ) );
459
- }
460
-
461
- /**
462
- * @param array $model
463
- */
464
- private function render_edit_price_element( $model ) {
465
- $twig_loader = $this->get_twig_loader();
466
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
467
- echo $twig_loader->get_template()->show( $model, self::DIALOG_TEMPLATE );
468
- }
469
-
470
- /**
471
- * @return array
472
- */
473
- private function get_one_price_types() {
474
-
475
- return [
476
- 'custom_text',
477
- 'custom_textarea',
478
- 'file_upload',
479
- 'input_multiplier',
480
- ];
481
- }
482
-
483
- /**
484
- * @return WPML_Twig_Template_Loader
485
- */
486
- private function get_twig_loader() {
487
- return new WPML_Twig_Template_Loader( [ $this->sitepress->get_wp_api()->constant( 'WCML_PLUGIN_PATH' ) . self::TEMPLATE_FOLDER ] );
488
- }
489
-
490
- /**
491
- * @param int|false $product
492
- *
493
- * @return mixed
494
- */
495
- private function is_product_custom_prices_on( $product_id ) {
496
-
497
- if ( $product_id ) {
498
- return get_post_meta( $product_id, '_wcml_custom_prices_status', true );
499
- }
500
-
501
- if ( $this->is_global_addon_edit_page() ) {
502
- return $this->get_global_addon_prices_status();
503
- }
504
-
505
- return false;
506
- }
507
-
508
- /**
509
- * @return bool|mixed
510
- */
511
- private function get_global_addon_prices_status() {
512
-
513
- if ( isset( $_GET['edit'] ) ) {
514
- return get_post_meta( $_GET['edit'], '_wcml_custom_prices_status', true );
515
- } elseif ( isset( $_POST['_wcml_custom_prices'] ) ) {
516
- return $_POST['_wcml_custom_prices'];
517
- }
518
-
519
- return false;
520
- }
521
-
522
- public function load_assets() {
523
- global $pagenow;
524
-
525
- $is_product_page = 'post.php' === $pagenow && isset( $_GET['post'] );
526
- $is_product_new_page = 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'];
527
-
528
- if ( $is_product_page || $is_product_new_page || $this->is_global_addon_edit_page() ) {
529
- wp_enqueue_script( 'wcml-product-addons', WCML_PLUGIN_URL . '/compatibility/res/js/wcml-product-addons' . WCML_JS_MIN . '.js', [ 'jquery' ], WCML_VERSION );
530
- wp_enqueue_style( 'wcml-product-addons', WCML_PLUGIN_URL . '/compatibility/res/css/wcml-product-addons.css', '', WCML_VERSION );
531
- }
532
-
533
- }
534
-
535
- /**
536
- * @param string $product_id
537
- */
538
- public function update_custom_prices_values( $product_id ) {
539
-
540
- if ( $this->is_multi_currency_on() ) {
541
- $this->save_global_addon_prices_setting( $product_id );
542
- $product_addons = $this->get_product_addons( $product_id );
543
-
544
- if ( $product_addons ) {
545
- $active_currencies = $this->woocommerce_wpml->multi_currency->get_currencies();
546
-
547
- foreach ( $product_addons as $addon_key => $product_addon ) {
548
-
549
- foreach ( $active_currencies as $code => $currency ) {
550
- $price_option_key = self::PRICE_OPTION_KEY;
551
-
552
- if ( in_array( $product_addon['type'], $this->get_one_price_types() ) ) {
553
- $product_addons = $this->update_single_option_prices( $product_addons, $price_option_key, $addon_key, $code );
554
- } else {
555
- $product_addons = $this->update_multiple_options_prices( $product_addons, $price_option_key, $addon_key, $code );
556
- }
557
- }
558
- }
559
-
560
- update_post_meta( $product_id, '_product_addons', $product_addons );
561
- }
562
- }
563
- }
564
-
565
- /**
566
- * @param array $product_addons
567
- * @param string $price_option_key
568
- * @param string $addon_key
569
- * @param string $code
570
- *
571
- * @return array
572
- */
573
- private function update_single_option_prices( $product_addons, $price_option_key, $addon_key, $code ) {
574
- if ( isset( $_POST[ $price_option_key ][ $addon_key ][ 'price_' . $code ][0] ) ) {
575
- $product_addons[ $addon_key ][ 'price_' . $code ] = wc_format_decimal( $_POST[ $price_option_key ][ $addon_key ][ 'price_' . $code ][0] );
576
- }
577
-
578
- return $product_addons;
579
- }
580
-
581
- /**
582
- * @param array $product_addons
583
- * @param string $price_option_key
584
- * @param string $addon_key
585
- * @param string $code
586
- *
587
- * @return array
588
- */
589
- private function update_multiple_options_prices( $product_addons, $price_option_key, $addon_key, $code ) {
590
-
591
- $addon_data = wpml_collect( $product_addons[ $addon_key ] );
592
-
593
- if ( $addon_data->offsetExists( 'options' ) ) {
594
- foreach ( $addon_data->get( 'options' ) as $option_key => $option ) {
595
- if ( isset( $_POST[ $price_option_key ][ $addon_key ][ 'price_' . $code ][ $option_key ] ) ) {
596
- $product_addons[ $addon_key ]['options'][ $option_key ][ 'price_' . $code ] = wc_format_decimal( $_POST[ $price_option_key ][ $addon_key ][ 'price_' . $code ][ $option_key ] );
597
- }
598
- }
599
- }
600
-
601
- return $product_addons;
602
- }
603
-
604
- /**
605
- * @param array $product_addons
606
- * @param array $option
607
- * @param int $loop
608
- * @param string|bool $custom_prices_on
609
- *
610
- * @return array
611
- */
612
- private function get_prices_dialog_model( $product_addons, $option, $loop, $custom_prices_on ) {
613
-
614
- $label = isset( $option['label'] ) ? $option['label'] : $option['name'];
615
-
616
- return [
617
- 'strings' => [
618
- 'dialog_title' => __( 'Multi-currency settings', 'woocommerce-multilingual' ),
619
- 'description' => sprintf( __( 'Here you can set different prices for the %s in multiple currencies:', 'woocommerce-multilingual' ), '<strong>' . $label . '</strong>' ),
620
- 'apply' => __( 'Apply', 'woocommerce-multilingual' ),
621
- 'cancel' => __( 'Cancel', 'woocommerce-multilingual' ),
622
- ],
623
- 'custom_prices_on' => $custom_prices_on,
624
- 'dialog_id' => '_product_addon_option_' . md5( uniqid( $loop . $label ) ),
625
- 'option_id' => isset( $product_addons[ $loop ]['options'] ) ? array_search( $option, $product_addons[ $loop ]['options'] ) : '',
626
- 'addon_id' => $loop,
627
- 'option_details' => $option,
628
- 'default_currency' => wcml_get_woocommerce_currency_option(),
629
- 'active_currencies' => $this->woocommerce_wpml->multi_currency->get_currencies(),
630
- ];
631
- }
632
-
633
- public function custom_prices_settings_block() {
634
- $twig_loader = $this->get_twig_loader();
635
- // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
636
- echo $twig_loader->get_template()->show( $this->get_custom_prices_settings_model(), self::SETTINGS_TEMPLATE );
637
- }
638
-
639
- private function get_custom_prices_settings_model() {
640
- return [
641
- 'strings' => [
642
- 'label' => __( 'Multi-currency settings', 'woocommerce-multilingual' ),
643
- 'auto' => __( 'Calculate prices in other currencies automatically', 'woocommerce-multilingual' ),
644
- 'manually' => __( 'Set prices in other currencies manually', 'woocommerce-multilingual' ),
645
- ],
646
- 'custom_prices_on' => $this->get_global_addon_prices_status(),
647
- 'nonce' => wp_create_nonce( 'wcml_save_custom_prices' ),
648
- ];
649
- }
650
-
651
- /**
652
- * @param int $global_addon_id
653
- */
654
- private function save_global_addon_prices_setting( $global_addon_id ) {
655
-
656
- $nonce = filter_var( isset( $_POST['_wcml_custom_prices_nonce'] ) ? $_POST['_wcml_custom_prices_nonce'] : '', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
657
-
658
- if ( isset( $_POST['_wcml_custom_prices'] ) && isset( $nonce ) && wp_verify_nonce( $nonce, 'wcml_save_custom_prices' ) ) {
659
- update_post_meta( $global_addon_id, '_wcml_custom_prices_status', $_POST['_wcml_custom_prices'] );
660
- }
661
-
662
- }
663
-
664
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-wc-name-your-price.php DELETED
@@ -1,29 +0,0 @@
1
- <?php
2
-
3
- class WCML_WC_Name_Your_Price {
4
-
5
- public function __construct() {
6
-
7
- add_action( 'init', [ $this, 'init' ], 9 );
8
-
9
- }
10
-
11
- public function init() {
12
- if ( ! is_admin() ) {
13
- if ( is_callable( [ 'WC_Name_Your_Price_Compatibility', 'is_nyp_gte' ] ) && WC_Name_Your_Price_Compatibility::is_nyp_gte( '3.0' ) ) {
14
- add_filter( 'wc_nyp_raw_suggested_price', [ $this, 'product_price_filter' ], 10, 2 );
15
- add_filter( 'wc_nyp_raw_minimum_price', [ $this, 'product_price_filter' ], 10, 2 );
16
- add_filter( 'wc_nyp_raw_maximum_price', [ $this, 'product_price_filter' ], 10, 2 );
17
- } else {
18
- add_filter( 'woocommerce_raw_suggested_price', [ $this, 'product_price_filter' ], 10, 2 );
19
- add_filter( 'woocommerce_raw_minimum_price', [ $this, 'product_price_filter' ], 10, 2 );
20
- add_filter( 'woocommerce_raw_maximum_price', [ $this, 'product_price_filter' ], 10, 2 );
21
- }
22
- }
23
- }
24
-
25
- public function product_price_filter( $price, $product ) {
26
- return apply_filters( 'wcml_raw_price_amount', $price );
27
- }
28
-
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
compatibility/class-wcml-wc-subscriptions.php DELETED
@@ -1,460 +0,0 @@
1
- <?php
2
-
3
- use function WPML\FP\tap as tap;
4
-
5
- class WCML_WC_Subscriptions {
6
-
7
- /** @var bool */
8
- private $new_subscription = false;
9
-
10
- /** @var bool */
11
- private $prorating_price = false;
12
-
13
- /** @var woocommerce_wpml */
14
- private $woocommerce_wpml;
15
-
16
- /** @var wpdb */
17
- private $wpdb;
18
-
19
- /** @var WC_Cart[]|null $recurring_carts */
20
- private $recurring_carts;
21
-
22
- public function __construct( woocommerce_wpml $woocommerce_wpml, wpdb $wpdb ) {
23
- $this->woocommerce_wpml = $woocommerce_wpml;
24
- $this->wpdb = $wpdb;
25
- }
26
-
27
- public function add_hooks() {
28
-
29
- add_action( 'init', [ $this, 'init' ], 9 );
30
- add_filter( 'wcml_variation_term_taxonomy_ids', [ $this, 'wcml_variation_term_taxonomy_ids' ] );
31
- add_filter( 'woocommerce_subscription_lengths', [ $this, 'woocommerce_subscription_lengths' ], 10, 2 );
32
-
33
- add_filter( 'wcml_register_endpoints_query_vars', [ $this, 'register_endpoint' ], 10, 3 );
34
- add_filter( 'wcml_endpoint_permalink_filter', [ $this, 'endpoint_permalink_filter' ], 10, 2 );
35
-
36
- // Custom prices
37
- add_filter( 'wcml_custom_prices_fields', [ $this, 'set_prices_fields' ], 10, 2 );
38
- add_filter( 'wcml_custom_prices_strings', [ $this, 'set_labels_for_prices_fields' ], 10, 2 );
39
- add_filter( 'wcml_custom_prices_fields_labels', [ $this, 'set_labels_for_prices_fields' ], 10, 2 );
40
- add_filter( 'wcml_update_custom_prices_values', [ $this, 'update_custom_prices_values' ], 10, 3 );
41
- add_action( 'wcml_after_custom_prices_block', [ $this, 'new_subscription_prices_block' ] );
42
-
43
- add_action( 'woocommerce_subscriptions_product_options_pricing', [ $this, 'show_pointer_info' ] );
44
- add_action( 'woocommerce_variable_subscription_pricing', [ $this, 'show_pointer_info' ] );
45
-
46
- add_filter(
47
- 'woocommerce_subscriptions_product_price',
48
- [
49
- $this,
50
- 'woocommerce_subscription_price_from',
51
- ],
52
- 10,
53
- 2
54
- );
55
-
56
- add_filter( 'wcml_xliff_allowed_variations_types', [ $this, 'set_allowed_variations_types_in_xliff' ] );
57
-
58
- // Add language links to email settings
59
- add_filter( 'wcml_emails_options_to_translate', [ $this, 'translate_email_options' ] );
60
- add_filter( 'wcml_emails_section_name_prefix', [ $this, 'email_option_section_prefix' ], 10, 2 );
61
- }
62
-
63
- public function init() {
64
- if ( ! is_admin() ) {
65
- add_filter(
66
- 'woocommerce_subscriptions_product_sign_up_fee',
67
- [
68
- $this,
69
- 'subscriptions_product_sign_up_fee_filter',
70
- ],
71
- 10,
72
- 2
73
- );
74
-
75
- add_action( 'woocommerce_before_calculate_totals', [ $this, 'maybe_backup_recurring_carts' ], 1 );
76
- add_action( 'woocommerce_after_calculate_totals', [ $this, 'maybe_restore_recurring_carts' ], 200 );
77
-
78
- $this->maybe_force_client_currency_for_subscription();
79
-
80
- add_filter( 'wcs_get_subscription', [ $this, 'filter_subscription_items' ] );
81
- }
82
-
83
- // Translate emails
84
- add_filter( 'woocommerce_generated_manual_renewal_order_renewal_notification', [ $this, 'translate_renewal_notification' ], 9 );
85
- add_filter( 'woocommerce_order_status_failed_renewal_notification', [ $this, 'translate_renewal_notification' ], 9 );
86
-
87
- add_filter( 'wcs_switch_proration_new_price_per_day', tap( [ $this, 'set_prorating_price' ] ) );
88
- }
89
-
90
- /**
91
- * Set a flag when we are prorating the price (upgrades/downgrades).
92
- * We do this to skip currency conversion in the sign_up_fee because
93
- * when switching subscription it has already been converted.
94
- */
95
- public function set_prorating_price() {
96
- $this->prorating_price = true;
97
- }
98
-
99
- /**
100
- * Filter Subscription Sign-up fee cost
101
- *
102
- * @param string $subscription_sign_up_fee
103
- * @param WC_Product $product
104
- * @return string
105
- */
106
- public function subscriptions_product_sign_up_fee_filter( $subscription_sign_up_fee, $product ) {
107
-
108
- if ( $product && wcml_is_multi_currency_on() && ! $this->prorating_price ) {
109
- $currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
110
-
111
- if ( $currency !== wcml_get_woocommerce_currency_option() ) {
112
-
113
- $product_id = $product->get_id();
114
- if( $product instanceof WC_Product_Variable_Subscription ){
115
- $product_id = $product->get_meta( '_min_price_variation_id', true );
116
- }
117
-
118
- $original_product_id = $this->woocommerce_wpml->products->get_original_product_id( $product_id );
119
-
120
- if ( get_post_meta( $original_product_id, '_wcml_custom_prices_status', true ) ) {
121
- $subscription_sign_up_fee = get_post_meta( $original_product_id, '_subscription_sign_up_fee_' . $currency, true );
122
- } else {
123
- $subscription_sign_up_fee = apply_filters( 'wcml_raw_price_amount', $subscription_sign_up_fee );
124
- }
125
- }
126
- }
127
-
128
- return $subscription_sign_up_fee;
129
- }
130
-
131
- public function wcml_variation_term_taxonomy_ids( $get_variation_term_taxonomy_ids ) {
132
-
133
- $get_variation_term_taxonomy_id = $this->wpdb->get_var( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.slug = 'variable-subscription'" );
134
-
135
- if ( ! empty( $get_variation_term_taxonomy_id ) ) {
136
- $get_variation_term_taxonomy_ids[] = $get_variation_term_taxonomy_id;
137
- }
138
-
139
- return $get_variation_term_taxonomy_ids;
140
- }
141
-
142
- public function woocommerce_subscription_lengths( $subscription_ranges, $subscription_period ) {
143
-
144
- if ( is_array( $subscription_ranges ) ) {
145
- foreach ( $subscription_ranges as $period => $ranges ) {
146
- if ( is_array( $ranges ) ) {
147
- foreach ( $ranges as $range ) {
148
- if ( $range == '9 months' ) {
149
- $breakpoint = true;
150
- }
151
- $new_subscription_ranges[ $period ][] = apply_filters( 'wpml_translate_single_string', $range, 'wc_subscription_ranges', $range );
152
- }
153
- }
154
- }
155
- }
156
-
157
- return isset( $new_subscription_ranges ) ? $new_subscription_ranges : $subscription_ranges;
158
- }
159
-
160
- public function set_prices_fields( $fields, $product_id ) {
161
- if ( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ) {
162
- $fields[] = '_subscription_sign_up_fee';
163
- }
164
-
165
- return $fields;
166
-
167
- }
168
-
169
- public function set_labels_for_prices_fields( $labels, $product_id ) {
170
-
171
- if ( $this->is_subscriptions_product( $product_id ) || $this->new_subscription ) {
172
- $labels['_regular_price'] = __( 'Subscription Price', 'woocommerce-multilingual' );
173
- $labels['_subscription_sign_up_fee'] = __( 'Sign-up Fee', 'woocommerce-multilingual' );
174
- }
175
-
176
- return $labels;
177
-
178
- }
179
-
180
- public function update_custom_prices_values( $prices, $code, $variation_id = false ) {
181
-
182
- if ( isset( $_POST['_custom_subscription_sign_up_fee'][ $code ] ) ) {
183
- $prices['_subscription_sign_up_fee'] = wc_format_decimal( $_POST['_custom_subscription_sign_up_fee'][ $code ] );
184
- }
185
-
186
- if ( $variation_id && isset( $_POST['_custom_variation_subscription_sign_up_fee'][ $code ][ $variation_id ] ) ) {
187
- $prices['_subscription_sign_up_fee'] = wc_format_decimal( $_POST['_custom_variation_subscription_sign_up_fee'][ $code ][ $variation_id ] );
188
- }
189
-
190
- return $prices;
191
-
192
- }
193
-
194
- public function is_subscriptions_product( $product_id ) {
195
-
196
- $get_variation_term_taxonomy_ids = $this->wpdb->get_col( "SELECT tt.term_taxonomy_id FROM {$this->wpdb->terms} AS t LEFT JOIN {$this->wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE t.slug IN ( 'subscription', 'variable-subscription' ) AND tt.taxonomy = 'product_type'" );
197
-
198
- if ( get_post_type( $product_id ) == 'product_variation' ) {
199
- $product_id = wp_get_post_parent_id( $product_id );
200
- }
201
-
202
- $is_subscriptions_product = $this->wpdb->get_var(
203
- $this->wpdb->prepare(
204
- "SELECT count(object_id) FROM {$this->wpdb->term_relationships}
205
- WHERE object_id = %d AND term_taxonomy_id IN (" . wpml_prepare_in( $get_variation_term_taxonomy_ids, '%d' ) . ')',
206
- $product_id
207
- )
208
- );
209
- return $is_subscriptions_product;
210
- }
211
-
212
- public function new_subscription_prices_block( $product_id ) {
213
-
214
- if ( $product_id == 'new' ) {
215
- $this->new_subscription = true;
216
- echo '<div class="wcml_prices_if_subscription" style="display: none">';
217
- $custom_prices_ui = new WCML_Custom_Prices_UI( $this->woocommerce_wpml, 'new' );
218
- $custom_prices_ui->show();
219
- echo '</div>';
220
- ?>
221
- <script>
222
- jQuery(function($) {
223
- jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new_subscription]').attr( 'id', '_wcml_custom_prices[new_subscription]');
224
- jQuery('.wcml_prices_if_subscription .wcml_custom_prices_options_block>label').attr('for', '_wcml_custom_prices[new_subscription]');
225
- jQuery('.wcml_prices_if_subscription .wcml_schedule_input').each( function(){
226
- jQuery(this).attr('name', jQuery(this).attr('name')+'_subscription');
227
- });
228
-
229
- jQuery('.options_group>.wcml_custom_prices_block .wcml_custom_prices_input:first-child').click();
230
- jQuery('.options_group>.wcml_custom_prices_block .wcml_schedule_options .wcml_schedule_input:first-child').click();
231
-
232
- jQuery(document).on('change', 'select#product-type', function () {
233
- if (jQuery(this).val() == 'subscription') {
234
- jQuery('.wcml_prices_if_subscription').show();
235
- jQuery('.options_group>.wcml_custom_prices_block').hide();
236
- } else if (jQuery(this).val() != 'variable-subscription') {
237
- jQuery('.wcml_prices_if_subscription').hide();
238
- jQuery('.options_group>.wcml_custom_prices_block').show();
239
- }
240
- });
241
-
242
- jQuery(document).on('click', '#publish', function () {
243
- if ( jQuery('.wcml_prices_if_subscription').is( ':visible' ) ) {
244
- jQuery('.options_group>.wcml_custom_prices_block').remove();
245
- jQuery('.wcml_prices_if_subscription .wcml_custom_prices_input').attr('name', '_wcml_custom_prices[new]');
246
- jQuery('.wcml_prices_if_subscription .wcml_schedule_input').each( function(){
247
- jQuery(this).attr('name', jQuery(this).attr('name').replace('_subscription','') );
248
- });
249
- }else{
250
- jQuery('.wcml_prices_if_subscription').remove();
251
- }
252
- });
253
- });
254
- </script>
255
- <?php
256
- }
257
- }
258
-
259
- public function register_endpoint( $query_vars, $wc_vars, $obj ) {
260
-
261
- $query_vars['view-subscription'] = $obj->get_endpoint_translation( 'view-subscription', isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );
262
- $query_vars['subscriptions'] = $obj->get_endpoint_translation( 'subscriptions', isset( $wc_vars['subscriptions'] ) ? $wc_vars['subscriptions'] : 'subscriptions' );
263
- return $query_vars;
264
- }
265
-
266
- public function endpoint_permalink_filter( $endpoint, $key ) {
267
-
268
- if ( $key == 'view-subscription' ) {
269
- return 'view-subscription';
270
- }
271
-
272
- return $endpoint;
273
- }
274
-
275
- public function show_pointer_info() {
276
-
277
- $pointer_ui = new WCML_Pointer_UI(
278
- sprintf( __( 'You can translate strings related to subscription products on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the strings.', 'woocommerce-multilingual' ), '<a href="' . admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=woocommerce_subscriptions' ) . '">', '</a>' ),
279
- WCML_Tracking_Link::getWcmlSubscriptionsDoc(),
280
- 'general_product_data .subscription_pricing',
281
- 'prepend'
282
- );
283
-
284
- $pointer_ui->show();
285
- }
286
-
287
- /**
288
- * @param WC_Cart $cart
289
- */
290
- public function maybe_backup_recurring_carts( $cart ) {
291
- if ( ! empty( $cart->recurring_carts ) ) {
292
- $this->recurring_carts = $cart->recurring_carts;
293
- }
294
- }
295
-
296
- /**
297
- * @param WC_Cart $cart
298
- */
299
- public function maybe_restore_recurring_carts( $cart ) {
300
- if ( ! empty( $this->recurring_carts ) ) {
301
- $cart->recurring_carts = $this->recurring_carts;
302
- $this->recurring_carts = null;
303
- }
304
- }
305
-
306
- /**
307
- * @param string $price
308
- * @param WC_Product|WC_Product_Subscription_Variation $product
309
- *
310
- * @return string
311
- */
312
- public function woocommerce_subscription_price_from( $price, $product ) {
313
-
314
- if ( $product && $product instanceof WC_Product_Subscription_Variation ) {
315
-
316
- $custom_prices_on = get_post_meta( $product->get_id(), '_wcml_custom_prices_status', true );
317
- if ( $custom_prices_on ) {
318
- $client_currency = $this->woocommerce_wpml->multi_currency->get_client_currency();
319
-
320
- $price = get_post_meta( $product->get_id(), '_price_' . $client_currency, true );
321
- } else {
322
- $price = apply_filters( 'wcml_raw_price_amount', $price );
323
- }
324
- }
325
-
326
- return $price;
327
- }
328
-
329
- /**
330
- * Force client currency for resubscribe subscription
331
- */
332
- public function maybe_force_client_currency_for_subscription() {
333
-
334
- if ( wcml_is_multi_currency_on() ) {
335
-
336
- $subscription_id = false;
337
- $getData = wpml_collect( $_GET );
338
-
339
- if ( $getData->has( 'resubscribe' ) ) {
340
- $subscription_id = (int) $getData->get( 'resubscribe' );
341
- } elseif ( $getData->has( 'subscription_renewal_early' ) ) {
342
- $subscription_id = (int) $getData->get( 'subscription_renewal_early' );
343
- } elseif ( is_cart() || is_checkout() ) {
344
- $resubscribe_cart_item = wcs_cart_contains_resubscribe();
345
- if ( $resubscribe_cart_item ) {
346
- $subscription_id = $resubscribe_cart_item['subscription_resubscribe']['subscription_id'];
347
- } else {
348
- $early_renewal_cart_item = wcs_cart_contains_early_renewal();
349
- if ( $early_renewal_cart_item ) {
350
- $subscription_id = $early_renewal_cart_item['subscription_renewal']['subscription_renewal_early'];
351
- }
352
- }
353
- }
354
-
355
- if ( $subscription_id ) {
356
- $subscription_currency = get_post_meta( $subscription_id, '_order_currency', true );
357
- if ( $subscription_currency && $this->woocommerce_wpml->multi_currency->get_client_currency() !== $subscription_currency ) {
358
- $this->woocommerce_wpml->multi_currency->set_client_currency( $subscription_currency );
359
- }
360
- }
361
- }
362
- }
363
-
364
- /**
365
- * @param array $allowed_types
366
- *
367
- * @return array
368
- */
369
- public function set_allowed_variations_types_in_xliff( $allowed_types ) {
370
-
371
- $allowed_types[] = 'variable-subscription';
372
- $allowed_types[] = 'subscription_variation';
373
-
374
- return $allowed_types;
375
- }
376
-
377
- /**
378
- * Translate strings of renewal notifications
379
- *
380
- * @param integer $order_id Order ID
381
- */
382
- public function translate_renewal_notification( $order_id ) {
383
-
384
- if ( isset( WC()->mailer()->emails['WCS_Email_Customer_Renewal_Invoice'] ) ) {
385
- $this->woocommerce_wpml->emails->refresh_email_lang( $order_id );
386
-
387
- $WCS_Email_Customer_Renewal_Invoice = WC()->mailer()->emails['WCS_Email_Customer_Renewal_Invoice'];
388
- $WCS_Email_Customer_Renewal_Invoice->heading = __( $WCS_Email_Customer_Renewal_Invoice->heading, 'woocommerce-subscriptions' );
389
- $WCS_Email_Customer_Renewal_Invoice->subject = __( $WCS_Email_Customer_Renewal_Invoice->subject, 'woocommerce-subscriptions' );
390
-
391
- add_filter( 'woocommerce_email_get_option', [ $this, 'translate_heading_subject' ], 10, 4 );
392
- }
393
- }
394
-
395
- /**
396
- * Translate custom heading and subject for renewal notification
397
- *
398
- * @param string $return_value original string
399
- * @param WCS_Email_Customer_Renewal_Invoice $obj Object of email class
400
- * @param string $value Original value from setting
401
- * @param string $key Name of the key
402
- * @return string Translated value or original value incase of not translated
403
- */
404
- public function translate_heading_subject( $return_value, $obj, $value, $key ) {
405
-
406
- if ( $obj instanceof WCS_Email_Customer_Renewal_Invoice ) {
407
- if ( $key == 'subject' || $key == 'heading' ) {
408
- $translated_admin_string = $this->woocommerce_wpml->emails->getStringTranslation( 'admin_texts_woocommerce_customer_renewal_invoice_settings', '[woocommerce_customer_renewal_invoice_settings]' . $key );
409
- return empty( $translated_admin_string ) ? $return_value : $translated_admin_string;
410
- }
411
- }
412
-
413
- return $return_value;
414
- }
415
-
416
- /**
417
- * Add customer renewal invoice option to translate
418
- *
419
- * @param array $emails_options list of option to translate
420
- * @return array $emails_options
421
- */
422
- public function translate_email_options( $emails_options ) {
423
-
424
- if ( is_array( $emails_options ) ) {
425
- $emails_options[] = 'woocommerce_customer_renewal_invoice_settings';
426
- }
427
-
428
- return $emails_options;
429
- }
430
-
431
- /**
432
- * Change section name prefix to add language links
433
- *
434
- * @param string $section_prefix section prefix
435
- * @param string $emails_option current option name
436
- * @return string $section_prefix
437
- */
438
- public function email_option_section_prefix( $section_prefix, $emails_option ) {
439
-
440
- if ( $emails_option === 'woocommerce_customer_renewal_invoice_settings' ) {
441
- return 'wcs_email_';
442
- }
443
-
444
- return $section_prefix;
445
- }
446
-
447
- /**
448
- * @param mixed $subscription
449
- *
450
- * @return mixed
451
- */
452
- public function filter_subscription_items( $subscription ) {
453
-
454
- if ( $subscription instanceof WC_Subscription ) {
455
- $this->woocommerce_wpml->orders->adjust_order_item_in_language( $subscription->get_items() );
456
- }
457
-
458
- return $subscription;
459
- }
460
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dist/css/homeScreen/styles.css ADDED
@@ -0,0 +1 @@
 
1
+ .fade-enter,.fade-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-enter.fade-enter-active,.fade-appear.fade-appear-active{-webkit-animation-name:antFadeIn;animation-name:antFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.fade-leave.fade-leave-active{-webkit-animation-name:antFadeOut;animation-name:antFadeOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.fade-enter,.fade-appear{opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}.fade-leave{-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}@keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}.move-up-enter,.move-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-enter.move-up-enter-active,.move-up-appear.move-up-appear-active{-webkit-animation-name:antMoveUpIn;animation-name:antMoveUpIn;-webkit-animation-play-state:running;animation-play-state:running}.move-up-leave.move-up-leave-active{-webkit-animation-name:antMoveUpOut;animation-name:antMoveUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-up-enter,.move-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-up-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-down-enter,.move-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-enter.move-down-enter-active,.move-down-appear.move-down-appear-active{-webkit-animation-name:antMoveDownIn;animation-name:antMoveDownIn;-webkit-animation-play-state:running;animation-play-state:running}.move-down-leave.move-down-leave-active{-webkit-animation-name:antMoveDownOut;animation-name:antMoveDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-down-enter,.move-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-down-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-left-enter,.move-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-enter.move-left-enter-active,.move-left-appear.move-left-appear-active{-webkit-animation-name:antMoveLeftIn;animation-name:antMoveLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.move-left-leave.move-left-leave-active{-webkit-animation-name:antMoveLeftOut;animation-name:antMoveLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-left-enter,.move-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-left-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-right-enter,.move-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-enter.move-right-enter-active,.move-right-appear.move-right-appear-active{-webkit-animation-name:antMoveRightIn;animation-name:antMoveRightIn;-webkit-animation-play-state:running;animation-play-state:running}.move-right-leave.move-right-leave-active{-webkit-animation-name:antMoveRightOut;animation-name:antMoveRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-right-enter,.move-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-right-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}@-webkit-keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}[ant-click-animating='true'],[ant-click-animating-without-extra-node='true']{position:relative}html{--antd-wave-shadow-color: #1890ff;--scroll-bar: 0}[ant-click-animating-without-extra-node='true']::after,.ant-click-animating-node{position:absolute;top:0;right:0;bottom:0;left:0;display:block;border-radius:inherit;box-shadow:0 0 0 0 #1890ff;box-shadow:0 0 0 0 var(--antd-wave-shadow-color);opacity:0.2;-webkit-animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;content:'';pointer-events:none}@-webkit-keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@-webkit-keyframes fadeEffect{100%{opacity:0}}@keyframes fadeEffect{100%{opacity:0}}.slide-up-enter,.slide-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-enter.slide-up-enter-active,.slide-up-appear.slide-up-appear-active{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-up-leave.slide-up-leave-active{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-up-enter,.slide-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-up-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-down-enter,.slide-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-enter.slide-down-enter-active,.slide-down-appear.slide-down-appear-active{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-down-leave.slide-down-leave-active{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-down-enter,.slide-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-down-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-left-enter,.slide-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-enter.slide-left-enter-active,.slide-left-appear.slide-left-appear-active{-webkit-animation-name:antSlideLeftIn;animation-name:antSlideLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-left-leave.slide-left-leave-active{-webkit-animation-name:antSlideLeftOut;animation-name:antSlideLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-left-enter,.slide-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-left-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-right-enter,.slide-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-enter.slide-right-enter-active,.slide-right-appear.slide-right-appear-active{-webkit-animation-name:antSlideRightIn;animation-name:antSlideRightIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-right-leave.slide-right-leave-active{-webkit-animation-name:antSlideRightOut;animation-name:antSlideRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-right-enter,.slide-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-right-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}@-webkit-keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@-webkit-keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@-webkit-keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@-webkit-keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}@keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}.zoom-enter,.zoom-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-enter.zoom-enter-active,.zoom-appear.zoom-appear-active{-webkit-animation-name:antZoomIn;animation-name:antZoomIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-leave.zoom-leave-active{-webkit-animation-name:antZoomOut;animation-name:antZoomOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-enter,.zoom-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-enter,.zoom-big-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-enter.zoom-big-enter-active,.zoom-big-appear.zoom-big-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-leave.zoom-big-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-enter,.zoom-big-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-leave{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-enter.zoom-big-fast-enter-active,.zoom-big-fast-appear.zoom-big-fast-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-fast-leave.zoom-big-fast-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-fast-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-up-enter,.zoom-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-enter.zoom-up-enter-active,.zoom-up-appear.zoom-up-appear-active{-webkit-animation-name:antZoomUpIn;animation-name:antZoomUpIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-up-leave.zoom-up-leave-active{-webkit-animation-name:antZoomUpOut;animation-name:antZoomUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-up-enter,.zoom-up-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-up-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-down-enter,.zoom-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-enter.zoom-down-enter-active,.zoom-down-appear.zoom-down-appear-active{-webkit-animation-name:antZoomDownIn;animation-name:antZoomDownIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-down-leave.zoom-down-leave-active{-webkit-animation-name:antZoomDownOut;animation-name:antZoomDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-down-enter,.zoom-down-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-down-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-left-enter,.zoom-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-enter.zoom-left-enter-active,.zoom-left-appear.zoom-left-appear-active{-webkit-animation-name:antZoomLeftIn;animation-name:antZoomLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-left-leave.zoom-left-leave-active{-webkit-animation-name:antZoomLeftOut;animation-name:antZoomLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-left-enter,.zoom-left-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-left-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-right-enter,.zoom-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-enter.zoom-right-enter-active,.zoom-right-appear.zoom-right-appear-active{-webkit-animation-name:antZoomRightIn;animation-name:antZoomRightIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-right-leave.zoom-right-leave-active{-webkit-animation-name:antZoomRightOut;animation-name:antZoomRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-right-enter,.zoom-right-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-right-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}@-webkit-keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@-webkit-keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@-webkit-keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@-webkit-keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@-webkit-keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@-webkit-keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@-webkit-keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@-webkit-keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@-webkit-keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@-webkit-keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}@keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}.ant-motion-collapse-legacy{overflow:hidden}.ant-motion-collapse-legacy-active{transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}.ant-motion-collapse{overflow:hidden;transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}
dist/css/multicurrencyOptions/styles.css CHANGED
@@ -1,4 +1,6 @@
 
1
  .fade-enter,.fade-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-enter.fade-enter-active,.fade-appear.fade-appear-active{-webkit-animation-name:antFadeIn;animation-name:antFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.fade-leave.fade-leave-active{-webkit-animation-name:antFadeOut;animation-name:antFadeOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.fade-enter,.fade-appear{opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}.fade-leave{-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}@keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}.move-up-enter,.move-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-enter.move-up-enter-active,.move-up-appear.move-up-appear-active{-webkit-animation-name:antMoveUpIn;animation-name:antMoveUpIn;-webkit-animation-play-state:running;animation-play-state:running}.move-up-leave.move-up-leave-active{-webkit-animation-name:antMoveUpOut;animation-name:antMoveUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-up-enter,.move-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-up-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-down-enter,.move-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-enter.move-down-enter-active,.move-down-appear.move-down-appear-active{-webkit-animation-name:antMoveDownIn;animation-name:antMoveDownIn;-webkit-animation-play-state:running;animation-play-state:running}.move-down-leave.move-down-leave-active{-webkit-animation-name:antMoveDownOut;animation-name:antMoveDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-down-enter,.move-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-down-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-left-enter,.move-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-enter.move-left-enter-active,.move-left-appear.move-left-appear-active{-webkit-animation-name:antMoveLeftIn;animation-name:antMoveLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.move-left-leave.move-left-leave-active{-webkit-animation-name:antMoveLeftOut;animation-name:antMoveLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-left-enter,.move-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-left-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-right-enter,.move-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-enter.move-right-enter-active,.move-right-appear.move-right-appear-active{-webkit-animation-name:antMoveRightIn;animation-name:antMoveRightIn;-webkit-animation-play-state:running;animation-play-state:running}.move-right-leave.move-right-leave-active{-webkit-animation-name:antMoveRightOut;animation-name:antMoveRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-right-enter,.move-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-right-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}@-webkit-keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}[ant-click-animating='true'],[ant-click-animating-without-extra-node='true']{position:relative}html{--antd-wave-shadow-color: #1890ff;--scroll-bar: 0}[ant-click-animating-without-extra-node='true']::after,.ant-click-animating-node{position:absolute;top:0;right:0;bottom:0;left:0;display:block;border-radius:inherit;box-shadow:0 0 0 0 #1890ff;box-shadow:0 0 0 0 var(--antd-wave-shadow-color);opacity:0.2;-webkit-animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;content:'';pointer-events:none}@-webkit-keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@-webkit-keyframes fadeEffect{100%{opacity:0}}@keyframes fadeEffect{100%{opacity:0}}.slide-up-enter,.slide-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-enter.slide-up-enter-active,.slide-up-appear.slide-up-appear-active{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-up-leave.slide-up-leave-active{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-up-enter,.slide-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-up-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-down-enter,.slide-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-enter.slide-down-enter-active,.slide-down-appear.slide-down-appear-active{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-down-leave.slide-down-leave-active{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-down-enter,.slide-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-down-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-left-enter,.slide-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-enter.slide-left-enter-active,.slide-left-appear.slide-left-appear-active{-webkit-animation-name:antSlideLeftIn;animation-name:antSlideLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-left-leave.slide-left-leave-active{-webkit-animation-name:antSlideLeftOut;animation-name:antSlideLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-left-enter,.slide-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-left-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-right-enter,.slide-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-enter.slide-right-enter-active,.slide-right-appear.slide-right-appear-active{-webkit-animation-name:antSlideRightIn;animation-name:antSlideRightIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-right-leave.slide-right-leave-active{-webkit-animation-name:antSlideRightOut;animation-name:antSlideRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-right-enter,.slide-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-right-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}@-webkit-keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@-webkit-keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@-webkit-keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@-webkit-keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}@keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}.zoom-enter,.zoom-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-enter.zoom-enter-active,.zoom-appear.zoom-appear-active{-webkit-animation-name:antZoomIn;animation-name:antZoomIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-leave.zoom-leave-active{-webkit-animation-name:antZoomOut;animation-name:antZoomOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-enter,.zoom-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-enter,.zoom-big-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-enter.zoom-big-enter-active,.zoom-big-appear.zoom-big-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-leave.zoom-big-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-enter,.zoom-big-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-leave{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-enter.zoom-big-fast-enter-active,.zoom-big-fast-appear.zoom-big-fast-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-fast-leave.zoom-big-fast-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-fast-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-up-enter,.zoom-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-enter.zoom-up-enter-active,.zoom-up-appear.zoom-up-appear-active{-webkit-animation-name:antZoomUpIn;animation-name:antZoomUpIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-up-leave.zoom-up-leave-active{-webkit-animation-name:antZoomUpOut;animation-name:antZoomUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-up-enter,.zoom-up-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-up-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-down-enter,.zoom-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-enter.zoom-down-enter-active,.zoom-down-appear.zoom-down-appear-active{-webkit-animation-name:antZoomDownIn;animation-name:antZoomDownIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-down-leave.zoom-down-leave-active{-webkit-animation-name:antZoomDownOut;animation-name:antZoomDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-down-enter,.zoom-down-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-down-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-left-enter,.zoom-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-enter.zoom-left-enter-active,.zoom-left-appear.zoom-left-appear-active{-webkit-animation-name:antZoomLeftIn;animation-name:antZoomLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-left-leave.zoom-left-leave-active{-webkit-animation-name:antZoomLeftOut;animation-name:antZoomLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-left-enter,.zoom-left-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-left-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-right-enter,.zoom-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-enter.zoom-right-enter-active,.zoom-right-appear.zoom-right-appear-active{-webkit-animation-name:antZoomRightIn;animation-name:antZoomRightIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-right-leave.zoom-right-leave-active{-webkit-animation-name:antZoomRightOut;animation-name:antZoomRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-right-enter,.zoom-right-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-right-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}@-webkit-keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@-webkit-keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@-webkit-keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@-webkit-keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@-webkit-keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@-webkit-keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@-webkit-keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@-webkit-keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@-webkit-keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@-webkit-keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}@keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}.ant-motion-collapse-legacy{overflow:hidden}.ant-motion-collapse-legacy-active{transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}.ant-motion-collapse{overflow:hidden;transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}
2
  .ant-modal{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;top:100px;width:auto;margin:0 auto;padding-bottom:24px;pointer-events:none}.ant-modal-wrap{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;outline:0;-webkit-overflow-scrolling:touch}.ant-modal-title{margin:0;color:rgba(0,0,0,0.85);font-weight:500;font-size:16px;line-height:22px;word-wrap:break-word}.ant-modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:0;border-radius:2px;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);pointer-events:auto}.ant-modal-close{position:absolute;top:0;right:0;z-index:10;padding:0;color:rgba(0,0,0,0.45);font-weight:700;line-height:1;text-decoration:none;background:transparent;border:0;outline:0;cursor:pointer;-webkit-transition:color 0.3s;transition:color 0.3s}.ant-modal-close-x{display:block;width:56px;height:56px;font-size:16px;font-style:normal;line-height:56px;text-align:center;text-transform:none;text-rendering:auto}.ant-modal-close:focus,.ant-modal-close:hover{color:rgba(0,0,0,0.75);text-decoration:none}.ant-modal-header{padding:16px 24px;color:rgba(0,0,0,0.65);background:#fff;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-modal-body{padding:24px;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-modal-footer{padding:10px 16px;text-align:right;background:transparent;border-top:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-modal-footer button+button{margin-bottom:0;margin-left:8px}.ant-modal.zoom-enter,.ant-modal.zoom-appear{-webkit-transform:none;transform:none;opacity:0;-webkit-animation-duration:0.3s;animation-duration:0.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-modal-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;height:100%;background-color:rgba(0,0,0,0.45);filter:alpha(opacity=50)}.ant-modal-mask-hidden{display:none}.ant-modal-open{overflow:hidden}.ant-modal-centered{text-align:center}.ant-modal-centered::before{display:inline-block;width:0;height:100%;vertical-align:middle;content:''}.ant-modal-centered .ant-modal{top:0;display:inline-block;text-align:left;vertical-align:middle}@media (max-width: 767px){.ant-modal{max-width:calc(100vw - 16px);margin:8px auto}.ant-modal-centered .ant-modal{-webkit-box-flex:1;-ms-flex:1;flex:1}}.ant-modal-confirm .ant-modal-header{display:none}.ant-modal-confirm .ant-modal-close{display:none}.ant-modal-confirm .ant-modal-body{padding:32px 32px 24px}.ant-modal-confirm-body-wrapper::before{display:table;content:''}.ant-modal-confirm-body-wrapper::after{display:table;clear:both;content:''}.ant-modal-confirm-body .ant-modal-confirm-title{display:block;overflow:hidden;color:rgba(0,0,0,0.85);font-weight:500;font-size:16px;line-height:1.4}.ant-modal-confirm-body .ant-modal-confirm-content{margin-top:8px;color:rgba(0,0,0,0.65);font-size:14px}.ant-modal-confirm-body>.anticon{float:left;margin-right:16px;font-size:22px}.ant-modal-confirm-body>.anticon+.ant-modal-confirm-title+.ant-modal-confirm-content{margin-left:38px}.ant-modal-confirm .ant-modal-confirm-btns{float:right;margin-top:24px}.ant-modal-confirm .ant-modal-confirm-btns button+button{margin-bottom:0;margin-left:8px}.ant-modal-confirm-error .ant-modal-confirm-body>.anticon{color:#ff4d4f}.ant-modal-confirm-warning .ant-modal-confirm-body>.anticon,.ant-modal-confirm-confirm .ant-modal-confirm-body>.anticon{color:#faad14}.ant-modal-confirm-info .ant-modal-confirm-body>.anticon{color:#1890ff}.ant-modal-confirm-success .ant-modal-confirm-body>.anticon{color:#52c41a}.ant-modal-wrap-rtl{direction:rtl}.ant-modal-wrap-rtl .ant-modal-close{right:initial;left:0}.ant-modal-wrap-rtl .ant-modal-footer{text-align:left}.ant-modal-wrap-rtl .ant-modal-footer button+button{margin-right:8px;margin-left:0}.ant-modal-wrap-rtl.ant-modal-centered .ant-modal{text-align:right}
3
- .ant-tooltip{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:absolute;z-index:1060;display:block;max-width:250px;visibility:visible}.ant-tooltip-hidden{display:none}.ant-tooltip-placement-top,.ant-tooltip-placement-topLeft,.ant-tooltip-placement-topRight{padding-bottom:8px}.ant-tooltip-placement-right,.ant-tooltip-placement-rightTop,.ant-tooltip-placement-rightBottom{padding-left:8px}.ant-tooltip-placement-bottom,.ant-tooltip-placement-bottomLeft,.ant-tooltip-placement-bottomRight{padding-top:8px}.ant-tooltip-placement-left,.ant-tooltip-placement-leftTop,.ant-tooltip-placement-leftBottom{padding-right:8px}.ant-tooltip-inner{min-width:30px;min-height:32px;padding:6px 8px;color:#fff;text-align:left;text-decoration:none;word-wrap:break-word;background-color:rgba(0,0,0,0.75);border-radius:2px;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05)}.ant-tooltip-arrow{position:absolute;display:block;width:13.07106781px;height:13.07106781px;overflow:hidden;background:transparent;pointer-events:none}.ant-tooltip-arrow::before{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:5px;height:5px;margin:auto;background-color:rgba(0,0,0,0.75);content:'';pointer-events:auto}.ant-tooltip-placement-top .ant-tooltip-arrow,.ant-tooltip-placement-topLeft .ant-tooltip-arrow,.ant-tooltip-placement-topRight .ant-tooltip-arrow{bottom:-5.07106781px}.ant-tooltip-placement-top .ant-tooltip-arrow::before,.ant-tooltip-placement-topLeft .ant-tooltip-arrow::before,.ant-tooltip-placement-topRight .ant-tooltip-arrow::before{-webkit-box-shadow:3px 3px 7px rgba(0,0,0,0.07);box-shadow:3px 3px 7px rgba(0,0,0,0.07);-webkit-transform:translateY(-6.53553px) rotate(45deg);transform:translateY(-6.53553px) rotate(45deg)}.ant-tooltip-placement-top .ant-tooltip-arrow{left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.ant-tooltip-placement-topLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-topRight .ant-tooltip-arrow{right:13px}.ant-tooltip-placement-right .ant-tooltip-arrow,.ant-tooltip-placement-rightTop .ant-tooltip-arrow,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{left:-5.07106781px}.ant-tooltip-placement-right .ant-tooltip-arrow::before,.ant-tooltip-placement-rightTop .ant-tooltip-arrow::before,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow::before{-webkit-box-shadow:-3px 3px 7px rgba(0,0,0,0.07);box-shadow:-3px 3px 7px rgba(0,0,0,0.07);-webkit-transform:translateX(6.53553px) rotate(45deg);transform:translateX(6.53553px) rotate(45deg)}.ant-tooltip-placement-right .ant-tooltip-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.ant-tooltip-placement-rightTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-left .ant-tooltip-arrow,.ant-tooltip-placement-leftTop .ant-tooltip-arrow,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{right:-5.07106781px}.ant-tooltip-placement-left .ant-tooltip-arrow::before,.ant-tooltip-placement-leftTop .ant-tooltip-arrow::before,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow::before{-webkit-box-shadow:3px -3px 7px rgba(0,0,0,0.07);box-shadow:3px -3px 7px rgba(0,0,0,0.07);-webkit-transform:translateX(-6.53553px) rotate(45deg);transform:translateX(-6.53553px) rotate(45deg)}.ant-tooltip-placement-left .ant-tooltip-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.ant-tooltip-placement-leftTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-bottom .ant-tooltip-arrow,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{top:-5.07106781px}.ant-tooltip-placement-bottom .ant-tooltip-arrow::before,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow::before,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow::before{-webkit-box-shadow:-3px -3px 7px rgba(0,0,0,0.07);box-shadow:-3px -3px 7px rgba(0,0,0,0.07);-webkit-transform:translateY(6.53553px) rotate(45deg);transform:translateY(6.53553px) rotate(45deg)}.ant-tooltip-placement-bottom .ant-tooltip-arrow{left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{right:13px}.ant-tooltip-rtl{direction:rtl}.ant-tooltip-rtl .ant-tooltip-inner{text-align:right}
4
  .ant-select-single .ant-select-selector{display:-webkit-box;display:-ms-flexbox;display:flex}.ant-select-single .ant-select-selector .ant-select-selection-search{position:absolute;top:0;right:11px;bottom:0;left:11px}.ant-select-single .ant-select-selector .ant-select-selection-search-input{width:100%}.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{padding:0;line-height:30px;-webkit-transition:all 0.3s;transition:all 0.3s}@supports (-moz-appearance: meterbar){.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{line-height:30px}}.ant-select-single .ant-select-selector .ant-select-selection-item{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-select-single .ant-select-selector .ant-select-selection-placeholder{pointer-events:none}.ant-select-single .ant-select-selector::after,.ant-select-single .ant-select-selector .ant-select-selection-item::after,.ant-select-single .ant-select-selector .ant-select-selection-placeholder::after{display:inline-block;width:0;visibility:hidden;content:'\a0'}.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:25px}.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:18px}.ant-select-single.ant-select-open .ant-select-selection-item{opacity:0.4}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;-webkit-transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);width:100%;height:32px;padding:0 11px}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{cursor:text}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important;outline:0;-webkit-box-shadow:0 0 0 2px rgba(24,144,255,0.2);box-shadow:0 0 0 2px rgba(24,144,255,0.2)}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{color:rgba(0,0,0,0.25);background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:not-allowed}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{height:30px}.ant-select-single.ant-select-customize-input .ant-select-selector::after{display:none}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-search{position:static;width:100%}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder{position:absolute;right:0;left:0;padding:0 11px}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder::after{display:none}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{height:40px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:38px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:38px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{height:24px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selection-search{right:7px;left:7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{padding:0 7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:28px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:21px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{padding:0 11px}.ant-select-multiple .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;-webkit-transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:1px 4px}.ant-select-multiple .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-show-search.ant-select-multiple .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-multiple .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important;outline:0;-webkit-box-shadow:0 0 0 2px rgba(24,144,255,0.2);box-shadow:0 0 0 2px rgba(24,144,255,0.2)}.ant-select-disabled.ant-select-multiple .ant-select-selector{color:rgba(0,0,0,0.25);background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-multiple .ant-select-selector input{cursor:not-allowed}.ant-select-multiple .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-multiple .ant-select-selector::after{display:inline-block;width:0;margin:2px 0;line-height:24px;content:'\a0'}.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:24px}.ant-select-multiple .ant-select-selection-item{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:none;flex:none;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:24px;margin-top:2px;margin-right:4px;margin-bottom:2px;padding:0 4px 0 8px;line-height:22px;background:#f5f5f5;border:1px solid #f0f0f0;border-radius:2px;cursor:default;-webkit-transition:font-size 0.3s, line-height 0.3s, height 0.3s;transition:font-size 0.3s, line-height 0.3s, height 0.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-select-multiple .ant-select-selection-item-content{display:inline-block;margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-multiple .ant-select-selection-item-remove{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:rgba(0,0,0,0.45);font-weight:bold;font-size:12px;line-height:inherit;cursor:pointer;display:inline-block;font-size:10px}.ant-select-multiple .ant-select-selection-item-remove>*{line-height:1}.ant-select-multiple .ant-select-selection-item-remove svg{display:inline-block}.ant-select-multiple .ant-select-selection-item-remove::before{display:none}.ant-select-multiple .ant-select-selection-item-remove .ant-select-multiple .ant-select-selection-item-remove-icon{display:block}.ant-select-multiple .ant-select-selection-item-remove>.anticon{vertical-align:-0.2em}.ant-select-multiple .ant-select-selection-item-remove:hover{color:rgba(0,0,0,0.75)}.ant-select-multiple .ant-select-selection-search{position:relative;margin-left:0.5px}.ant-select-multiple .ant-select-selection-search-input,.ant-select-multiple .ant-select-selection-search-mirror{font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';line-height:1.5715;-webkit-transition:all 0.3s;transition:all 0.3s}.ant-select-multiple .ant-select-selection-search-input{width:100%;min-width:3px}.ant-select-multiple .ant-select-selection-search-mirror{position:absolute;top:0;left:0;z-index:999;white-space:nowrap;visibility:hidden}.ant-select-multiple .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:6.5px}.ant-select-multiple .ant-select-selection-placeholder{position:absolute;top:50%;right:11px;left:11px;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all 0.3s;transition:all 0.3s}.ant-select-multiple.ant-select-lg .ant-select-selector::after{line-height:32px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:30px}.ant-select-multiple.ant-select-lg .ant-select-selection-search{height:33px;line-height:33px}.ant-select-multiple.ant-select-lg .ant-select-selection-search-input,.ant-select-multiple.ant-select-lg .ant-select-selection-search-mirror{height:32px;line-height:30px}.ant-select-multiple.ant-select-sm .ant-select-selector::after{line-height:16px}.ant-select-multiple.ant-select-sm .ant-select-selection-item{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-search{height:17px;line-height:17px}.ant-select-multiple.ant-select-sm .ant-select-selection-search-input,.ant-select-multiple.ant-select-sm .ant-select-selection-search-mirror{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{left:7px}.ant-select-multiple.ant-select-sm .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:3px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:32px}.ant-select-disabled .ant-select-selection-item-remove{display:none}.ant-select{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;display:inline-block;cursor:pointer}.ant-select:not(.ant-select-disabled):hover .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important}.ant-select-selection-item{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media all and (-ms-high-contrast: none){.ant-select-selection-item *::-ms-backdrop,.ant-select-selection-item{-ms-flex:auto;flex:auto}}.ant-select-selection-placeholder{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;opacity:0.4}@media all and (-ms-high-contrast: none){.ant-select-selection-placeholder *::-ms-backdrop,.ant-select-selection-placeholder{-ms-flex:auto;flex:auto}}.ant-select-arrow{display:inline-block;color:inherit;font-style:normal;line-height:0;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:53%;right:11px;width:12px;height:12px;margin-top:-6px;color:rgba(0,0,0,0.25);font-size:12px;line-height:1;text-align:center;pointer-events:none}.ant-select-arrow>*{line-height:1}.ant-select-arrow svg{display:inline-block}.ant-select-arrow::before{display:none}.ant-select-arrow .ant-select-arrow-icon{display:block}.ant-select-arrow .anticon{vertical-align:top;-webkit-transition:-webkit-transform 0.3s;transition:-webkit-transform 0.3s;transition:transform 0.3s;transition:transform 0.3s, -webkit-transform 0.3s}.ant-select-arrow .anticon>svg{vertical-align:top}.ant-select-arrow .anticon:not(.anticon-down){pointer-events:auto}.ant-select-clear{position:absolute;top:50%;right:11px;z-index:1;display:inline-block;width:12px;height:12px;margin-top:-6px;color:rgba(0,0,0,0.25);font-size:12px;font-style:normal;line-height:1;text-align:center;text-transform:none;background:#fff;cursor:pointer;opacity:0;-webkit-transition:color 0.3s ease, opacity 0.15s ease;transition:color 0.3s ease, opacity 0.15s ease;text-rendering:auto}.ant-select-clear::before{display:block}.ant-select-clear:hover{color:rgba(0,0,0,0.45)}.ant-select:hover .ant-select-clear{opacity:1}.ant-select-dropdown{margin:0;padding:0;color:rgba(0,0,0,0.65);font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:absolute;top:-9999px;left:-9999px;z-index:1050;-webkit-box-sizing:border-box;box-sizing:border-box;padding:4px 0;overflow:hidden;font-size:14px;font-variant:initial;background-color:#fff;border-radius:2px;outline:none;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05)}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-bottomLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-topLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-select-dropdown-hidden{display:none}.ant-select-item-empty{position:relative;display:block;min-height:32px;padding:5px 12px;color:rgba(0,0,0,0.65);font-weight:normal;font-size:14px;line-height:22px}.ant-select-item{position:relative;display:block;min-height:32px;padding:5px 12px;color:rgba(0,0,0,0.65);font-weight:normal;font-size:14px;line-height:22px;cursor:pointer;-webkit-transition:background 0.3s ease;transition:background 0.3s ease}.ant-select-item-group{color:rgba(0,0,0,0.45);font-size:12px;cursor:default}.ant-select-item-option{display:-webkit-box;display:-ms-flexbox;display:flex}.ant-select-item-option-content{-webkit-box-flex:1;-ms-flex:auto;flex:auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-item-option-state{-webkit-box-flex:0;-ms-flex:none;flex:none}.ant-select-item-option-active:not(.ant-select-item-option-disabled){background-color:#f5f5f5}.ant-select-item-option-selected:not(.ant-select-item-option-disabled){color:rgba(0,0,0,0.65);font-weight:600;background-color:#e6f7ff}.ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state{color:#1890ff}.ant-select-item-option-disabled{color:rgba(0,0,0,0.25);cursor:not-allowed}.ant-select-item-option-grouped{padding-left:24px}.ant-select-lg{font-size:16px}.ant-select-borderless .ant-select-selector{background-color:transparent !important;border-color:transparent !important;-webkit-box-shadow:none !important;box-shadow:none !important}.ant-select-rtl{direction:rtl}.ant-select-rtl .ant-select-arrow{right:initial;left:11px}.ant-select-rtl .ant-select-clear{right:initial;left:11px}.ant-select-dropdown-rtl{direction:rtl}.ant-select-dropdown-rtl .ant-select-item-option-grouped{padding-right:24px;padding-left:12px}.ant-select-rtl.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:4px;padding-left:24px}.ant-select-rtl.ant-select-multiple .ant-select-selection-item{margin-right:0;margin-left:4px;padding:0 8px 0 4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-item-content{margin-right:0;margin-left:4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-search{margin-right:0.5px;margin-left:4px}.ant-select-rtl.ant-select-multiple .ant-select-selection-search-mirror{right:0;left:auto}.ant-select-rtl.ant-select-multiple .ant-select-selection-placeholder{right:11px;left:auto}.ant-select-rtl.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{right:7px}.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-placeholder{right:0;left:9px;text-align:right}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:11px;left:25px}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:18px}.ant-select-rtl.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{padding:0 11px}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:0}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:21px}
 
 
1
+ #wcml-by-language-tooltip{text-align:center}#wcml-by-language-tooltip a{color:#ffffff}
2
  .fade-enter,.fade-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.fade-enter.fade-enter-active,.fade-appear.fade-appear-active{-webkit-animation-name:antFadeIn;animation-name:antFadeIn;-webkit-animation-play-state:running;animation-play-state:running}.fade-leave.fade-leave-active{-webkit-animation-name:antFadeOut;animation-name:antFadeOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.fade-enter,.fade-appear{opacity:0;-webkit-animation-timing-function:linear;animation-timing-function:linear}.fade-leave{-webkit-animation-timing-function:linear;animation-timing-function:linear}@-webkit-keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@keyframes antFadeIn{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}@keyframes antFadeOut{0%{opacity:1}100%{opacity:0}}.move-up-enter,.move-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-up-enter.move-up-enter-active,.move-up-appear.move-up-appear-active{-webkit-animation-name:antMoveUpIn;animation-name:antMoveUpIn;-webkit-animation-play-state:running;animation-play-state:running}.move-up-leave.move-up-leave-active{-webkit-animation-name:antMoveUpOut;animation-name:antMoveUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-up-enter,.move-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-up-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-down-enter,.move-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-down-enter.move-down-enter-active,.move-down-appear.move-down-appear-active{-webkit-animation-name:antMoveDownIn;animation-name:antMoveDownIn;-webkit-animation-play-state:running;animation-play-state:running}.move-down-leave.move-down-leave-active{-webkit-animation-name:antMoveDownOut;animation-name:antMoveDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-down-enter,.move-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-down-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-left-enter,.move-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-left-enter.move-left-enter-active,.move-left-appear.move-left-appear-active{-webkit-animation-name:antMoveLeftIn;animation-name:antMoveLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.move-left-leave.move-left-leave-active{-webkit-animation-name:antMoveLeftOut;animation-name:antMoveLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-left-enter,.move-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-left-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}.move-right-enter,.move-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.move-right-enter.move-right-enter-active,.move-right-appear.move-right-appear-active{-webkit-animation-name:antMoveRightIn;animation-name:antMoveRightIn;-webkit-animation-play-state:running;animation-play-state:running}.move-right-leave.move-right-leave-active{-webkit-animation-name:antMoveRightOut;animation-name:antMoveRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.move-right-enter,.move-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.move-right-leave{-webkit-animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34);animation-timing-function:cubic-bezier(0.6, 0.04, 0.98, 0.34)}@-webkit-keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveDownIn{0%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveDownOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveLeftIn{0%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveLeftOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveRightIn{0%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveRightOut{0%{-webkit-transform:translateX(0%);transform:translateX(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateX(100%);transform:translateX(100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@keyframes antMoveUpIn{0%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}100%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}}@-webkit-keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@keyframes antMoveUpOut{0%{-webkit-transform:translateY(0%);transform:translateY(0%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:1}100%{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transform-origin:0 0;transform-origin:0 0;opacity:0}}@-webkit-keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loadingCircle{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}[ant-click-animating='true'],[ant-click-animating-without-extra-node='true']{position:relative}html{--antd-wave-shadow-color: #1890ff;--scroll-bar: 0}[ant-click-animating-without-extra-node='true']::after,.ant-click-animating-node{position:absolute;top:0;right:0;bottom:0;left:0;display:block;border-radius:inherit;box-shadow:0 0 0 0 #1890ff;box-shadow:0 0 0 0 var(--antd-wave-shadow-color);opacity:0.2;-webkit-animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);animation:fadeEffect 2s cubic-bezier(0.08, 0.82, 0.17, 1),waveEffect 0.4s cubic-bezier(0.08, 0.82, 0.17, 1);-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;content:'';pointer-events:none}@-webkit-keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@keyframes waveEffect{100%{box-shadow:0 0 0 #1890ff;box-shadow:0 0 0 6px var(--antd-wave-shadow-color)}}@-webkit-keyframes fadeEffect{100%{opacity:0}}@keyframes fadeEffect{100%{opacity:0}}.slide-up-enter,.slide-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-up-enter.slide-up-enter-active,.slide-up-appear.slide-up-appear-active{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-up-leave.slide-up-leave-active{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-up-enter,.slide-up-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-up-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-down-enter,.slide-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-down-enter.slide-down-enter-active,.slide-down-appear.slide-down-appear-active{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-down-leave.slide-down-leave-active{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-down-enter,.slide-down-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-down-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-left-enter,.slide-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-left-enter.slide-left-enter-active,.slide-left-appear.slide-left-appear-active{-webkit-animation-name:antSlideLeftIn;animation-name:antSlideLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-left-leave.slide-left-leave-active{-webkit-animation-name:antSlideLeftOut;animation-name:antSlideLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-left-enter,.slide-left-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-left-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}.slide-right-enter,.slide-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.slide-right-enter.slide-right-enter-active,.slide-right-appear.slide-right-appear-active{-webkit-animation-name:antSlideRightIn;animation-name:antSlideRightIn;-webkit-animation-play-state:running;animation-play-state:running}.slide-right-leave.slide-right-leave-active{-webkit-animation-name:antSlideRightOut;animation-name:antSlideRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.slide-right-enter,.slide-right-appear{opacity:0;-webkit-animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1);animation-timing-function:cubic-bezier(0.23, 1, 0.32, 1)}.slide-right-leave{-webkit-animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06);animation-timing-function:cubic-bezier(0.755, 0.05, 0.855, 0.06)}@-webkit-keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideUpIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideUpOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@keyframes antSlideDownIn{0%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}100%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}}@-webkit-keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@keyframes antSlideDownOut{0%{-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:1}100%{-webkit-transform:scaleY(0.8);transform:scaleY(0.8);-webkit-transform-origin:100% 100%;transform-origin:100% 100%;opacity:0}}@-webkit-keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@keyframes antSlideLeftIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}}@-webkit-keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@keyframes antSlideLeftOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:0% 0%;transform-origin:0% 0%;opacity:0}}@-webkit-keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@keyframes antSlideRightIn{0%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}100%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}}@-webkit-keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}@keyframes antSlideRightOut{0%{-webkit-transform:scaleX(1);transform:scaleX(1);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:1}100%{-webkit-transform:scaleX(0.8);transform:scaleX(0.8);-webkit-transform-origin:100% 0%;transform-origin:100% 0%;opacity:0}}.zoom-enter,.zoom-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-enter.zoom-enter-active,.zoom-appear.zoom-appear-active{-webkit-animation-name:antZoomIn;animation-name:antZoomIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-leave.zoom-leave-active{-webkit-animation-name:antZoomOut;animation-name:antZoomOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-enter,.zoom-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-enter,.zoom-big-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-enter.zoom-big-enter-active,.zoom-big-appear.zoom-big-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-leave.zoom-big-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-enter,.zoom-big-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-leave{-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-big-fast-enter.zoom-big-fast-enter-active,.zoom-big-fast-appear.zoom-big-fast-appear-active{-webkit-animation-name:antZoomBigIn;animation-name:antZoomBigIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-big-fast-leave.zoom-big-fast-leave-active{-webkit-animation-name:antZoomBigOut;animation-name:antZoomBigOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-big-fast-enter,.zoom-big-fast-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-big-fast-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-up-enter,.zoom-up-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-up-enter.zoom-up-enter-active,.zoom-up-appear.zoom-up-appear-active{-webkit-animation-name:antZoomUpIn;animation-name:antZoomUpIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-up-leave.zoom-up-leave-active{-webkit-animation-name:antZoomUpOut;animation-name:antZoomUpOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-up-enter,.zoom-up-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-up-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-down-enter,.zoom-down-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-down-enter.zoom-down-enter-active,.zoom-down-appear.zoom-down-appear-active{-webkit-animation-name:antZoomDownIn;animation-name:antZoomDownIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-down-leave.zoom-down-leave-active{-webkit-animation-name:antZoomDownOut;animation-name:antZoomDownOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-down-enter,.zoom-down-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-down-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-left-enter,.zoom-left-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-left-enter.zoom-left-enter-active,.zoom-left-appear.zoom-left-appear-active{-webkit-animation-name:antZoomLeftIn;animation-name:antZoomLeftIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-left-leave.zoom-left-leave-active{-webkit-animation-name:antZoomLeftOut;animation-name:antZoomLeftOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-left-enter,.zoom-left-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-left-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}.zoom-right-enter,.zoom-right-appear{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-leave{-webkit-animation-duration:0.2s;animation-duration:0.2s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-play-state:paused;animation-play-state:paused}.zoom-right-enter.zoom-right-enter-active,.zoom-right-appear.zoom-right-appear-active{-webkit-animation-name:antZoomRightIn;animation-name:antZoomRightIn;-webkit-animation-play-state:running;animation-play-state:running}.zoom-right-leave.zoom-right-leave-active{-webkit-animation-name:antZoomRightOut;animation-name:antZoomRightOut;-webkit-animation-play-state:running;animation-play-state:running;pointer-events:none}.zoom-right-enter,.zoom-right-appear{-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1);animation-timing-function:cubic-bezier(0.08, 0.82, 0.17, 1)}.zoom-right-leave{-webkit-animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86);animation-timing-function:cubic-bezier(0.78, 0.14, 0.15, 0.86)}@-webkit-keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomIn{0%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@keyframes antZoomOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.2);transform:scale(0.2);opacity:0}}@-webkit-keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@keyframes antZoomBigIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);opacity:1}}@-webkit-keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@keyframes antZoomBigOut{0%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.8);transform:scale(0.8);opacity:0}}@-webkit-keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@keyframes antZoomUpIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}}@-webkit-keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@keyframes antZoomUpOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 0%;transform-origin:50% 0%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 0%;transform-origin:50% 0%;opacity:0}}@-webkit-keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@keyframes antZoomLeftIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}}@-webkit-keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@keyframes antZoomLeftOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:0% 50%;transform-origin:0% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:0% 50%;transform-origin:0% 50%;opacity:0}}@-webkit-keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@keyframes antZoomRightIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}}@-webkit-keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@keyframes antZoomRightOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:100% 50%;transform-origin:100% 50%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:100% 50%;transform-origin:100% 50%;opacity:0}}@-webkit-keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@keyframes antZoomDownIn{0%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}100%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}}@-webkit-keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}@keyframes antZoomDownOut{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 100%;transform-origin:50% 100%}100%{-webkit-transform:scale(0.8);transform:scale(0.8);-webkit-transform-origin:50% 100%;transform-origin:50% 100%;opacity:0}}.ant-motion-collapse-legacy{overflow:hidden}.ant-motion-collapse-legacy-active{transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}.ant-motion-collapse{overflow:hidden;transition:height 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) !important}
3
  .ant-modal{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;top:100px;width:auto;margin:0 auto;padding-bottom:24px;pointer-events:none}.ant-modal-wrap{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;overflow:auto;outline:0;-webkit-overflow-scrolling:touch}.ant-modal-title{margin:0;color:rgba(0,0,0,0.85);font-weight:500;font-size:16px;line-height:22px;word-wrap:break-word}.ant-modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:0;border-radius:2px;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);pointer-events:auto}.ant-modal-close{position:absolute;top:0;right:0;z-index:10;padding:0;color:rgba(0,0,0,0.45);font-weight:700;line-height:1;text-decoration:none;background:transparent;border:0;outline:0;cursor:pointer;-webkit-transition:color 0.3s;transition:color 0.3s}.ant-modal-close-x{display:block;width:56px;height:56px;font-size:16px;font-style:normal;line-height:56px;text-align:center;text-transform:none;text-rendering:auto}.ant-modal-close:focus,.ant-modal-close:hover{color:rgba(0,0,0,0.75);text-decoration:none}.ant-modal-header{padding:16px 24px;color:rgba(0,0,0,0.65);background:#fff;border-bottom:1px solid #f0f0f0;border-radius:2px 2px 0 0}.ant-modal-body{padding:24px;font-size:14px;line-height:1.5715;word-wrap:break-word}.ant-modal-footer{padding:10px 16px;text-align:right;background:transparent;border-top:1px solid #f0f0f0;border-radius:0 0 2px 2px}.ant-modal-footer button+button{margin-bottom:0;margin-left:8px}.ant-modal.zoom-enter,.ant-modal.zoom-appear{-webkit-transform:none;transform:none;opacity:0;-webkit-animation-duration:0.3s;animation-duration:0.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-modal-mask{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;height:100%;background-color:rgba(0,0,0,0.45);filter:alpha(opacity=50)}.ant-modal-mask-hidden{display:none}.ant-modal-open{overflow:hidden}.ant-modal-centered{text-align:center}.ant-modal-centered::before{display:inline-block;width:0;height:100%;vertical-align:middle;content:''}.ant-modal-centered .ant-modal{top:0;display:inline-block;text-align:left;vertical-align:middle}@media (max-width: 767px){.ant-modal{max-width:calc(100vw - 16px);margin:8px auto}.ant-modal-centered .ant-modal{-webkit-box-flex:1;-ms-flex:1;flex:1}}.ant-modal-confirm .ant-modal-header{display:none}.ant-modal-confirm .ant-modal-close{display:none}.ant-modal-confirm .ant-modal-body{padding:32px 32px 24px}.ant-modal-confirm-body-wrapper::before{display:table;content:''}.ant-modal-confirm-body-wrapper::after{display:table;clear:both;content:''}.ant-modal-confirm-body .ant-modal-confirm-title{display:block;overflow:hidden;color:rgba(0,0,0,0.85);font-weight:500;font-size:16px;line-height:1.4}.ant-modal-confirm-body .ant-modal-confirm-content{margin-top:8px;color:rgba(0,0,0,0.65);font-size:14px}.ant-modal-confirm-body>.anticon{float:left;margin-right:16px;font-size:22px}.ant-modal-confirm-body>.anticon+.ant-modal-confirm-title+.ant-modal-confirm-content{margin-left:38px}.ant-modal-confirm .ant-modal-confirm-btns{float:right;margin-top:24px}.ant-modal-confirm .ant-modal-confirm-btns button+button{margin-bottom:0;margin-left:8px}.ant-modal-confirm-error .ant-modal-confirm-body>.anticon{color:#ff4d4f}.ant-modal-confirm-warning .ant-modal-confirm-body>.anticon,.ant-modal-confirm-confirm .ant-modal-confirm-body>.anticon{color:#faad14}.ant-modal-confirm-info .ant-modal-confirm-body>.anticon{color:#1890ff}.ant-modal-confirm-success .ant-modal-confirm-body>.anticon{color:#52c41a}.ant-modal-wrap-rtl{direction:rtl}.ant-modal-wrap-rtl .ant-modal-close{right:initial;left:0}.ant-modal-wrap-rtl .ant-modal-footer{text-align:left}.ant-modal-wrap-rtl .ant-modal-footer button+button{margin-right:8px;margin-left:0}.ant-modal-wrap-rtl.ant-modal-centered .ant-modal{text-align:right}
 
4
  .ant-select-single .ant-select-selector{display:-webkit-box;display:-ms-flexbox;display:flex}.ant-select-single .ant-select-selector .ant-select-selection-search{position:absolute;top:0;right:11px;bottom:0;left:11px}.ant-select-single .ant-select-selector .ant-select-selection-search-input{width:100%}.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{padding:0;line-height:30px;-webkit-transition:all 0.3s;transition:all 0.3s}@supports (-moz-appearance: meterbar){.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-single .ant-select-selector .ant-select-selection-placeholder{line-height:30px}}.ant-select-single .ant-select-selector .ant-select-selection-item{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-select-single .ant-select-selector .ant-select-selection-placeholder{pointer-events:none}.ant-select-single .ant-select-selector::after,.ant-select-single .ant-select-selector .ant-select-selection-item::after,.ant-select-single .ant-select-selector .ant-select-selection-placeholder::after{display:inline-block;width:0;visibility:hidden;content:'\a0'}.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:25px}.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:18px}.ant-select-single.ant-select-open .ant-select-selection-item{opacity:0.4}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;-webkit-transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);width:100%;height:32px;padding:0 11px}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{cursor:text}.ant-select-show-search.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important;outline:0;-webkit-box-shadow:0 0 0 2px rgba(24,144,255,0.2);box-shadow:0 0 0 2px rgba(24,144,255,0.2)}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{color:rgba(0,0,0,0.25);background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector input{cursor:not-allowed}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-single:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-search-input{height:30px}.ant-select-single.ant-select-customize-input .ant-select-selector::after{display:none}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-search{position:static;width:100%}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder{position:absolute;right:0;left:0;padding:0 11px}.ant-select-single.ant-select-customize-input .ant-select-selector .ant-select-selection-placeholder::after{display:none}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{height:40px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:38px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:38px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{height:24px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector .ant-select-selection-placeholder{line-height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input):not(.ant-select-customize-input) .ant-select-selection-search-input{height:22px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selection-search{right:7px;left:7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input) .ant-select-selector{padding:0 7px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:28px}.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:21px}.ant-select-single.ant-select-lg:not(.ant-select-customize-input) .ant-select-selector{padding:0 11px}.ant-select-multiple .ant-select-selector{position:relative;background-color:#fff;border:1px solid #d9d9d9;border-radius:2px;-webkit-transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);transition:all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:1px 4px}.ant-select-multiple .ant-select-selector input{cursor:pointer}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-show-search.ant-select-multiple .ant-select-selector input{cursor:auto}.ant-select-focused.ant-select-multiple .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important;outline:0;-webkit-box-shadow:0 0 0 2px rgba(24,144,255,0.2);box-shadow:0 0 0 2px rgba(24,144,255,0.2)}.ant-select-disabled.ant-select-multiple .ant-select-selector{color:rgba(0,0,0,0.25);background:#f5f5f5;cursor:not-allowed}.ant-select-disabled.ant-select-multiple .ant-select-selector input{cursor:not-allowed}.ant-select-multiple .ant-select-selector .ant-select-selection-search-input{background:transparent;border:none;outline:none}.ant-select-show-search.ant-select-multiple .ant-select-selector{cursor:text}.ant-select-multiple .ant-select-selector::after{display:inline-block;width:0;margin:2px 0;line-height:24px;content:'\a0'}.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:24px}.ant-select-multiple .ant-select-selection-item{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:none;flex:none;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:24px;margin-top:2px;margin-right:4px;margin-bottom:2px;padding:0 4px 0 8px;line-height:22px;background:#f5f5f5;border:1px solid #f0f0f0;border-radius:2px;cursor:default;-webkit-transition:font-size 0.3s, line-height 0.3s, height 0.3s;transition:font-size 0.3s, line-height 0.3s, height 0.3s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ant-select-multiple .ant-select-selection-item-content{display:inline-block;margin-right:4px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-multiple .ant-select-selection-item-remove{color:inherit;font-style:normal;line-height:0;text-align:center;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:rgba(0,0,0,0.45);font-weight:bold;font-size:12px;line-height:inherit;cursor:pointer;display:inline-block;font-size:10px}.ant-select-multiple .ant-select-selection-item-remove>*{line-height:1}.ant-select-multiple .ant-select-selection-item-remove svg{display:inline-block}.ant-select-multiple .ant-select-selection-item-remove::before{display:none}.ant-select-multiple .ant-select-selection-item-remove .ant-select-multiple .ant-select-selection-item-remove-icon{display:block}.ant-select-multiple .ant-select-selection-item-remove>.anticon{vertical-align:-0.2em}.ant-select-multiple .ant-select-selection-item-remove:hover{color:rgba(0,0,0,0.75)}.ant-select-multiple .ant-select-selection-search{position:relative;margin-left:0.5px}.ant-select-multiple .ant-select-selection-search-input,.ant-select-multiple .ant-select-selection-search-mirror{font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';line-height:1.5715;-webkit-transition:all 0.3s;transition:all 0.3s}.ant-select-multiple .ant-select-selection-search-input{width:100%;min-width:3px}.ant-select-multiple .ant-select-selection-search-mirror{position:absolute;top:0;left:0;z-index:999;white-space:nowrap;visibility:hidden}.ant-select-multiple .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:6.5px}.ant-select-multiple .ant-select-selection-placeholder{position:absolute;top:50%;right:11px;left:11px;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition:all 0.3s;transition:all 0.3s}.ant-select-multiple.ant-select-lg .ant-select-selector::after{line-height:32px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:30px}.ant-select-multiple.ant-select-lg .ant-select-selection-search{height:33px;line-height:33px}.ant-select-multiple.ant-select-lg .ant-select-selection-search-input,.ant-select-multiple.ant-select-lg .ant-select-selection-search-mirror{height:32px;line-height:30px}.ant-select-multiple.ant-select-sm .ant-select-selector::after{line-height:16px}.ant-select-multiple.ant-select-sm .ant-select-selection-item{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-search{height:17px;line-height:17px}.ant-select-multiple.ant-select-sm .ant-select-selection-search-input,.ant-select-multiple.ant-select-sm .ant-select-selection-search-mirror{height:16px;line-height:14px}.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{left:7px}.ant-select-multiple.ant-select-sm .ant-select-selection-search:first-child .ant-select-selection-search-input{margin-left:3px}.ant-select-multiple.ant-select-lg .ant-select-selection-item{height:32px;line-height:32px}.ant-select-disabled .ant-select-selection-item-remove{display:none}.ant-select{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;display:inline-block;cursor:pointer}.ant-select:not(.ant-select-disabled):hover .ant-select-selector{border-color:#40a9ff;border-right-width:1px !important}.ant-select-selection-item{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}@media all and (-ms-high-contrast: none){.ant-select-selection-item *::-ms-backdrop,.ant-select-selection-item{-ms-flex:auto;flex:auto}}.ant-select-selection-placeholder{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;opacity:0.4}@media all and (-ms-high-contrast: none){.ant-select-selection-placeholder *::-ms-backdrop,.ant-select-selection-placeholder{-ms-flex:auto;flex:auto}}.ant-select-arrow{display:inline-block;color:inherit;font-style:normal;line-height:0;text-transform:none;vertical-align:-0.125em;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:53%;right:11px;width:12px;height:12px;margin-top:-6px;color:rgba(0,0,0,0.25);font-size:12px;line-height:1;text-align:center;pointer-events:none}.ant-select-arrow>*{line-height:1}.ant-select-arrow svg{display:inline-block}.ant-select-arrow::before{display:none}.ant-select-arrow .ant-select-arrow-icon{display:block}.ant-select-arrow .anticon{vertical-align:top;-webkit-transition:-webkit-transform 0.3s;transition:-webkit-transform 0.3s;transition:transform 0.3s;transition:transform 0.3s, -webkit-transform 0.3s}.ant-select-arrow .anticon>svg{vertical-align:top}.ant-select-arrow .anticon:not(.anticon-down){pointer-events:auto}.ant-select-clear{position:absolute;top:50%;right:11px;z-index:1;display:inline-block;width:12px;height:12px;margin-top:-6px;color:rgba(0,0,0,0.25);font-size:12px;font-style:normal;line-height:1;text-align:center;text-transform:none;background:#fff;cursor:pointer;opacity:0;-webkit-transition:color 0.3s ease, opacity 0.15s ease;transition:color 0.3s ease, opacity 0.15s ease;text-rendering:auto}.ant-select-clear::before{display:block}.ant-select-clear:hover{color:rgba(0,0,0,0.45)}.ant-select:hover .ant-select-clear{opacity:1}.ant-select-dropdown{margin:0;padding:0;color:rgba(0,0,0,0.65);font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:absolute;top:-9999px;left:-9999px;z-index:1050;-webkit-box-sizing:border-box;box-sizing:border-box;padding:4px 0;overflow:hidden;font-size:14px;font-variant:initial;background-color:#fff;border-radius:2px;outline:none;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05)}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-bottomLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpIn;animation-name:antSlideUpIn}.ant-select-dropdown.slide-up-enter.slide-up-enter-active.ant-select-dropdown-placement-topLeft,.ant-select-dropdown.slide-up-appear.slide-up-appear-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownIn;animation-name:antSlideDownIn}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-bottomLeft{-webkit-animation-name:antSlideUpOut;animation-name:antSlideUpOut}.ant-select-dropdown.slide-up-leave.slide-up-leave-active.ant-select-dropdown-placement-topLeft{-webkit-animation-name:antSlideDownOut;animation-name:antSlideDownOut}.ant-select-dropdown-hidden{display:none}.ant-select-item-empty{position:relative;display:block;min-height:32px;padding:5px 12px;color:rgba(0,0,0,0.65);font-weight:normal;font-size:14px;line-height:22px}.ant-select-item{position:relative;display:block;min-height:32px;padding:5px 12px;color:rgba(0,0,0,0.65);font-weight:normal;font-size:14px;line-height:22px;cursor:pointer;-webkit-transition:background 0.3s ease;transition:background 0.3s ease}.ant-select-item-group{color:rgba(0,0,0,0.45);font-size:12px;cursor:default}.ant-select-item-option{display:-webkit-box;display:-ms-flexbox;display:flex}.ant-select-item-option-content{-webkit-box-flex:1;-ms-flex:auto;flex:auto;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.ant-select-item-option-state{-webkit-box-flex:0;-ms-flex:none;flex:none}.ant-select-item-option-active:not(.ant-select-item-option-disabled){background-color:#f5f5f5}.ant-select-item-option-selected:not(.ant-select-item-option-disabled){color:rgba(0,0,0,0.65);font-weight:600;background-color:#e6f7ff}.ant-select-item-option-selected:not(.ant-select-item-option-disabled) .ant-select-item-option-state{color:#1890ff}.ant-select-item-option-disabled{color:rgba(0,0,0,0.25);cursor:not-allowed}.ant-select-item-option-grouped{padding-left:24px}.ant-select-lg{font-size:16px}.ant-select-borderless .ant-select-selector{background-color:transparent !important;border-color:transparent !important;-webkit-box-shadow:none !important;box-shadow:none !important}.ant-select-rtl{direction:rtl}.ant-select-rtl .ant-select-arrow{right:initial;left:11px}.ant-select-rtl .ant-select-clear{right:initial;left:11px}.ant-select-dropdown-rtl{direction:rtl}.ant-select-dropdown-rtl .ant-select-item-option-grouped{padding-right:24px;padding-left:12px}.ant-select-rtl.ant-select-multiple.ant-select-allow-clear .ant-select-selector{padding-right:4px;padding-left:24px}.ant-select-rtl.ant-select-multiple .ant-select-selection-item{margin-right:0;margin-left:4px;padding:0 8px 0 4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-item-content{margin-right:0;margin-left:4px;text-align:right}.ant-select-rtl.ant-select-multiple .ant-select-selection-search{margin-right:0.5px;margin-left:4px}.ant-select-rtl.ant-select-multiple .ant-select-selection-search-mirror{right:0;left:auto}.ant-select-rtl.ant-select-multiple .ant-select-selection-placeholder{right:11px;left:auto}.ant-select-rtl.ant-select-multiple.ant-select-sm .ant-select-selection-placeholder{right:7px}.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-item,.ant-select-rtl.ant-select-single .ant-select-selector .ant-select-selection-placeholder{right:0;left:9px;text-align:right}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-search{right:11px;left:25px}.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:18px}.ant-select-rtl.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{padding:0 11px}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-search{right:0}.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-item,.ant-select-rtl.ant-select-single.ant-select-sm:not(.ant-select-customize-input).ant-select-show-arrow .ant-select-selection-placeholder{padding-right:0;padding-left:21px}
5
+ .ant-tooltip{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:absolute;z-index:1060;display:block;max-width:250px;visibility:visible}.ant-tooltip-hidden{display:none}.ant-tooltip-placement-top,.ant-tooltip-placement-topLeft,.ant-tooltip-placement-topRight{padding-bottom:8px}.ant-tooltip-placement-right,.ant-tooltip-placement-rightTop,.ant-tooltip-placement-rightBottom{padding-left:8px}.ant-tooltip-placement-bottom,.ant-tooltip-placement-bottomLeft,.ant-tooltip-placement-bottomRight{padding-top:8px}.ant-tooltip-placement-left,.ant-tooltip-placement-leftTop,.ant-tooltip-placement-leftBottom{padding-right:8px}.ant-tooltip-inner{min-width:30px;min-height:32px;padding:6px 8px;color:#fff;text-align:left;text-decoration:none;word-wrap:break-word;background-color:rgba(0,0,0,0.75);border-radius:2px;-webkit-box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05);box-shadow:0 3px 6px -4px rgba(0,0,0,0.12),0 6px 16px 0 rgba(0,0,0,0.08),0 9px 28px 8px rgba(0,0,0,0.05)}.ant-tooltip-arrow{position:absolute;display:block;width:13.07106781px;height:13.07106781px;overflow:hidden;background:transparent;pointer-events:none}.ant-tooltip-arrow::before{position:absolute;top:0;right:0;bottom:0;left:0;display:block;width:5px;height:5px;margin:auto;background-color:rgba(0,0,0,0.75);content:'';pointer-events:auto}.ant-tooltip-placement-top .ant-tooltip-arrow,.ant-tooltip-placement-topLeft .ant-tooltip-arrow,.ant-tooltip-placement-topRight .ant-tooltip-arrow{bottom:-5.07106781px}.ant-tooltip-placement-top .ant-tooltip-arrow::before,.ant-tooltip-placement-topLeft .ant-tooltip-arrow::before,.ant-tooltip-placement-topRight .ant-tooltip-arrow::before{-webkit-box-shadow:3px 3px 7px rgba(0,0,0,0.07);box-shadow:3px 3px 7px rgba(0,0,0,0.07);-webkit-transform:translateY(-6.53553px) rotate(45deg);transform:translateY(-6.53553px) rotate(45deg)}.ant-tooltip-placement-top .ant-tooltip-arrow{left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.ant-tooltip-placement-topLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-topRight .ant-tooltip-arrow{right:13px}.ant-tooltip-placement-right .ant-tooltip-arrow,.ant-tooltip-placement-rightTop .ant-tooltip-arrow,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{left:-5.07106781px}.ant-tooltip-placement-right .ant-tooltip-arrow::before,.ant-tooltip-placement-rightTop .ant-tooltip-arrow::before,.ant-tooltip-placement-rightBottom .ant-tooltip-arrow::before{-webkit-box-shadow:-3px 3px 7px rgba(0,0,0,0.07);box-shadow:-3px 3px 7px rgba(0,0,0,0.07);-webkit-transform:translateX(6.53553px) rotate(45deg);transform:translateX(6.53553px) rotate(45deg)}.ant-tooltip-placement-right .ant-tooltip-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.ant-tooltip-placement-rightTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-rightBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-left .ant-tooltip-arrow,.ant-tooltip-placement-leftTop .ant-tooltip-arrow,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{right:-5.07106781px}.ant-tooltip-placement-left .ant-tooltip-arrow::before,.ant-tooltip-placement-leftTop .ant-tooltip-arrow::before,.ant-tooltip-placement-leftBottom .ant-tooltip-arrow::before{-webkit-box-shadow:3px -3px 7px rgba(0,0,0,0.07);box-shadow:3px -3px 7px rgba(0,0,0,0.07);-webkit-transform:translateX(-6.53553px) rotate(45deg);transform:translateX(-6.53553px) rotate(45deg)}.ant-tooltip-placement-left .ant-tooltip-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.ant-tooltip-placement-leftTop .ant-tooltip-arrow{top:5px}.ant-tooltip-placement-leftBottom .ant-tooltip-arrow{bottom:5px}.ant-tooltip-placement-bottom .ant-tooltip-arrow,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{top:-5.07106781px}.ant-tooltip-placement-bottom .ant-tooltip-arrow::before,.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow::before,.ant-tooltip-placement-bottomRight .ant-tooltip-arrow::before{-webkit-box-shadow:-3px -3px 7px rgba(0,0,0,0.07);box-shadow:-3px -3px 7px rgba(0,0,0,0.07);-webkit-transform:translateY(6.53553px) rotate(45deg);transform:translateY(6.53553px) rotate(45deg)}.ant-tooltip-placement-bottom .ant-tooltip-arrow{left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.ant-tooltip-placement-bottomLeft .ant-tooltip-arrow{left:13px}.ant-tooltip-placement-bottomRight .ant-tooltip-arrow{right:13px}.ant-tooltip-rtl{direction:rtl}.ant-tooltip-rtl .ant-tooltip-inner{text-align:right}
6
+ .ant-radio-group{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';display:inline-block;line-height:unset}.ant-radio-group .ant-badge-count{z-index:1}.ant-radio-group>.ant-badge:not(:first-child)>.ant-radio-button-wrapper{border-left:none}.ant-radio-wrapper{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;display:inline-block;margin-right:8px;white-space:nowrap;cursor:pointer}.ant-radio{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;color:rgba(0,0,0,0.65);font-size:14px;font-variant:tabular-nums;line-height:1.5715;list-style:none;-webkit-font-feature-settings:'tnum';font-feature-settings:'tnum';position:relative;top:0px;display:inline-block;line-height:1;white-space:nowrap;vertical-align:sub;outline:none;cursor:pointer}.ant-radio-wrapper:hover .ant-radio,.ant-radio:hover .ant-radio-inner,.ant-radio-input:focus+.ant-radio-inner{border-color:#1890ff}.ant-radio-input:focus+.ant-radio-inner{-webkit-box-shadow:0 0 0 3px rgba(24,144,255,0.08);box-shadow:0 0 0 3px rgba(24,144,255,0.08)}.ant-radio-checked::after{position:absolute;top:0;left:0;width:100%;height:100%;border:1px solid #1890ff;border-radius:50%;visibility:hidden;-webkit-animation:antRadioEffect 0.36s ease-in-out;animation:antRadioEffect 0.36s ease-in-out;-webkit-animation-fill-mode:both;animation-fill-mode:both;content:''}.ant-radio:hover::after,.ant-radio-wrapper:hover .ant-radio::after{visibility:visible}.ant-radio-inner{position:relative;top:0;left:0;display:block;width:16px;height:16px;background-color:#fff;border-color:#d9d9d9;border-style:solid;border-width:1px;border-radius:100px;-webkit-transition:all 0.3s;transition:all 0.3s}.ant-radio-inner::after{position:absolute;top:3px;left:3px;display:table;width:8px;height:8px;background-color:#1890ff;border-top:0;border-left:0;border-radius:8px;-webkit-transform:scale(0);transform:scale(0);opacity:0;-webkit-transition:all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);transition:all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);content:' '}.ant-radio-input{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;cursor:pointer;opacity:0}.ant-radio-checked .ant-radio-inner{border-color:#1890ff}.ant-radio-checked .ant-radio-inner::after{-webkit-transform:scale(1);transform:scale(1);opacity:1;-webkit-transition:all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);transition:all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86)}.ant-radio-disabled .ant-radio-inner{background-color:#f5f5f5;border-color:#d9d9d9 !important;cursor:not-allowed}.ant-radio-disabled .ant-radio-inner::after{background-color:rgba(0,0,0,0.2)}.ant-radio-disabled .ant-radio-input{cursor:not-allowed}.ant-radio-disabled+span{color:rgba(0,0,0,0.25);cursor:not-allowed}span.ant-radio+*{padding-right:8px;padding-left:8px}.ant-radio-button-wrapper{position:relative;display:inline-block;height:32px;margin:0;padding:0 15px;color:rgba(0,0,0,0.65);line-height:30px;background:#fff;border:1px solid #d9d9d9;border-top-width:1.02px;border-left-width:0;cursor:pointer;-webkit-transition:color 0.3s, background 0.3s, border-color 0.3s, -webkit-box-shadow 0.3s;transition:color 0.3s, background 0.3s, border-color 0.3s, -webkit-box-shadow 0.3s;transition:color 0.3s, background 0.3s, border-color 0.3s, box-shadow 0.3s;transition:color 0.3s, background 0.3s, border-color 0.3s, box-shadow 0.3s, -webkit-box-shadow 0.3s}.ant-radio-button-wrapper a{color:rgba(0,0,0,0.65)}.ant-radio-button-wrapper>.ant-radio-button{display:block;width:0;height:0;margin-left:0}.ant-radio-group-large .ant-radio-button-wrapper{height:40px;font-size:16px;line-height:38px}.ant-radio-group-small .ant-radio-button-wrapper{height:24px;padding:0 7px;line-height:22px}.ant-radio-button-wrapper:not(:first-child)::before{position:absolute;top:-1px;left:-1px;display:block;-webkit-box-sizing:content-box;box-sizing:content-box;width:1px;height:100%;padding:1px 0;background-color:#d9d9d9;-webkit-transition:background-color 0.3s;transition:background-color 0.3s;content:''}.ant-radio-button-wrapper:first-child{border-left:1px solid #d9d9d9;border-radius:2px 0 0 2px}.ant-radio-button-wrapper:last-child{border-radius:0 2px 2px 0}.ant-radio-button-wrapper:first-child:last-child{border-radius:2px}.ant-radio-button-wrapper:hover{position:relative;color:#1890ff}.ant-radio-button-wrapper:focus-within{-webkit-box-shadow:0 0 0 3px rgba(24,144,255,0.08);box-shadow:0 0 0 3px rgba(24,144,255,0.08)}.ant-radio-button-wrapper .ant-radio-inner,.ant-radio-button-wrapper input[type='checkbox'],.ant-radio-button-wrapper input[type='radio']{width:0;height:0;opacity:0;pointer-events:none}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){z-index:1;color:#1890ff;background:#fff;border-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled)::before{background-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):first-child{border-color:#1890ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#40a9ff;border-color:#40a9ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover::before{background-color:#40a9ff}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#096dd9;border-color:#096dd9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active::before{background-color:#096dd9}.ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{-webkit-box-shadow:0 0 0 3px rgba(24,144,255,0.08);box-shadow:0 0 0 3px rgba(24,144,255,0.08)}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled){color:#fff;background:#1890ff;border-color:#1890ff}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):hover{color:#fff;background:#40a9ff;border-color:#40a9ff}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):active{color:#fff;background:#096dd9;border-color:#096dd9}.ant-radio-group-solid .ant-radio-button-wrapper-checked:not(.ant-radio-button-wrapper-disabled):focus-within{-webkit-box-shadow:0 0 0 3px rgba(24,144,255,0.08);box-shadow:0 0 0 3px rgba(24,144,255,0.08)}.ant-radio-button-wrapper-disabled{color:rgba(0,0,0,0.25);background-color:#f5f5f5;border-color:#d9d9d9;cursor:not-allowed}.ant-radio-button-wrapper-disabled:first-child,.ant-radio-button-wrapper-disabled:hover{color:rgba(0,0,0,0.25);background-color:#f5f5f5;border-color:#d9d9d9}.ant-radio-button-wrapper-disabled:first-child{border-left-color:#d9d9d9}.ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked{color:#fff;background-color:#e6e6e6;border-color:#d9d9d9;-webkit-box-shadow:none;box-shadow:none}@-webkit-keyframes antRadioEffect{0%{-webkit-transform:scale(1);transform:scale(1);opacity:0.5}100%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:0}}@keyframes antRadioEffect{0%{-webkit-transform:scale(1);transform:scale(1);opacity:0.5}100%{-webkit-transform:scale(1.6);transform:scale(1.6);opacity:0}}@supports (-moz-appearance: meterbar) and (background-blend-mode: difference,normal){.ant-radio{vertical-align:text-bottom}}.ant-radio-group.ant-radio-group-rtl{direction:rtl}.ant-radio-wrapper.ant-radio-wrapper-rtl{margin-right:0;margin-left:8px;direction:rtl}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl{border-right-width:0;border-left-width:1px}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:not(:first-child)::before{right:-1px;left:0}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:first-child{border-right:1px solid #d9d9d9;border-radius:0 2px 2px 0}.ant-radio-button-wrapper-checked:not([class*=' ant-radio-button-wrapper-disabled']).ant-radio-button-wrapper:first-child{border-right-color:#40a9ff}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper:last-child{border-radius:2px 0 0 2px}.ant-radio-button-wrapper.ant-radio-button-wrapper-rtl.ant-radio-button-wrapper-disabled:first-child{border-right-color:#d9d9d9}
dist/js/homeScreen/app.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){var r={};function e(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=t,e.c=r,e.d=function(t,r,n){e.o(t,r)||Object.defineProperty(t,r,{configurable:!1,enumerable:!0,get:n})},e.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},e.n=function(t){var r=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,r){return Object.prototype.hasOwnProperty.call(t,r)},e.p="",e(e.s=2)}([function(t,r,e){"use strict";document.addEventListener("DOMContentLoaded",function(){(0,wp.hooks.addFilter)("woocommerce_admin_homepage_default_stats","wcml/homescreen/remove_revenue_widgets",n)});var n=function(t){return t.filter(function(t){return"revenue/"!==t.substr(0,8)})}},function(t,r,e){var n=function(t){"use strict";var r,e=Object.prototype,n=e.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function u(t,r,e,n){var o=r&&r.prototype instanceof v?r:v,i=Object.create(o.prototype),a=new k(n||[]);return i._invoke=function(t,r,e){var n=s;return function(o,i){if(n===l)throw new Error("Generator is already running");if(n===p){if("throw"===o)throw i;return N()}for(e.method=o,e.arg=i;;){var a=e.delegate;if(a){var c=E(a,e);if(c){if(c===y)continue;return c}}if("next"===e.method)e.sent=e._sent=e.arg;else if("throw"===e.method){if(n===s)throw n=p,e.arg;e.dispatchException(e.arg)}else"return"===e.method&&e.abrupt("return",e.arg);n=l;var u=f(t,r,e);if("normal"===u.type){if(n=e.done?p:h,u.arg===y)continue;return{value:u.arg,done:e.done}}"throw"===u.type&&(n=p,e.method="throw",e.arg=u.arg)}}}(t,e,a),i}function f(t,r,e){try{return{type:"normal",arg:t.call(r,e)}}catch(t){return{type:"throw",arg:t}}}t.wrap=u;var s="suspendedStart",h="suspendedYield",l="executing",p="completed",y={};function v(){}function d(){}function g(){}var m={};m[i]=function(){return this};var w=Object.getPrototypeOf,x=w&&w(w(G([])));x&&x!==e&&n.call(x,i)&&(m=x);var L=g.prototype=v.prototype=Object.create(m);function _(t){["next","throw","return"].forEach(function(r){t[r]=function(t){return this._invoke(r,t)}})}function b(t,r){var e;this._invoke=function(o,i){function a(){return new r(function(e,a){!function e(o,i,a,c){var u=f(t[o],t,i);if("throw"!==u.type){var s=u.arg,h=s.value;return h&&"object"==typeof h&&n.call(h,"__await")?r.resolve(h.__await).then(function(t){e("next",t,a,c)},function(t){e("throw",t,a,c)}):r.resolve(h).then(function(t){s.value=t,a(s)},function(t){return e("throw",t,a,c)})}c(u.arg)}(o,i,e,a)})}return e=e?e.then(a,a):a()}}function E(t,e){var n=t.iterator[e.method];if(n===r){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=r,E(t,e),"throw"===e.method))return y;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return y}var o=f(n,t.iterator,e.arg);if("throw"===o.type)return e.method="throw",e.arg=o.arg,e.delegate=null,y;var i=o.arg;return i?i.done?(e[t.resultName]=i.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=r),e.delegate=null,y):i:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,y)}function O(t){var r={tryLoc:t[0]};1 in t&&(r.catchLoc=t[1]),2 in t&&(r.finallyLoc=t[2],r.afterLoc=t[3]),this.tryEntries.push(r)}function j(t){var r=t.completion||{};r.type="normal",delete r.arg,t.completion=r}function k(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(O,this),this.reset(!0)}function G(t){if(t){var e=t[i];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,a=function e(){for(;++o<t.length;)if(n.call(t,o))return e.value=t[o],e.done=!1,e;return e.value=r,e.done=!0,e};return a.next=a}}return{next:N}}function N(){return{value:r,done:!0}}return d.prototype=L.constructor=g,g.constructor=d,g[c]=d.displayName="GeneratorFunction",t.isGeneratorFunction=function(t){var r="function"==typeof t&&t.constructor;return!!r&&(r===d||"GeneratorFunction"===(r.displayName||r.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,g):(t.__proto__=g,c in t||(t[c]="GeneratorFunction")),t.prototype=Object.create(L),t},t.awrap=function(t){return{__await:t}},_(b.prototype),b.prototype[a]=function(){return this},t.AsyncIterator=b,t.async=function(r,e,n,o,i){void 0===i&&(i=Promise);var a=new b(u(r,e,n,o),i);return t.isGeneratorFunction(e)?a:a.next().then(function(t){return t.done?t.value:a.next()})},_(L),L[c]="Generator",L[i]=function(){return this},L.toString=function(){return"[object Generator]"},t.keys=function(t){var r=[];for(var e in t)r.push(e);return r.reverse(),function e(){for(;r.length;){var n=r.pop();if(n in t)return e.value=n,e.done=!1,e}return e.done=!0,e}},t.values=G,k.prototype={constructor:k,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=r,this.done=!1,this.delegate=null,this.method="next",this.arg=r,this.tryEntries.forEach(j),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=r)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function o(n,o){return c.type="throw",c.arg=t,e.next=n,o&&(e.method="next",e.arg=r),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var u=n.call(a,"catchLoc"),f=n.call(a,"finallyLoc");if(u&&f){if(this.prev<a.catchLoc)return o(a.catchLoc,!0);if(this.prev<a.finallyLoc)return o(a.finallyLoc)}else if(u){if(this.prev<a.catchLoc)return o(a.catchLoc,!0)}else{if(!f)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return o(a.finallyLoc)}}}},abrupt:function(t,r){for(var e=this.tryEntries.length-1;e>=0;--e){var o=this.tryEntries[e];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=r&&r<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=r,i?(this.method="next",this.next=i.finallyLoc,y):this.complete(a)},complete:function(t,r){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&r&&(this.next=r),y},finish:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.finallyLoc===t)return this.complete(e.completion,e.afterLoc),j(e),y}},catch:function(t){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc===t){var n=e.completion;if("throw"===n.type){var o=n.arg;j(e)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:G(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=r),y}},t}(t.exports);try{regeneratorRuntime=n}catch(t){Function("r","regeneratorRuntime = r")(n)}},function(t,r,e){e(1),e(7),t.exports=e(0)},,,,,function(t,r){}]);
dist/js/multicurrencyOptions/app.js CHANGED
@@ -1,4 +1,4 @@
1
- !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=257)}([function(e,t,n){"use strict";e.exports=n(255)},function(e,t,n){var r;
2
  /*!
3
  Copyright (c) 2017 Jed Watson.
4
  Licensed under the MIT License (MIT), see
@@ -9,12 +9,12 @@
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
- !function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if("string"===i||"number"===i)e.push(r);else if(Array.isArray(r)&&r.length){var a=o.apply(null,r);a&&e.push(a)}else if("object"===i)for(var u in r)n.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}void 0!==e&&e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,t,n){"use strict";n.d(t,"b",function(){return u});var r={};function o(e,t){0}function i(e,t){0}function a(e,t,n){t||r[n]||(e(!1,n),r[n]=!0)}function u(e,t){a(i,e,t)}t.a=function(e,t){a(o,e,t)}},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),e.exports=n(254)},function(e,t,n){"use strict";var r={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(e){var t=e.keyCode;if(e.altKey&&!e.ctrlKey||e.metaKey||t>=r.F1&&t<=r.F12)return!1;switch(t){case r.ALT:case r.CAPS_LOCK:case r.CONTEXT_MENU:case r.CTRL:case r.DOWN:case r.END:case r.ESC:case r.HOME:case r.INSERT:case r.LEFT:case r.MAC_FF_META:case r.META:case r.NUMLOCK:case r.NUM_CENTER:case r.PAGE_DOWN:case r.PAGE_UP:case r.PAUSE:case r.PRINT_SCREEN:case r.RIGHT:case r.SHIFT:case r.UP:case r.WIN_KEY:case r.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(e){if(e>=r.ZERO&&e<=r.NINE)return!0;if(e>=r.NUM_ZERO&&e<=r.NUM_MULTIPLY)return!0;if(e>=r.A&&e<=r.Z)return!0;if(-1!==window.navigator.userAgent.indexOf("WebKit")&&0===e)return!0;switch(e){case r.SPACE:case r.QUESTION_MARK:case r.NUM_PLUS:case r.NUM_MINUS:case r.NUM_PERIOD:case r.NUM_DIVISION:case r.SEMICOLON:case r.DASH:case r.EQUALS:case r.COMMA:case r.PERIOD:case r.SLASH:case r.APOSTROPHE:case r.SINGLE_QUOTE:case r.OPEN_SQUARE_BRACKET:case r.BACKSLASH:case r.CLOSE_SQUARE_BRACKET:return!0;default:return!1}}};t.a=r},function(e,t,n){e.exports=n(244)()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ConfigConsumer",{enumerable:!0,get:function(){return u.ConfigConsumer}}),Object.defineProperty(t,"ConfigContext",{enumerable:!0,get:function(){return u.ConfigContext}}),t.default=t.configConsumerProps=void 0;var r=s(n(0)),o=n(114),i=s(n(238)),a=function(e){return e&&e.__esModule?e:{default:e}}(n(42)),u=n(233),l=n(35);function c(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return c=function(){return e},e}function s(e){if(e&&e.__esModule)return e;if(null===e||"object"!==f(e)&&"function"!=typeof e)return{default:e};var t=c();if(t&&t.has(e))return t.get(e);var n={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var i=r?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(n,o,i):n[o]=e[o]}return n.default=e,t&&t.set(e,n),n}function f(e){"@babel/helpers - typeof";return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function p(){return(p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function d(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function y(e,t){return(y=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function h(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}();return function(){var n,r=m(e);if(t){var o=m(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===f(t)||"function"==typeof t))return t;return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function m(e){return(m=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}t.configConsumerProps=["getTargetContainer","getPopupContainer","rootPrefixCls","getPrefixCls","renderEmpty","csp","autoInsertSpaceInButton","locale","pageHeader"];var v=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&y(e,t)}(n,r.Component);var t=h(n);function n(){var e;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),(e=t.apply(this,arguments)).getPrefixClsWrapper=function(t){return function(n,r){var o=e.props.prefixCls;if(r)return r;var i=o||t.getPrefixCls("");return n?"".concat(i,"-").concat(n):i}},e.renderProvider=function(t,n){var a=e.props,c=a.children,s=a.getTargetContainer,f=a.getPopupContainer,d=a.renderEmpty,y=a.csp,h=a.autoInsertSpaceInButton,m=a.form,v=a.input,b=a.locale,g=a.pageHeader,w=a.componentSize,O=a.direction,E=a.space,S=p(p({},t),{getPrefixCls:e.getPrefixClsWrapper(t),csp:y,autoInsertSpaceInButton:h,locale:b||n,direction:O,space:E});s&&(S.getTargetContainer=s),f&&(S.getPopupContainer=f),d&&(S.renderEmpty=d),g&&(S.pageHeader=g),v&&(S.input=v);var _=c,P={};return b&&b.Form&&b.Form.defaultValidateMessages&&(P=b.Form.defaultValidateMessages),m&&m.validateMessages&&(P=p(p({},P),m.validateMessages)),Object.keys(P).length>0&&(_=r.createElement(o.FormProvider,{validateMessages:P},c)),r.createElement(l.SizeContextProvider,{size:w},r.createElement(u.ConfigContext.Provider,{value:S},r.createElement(i.default,{locale:b||n,_ANT_MARK__:i.ANT_MARK},_)))},e}return function(e,t,n){t&&d(e.prototype,t),n&&d(e,n)}(n,[{key:"render",value:function(){var e=this;return r.createElement(a.default,null,function(t,n,o){return r.createElement(u.ConfigConsumer,null,function(t){return e.renderProvider(t,o)})})}}]),n}();t.default=v},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useStore=t.getStore=t.getStoreAction=t.getStoreProperty=t.getCurrencyIndex=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=n(78),i=n(36),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(n(28));t.default=function(e){var t=e.activeCurrencies,n=e.allCurrencies,a=e.allCountries,l=e.languages,c=e.gateways,s=e.mode,f=e.maxMindKeyExist;return(0,o.createStore)({activeCurrencies:t,allCurrencies:n,allCountries:a,languages:l,gateways:c,mode:s,maxMindKeyExist:f,modalCurrency:null,updating:!1,setDefaultCurrencyForLang:(0,o.action)(function(e,t){var n=e.languages.findIndex(function(e){return e.code===t.language}),r=e.languages[n];r.defaultCurrency=t.currency,e.languages[n]=r}),getCurrencyIndex:(0,o.action)(function(e,t){e.activeCurrencies.findIndex(function(e){return e.code===t})}),enableCurrencyForLang:(0,o.action)(function(e,t){var n=u(e.activeCurrencies)(t.currency),o=e.activeCurrencies[n],i=t.enable?1:0;o.languages=r({},o.languages,function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}({},t.language,i)),e.activeCurrencies[n]=o}),deleteCurrency:(0,o.action)(function(e,t){var n=u(e.activeCurrencies)(t),o=r({},e.activeCurrencies[n]);e.activeCurrencies.splice(n,1),(0,i.triggerActiveCurrenciesChange)({action:"remove",currency:o})}),setModalCurrency:(0,o.action)(function(e,t){e.modalCurrency=e.setInitialGatewayCurrency(t,e.activeCurrencies)}),setInitialGatewayCurrency:function(e,t){var n=function(n){return void 0===n.currency||function(e){return t.find(function(t){return t.code===e})}(n.currency)||(n=r({},n,{currency:e.code})),n};return e&&e.gatewaysSettings&&Object.keys(e.gatewaysSettings).map(function(t){e.gatewaysSettings[t]=n(e.gatewaysSettings[t])}),e},saveModalCurrency:(0,o.action)(function(e){var t=u(e.activeCurrencies)(e.modalCurrency.code);if(t<0){var n=r({},e.modalCurrency,{isNew:!1});e.activeCurrencies.push(n),(0,i.triggerActiveCurrenciesChange)({action:"add",currency:n})}else e.activeCurrencies[t]=e.modalCurrency}),newCurrencies:(0,o.computed)(function(e){var t=e.activeCurrencies.map(function(e){return e.code});return e.allCurrencies.filter(function(e){return!t.includes(e.code)})}),defaultCurrency:(0,o.computed)(function(e){return e.activeCurrencies.filter(function(e){return e.isDefault})[0]}),setUpdating:(0,o.action)(function(e,t){e.updating=t}),setMode:(0,o.action)(function(e,t){e.mode=t,(0,i.triggerModeChange)({mode:t})}),setMaxMindKeyExist:(0,o.action)(function(e){e.maxMindKeyExist=!0})})};var u=t.getCurrencyIndex=function(e){return function(t){return a.findIndex(a.propEq("code",t))(e)}},l=t.getStoreProperty=function(e){return(0,o.useStoreState)(a.path(Array.isArray(e)?e:[e]))},c=t.getStoreAction=function(e){return(0,o.useStoreActions)(a.prop(e))};t.getStore=function(e,t){return[l(e),c(t)]},t.useStore=function(e){return[l(e),c("set"+(0,i.capitalize)(e)),c("reset"+(0,i.capitalize)(e))]}},function(e,t,n){"use strict";t.__esModule=!0;var r=function(e){return e&&e.__esModule?e:{default:e}}(n(218));t.default=r.default||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}},function(e,t,n){(function(t){for(var r=n(242),o="undefined"==typeof window?t:window,i=["moz","webkit"],a="AnimationFrame",u=o["request"+a],l=o["cancel"+a]||o["cancelRequest"+a],c=0;!u&&c<i.length;c++)u=o[i[c]+"Request"+a],l=o[i[c]+"Cancel"+a]||o[i[c]+"CancelRequest"+a];if(!u||!l){var s=0,f=0,p=[];u=function(e){if(0===p.length){var t=r(),n=Math.max(0,1e3/60-(t-s));s=n+t,setTimeout(function(){var e=p.slice(0);p.length=0;for(var t=0;t<e.length;t++)if(!e[t].cancelled)try{e[t].callback(s)}catch(e){setTimeout(function(){throw e},0)}},Math.round(n))}return p.push({handle:++f,callback:e,cancelled:!1}),f},l=function(e){for(var t=0;t<p.length;t++)p[t].handle===e&&(p[t].cancelled=!0)}}e.exports=function(e){return u.call(o,e)},e.exports.cancel=function(){l.apply(o,arguments)},e.exports.polyfill=function(e){e||(e=o),e.requestAnimationFrame=u,e.cancelAnimationFrame=l}}).call(this,n(45))},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var t=s();if(t&&t.has(e))return t.get(e);var n={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var a=o?Object.getOwnPropertyDescriptor(e,i):null;a&&(a.get||a.set)?Object.defineProperty(n,i,a):n[i]=e[i]}n.default=e,t&&t.set(e,n);return n}(n(0)),i=c(n(1)),a=c(n(88)),u=n(174),l=n(56);function c(e){return e&&e.__esModule?e:{default:e}}function s(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return s=function(){return e},e}function f(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(e)))return;var n=[],r=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(r=(a=u.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){o=!0,i=e}finally{try{r||null==u.return||u.return()}finally{if(o)throw i}}return n}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return p(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return p(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function d(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(0,u.setTwoToneColor)("#1890ff");var y=o.forwardRef(function(e,t){var n=e.className,r=e.icon,u=e.spin,c=e.rotate,s=e.tabIndex,p=e.onClick,y=e.twoToneColor,h=d(e,["className","icon","spin","rotate","tabIndex","onClick","twoToneColor"]),m=(0,i.default)("anticon",function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}({},"anticon-".concat(r.name),Boolean(r.name)),n),v=(0,i.default)({"anticon-spin":!!u||"loading"===r.name}),b=s;void 0===b&&p&&(b=-1);var g=c?{msTransform:"rotate(".concat(c,"deg)"),transform:"rotate(".concat(c,"deg)")}:void 0,w=f((0,l.normalizeTwoToneColors)(y),2),O=w[0],E=w[1];return o.createElement("span",Object.assign({role:"img","aria-label":r.name},h,{ref:t,tabIndex:b,onClick:p,className:m}),o.createElement(a.default,{className:v,icon:r,primaryColor:O,secondaryColor:E,style:g}))});y.displayName="AntdIcon",y.getTwoToneColor=u.getTwoToneColor,y.setTwoToneColor=u.setTwoToneColor;var h=y;t.default=h},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return function(e){t.forEach(function(t){!function(e,t){"function"==typeof e?e(t):"object"===r(e)&&e&&"current"in e&&(e.current=t)}(t,e)})}}function i(e){return!(e.type&&e.type.prototype&&!e.type.prototype.render)&&!("function"==typeof e&&e.prototype&&!e.prototype.render)}n.d(t,"a",function(){return o}),n.d(t,"b",function(){return i})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Spinner=t.getTooltip=t.InputRow=t.SelectRow=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=a(n(0)),i=a(n(105));function a(e){return e&&e.__esModule?e:{default:e}}t.SelectRow=function(e){var t=e.onChange,n=e.label,i=e.attrs,a=e.tooltip,l=e.children,c=e.afterSelect,s=void 0===c?null:c;return o.default.createElement("div",{className:"wpml-form-row"},o.default.createElement("label",{htmlFor:i.id},n,u(a)),o.default.createElement("select",r({onChange:t},i),l),s)},t.InputRow=function(e){var t=e.onChange,n=e.label,i=e.attrs,a=e.tooltip;return o.default.createElement("div",{className:"wpml-form-row"},o.default.createElement("label",{htmlFor:i.id},n,u(a)),o.default.createElement("input",r({},i,{onChange:t})))};var u=t.getTooltip=function(e){return e&&o.default.createElement(i.default,{title:l(e)}," ",o.default.createElement("i",{className:"wcml-tip otgs-ico-help"}))},l=function(e){return o.default.createElement("div",{dangerouslySetInnerHTML:{__html:e}})};t.Spinner=function(e){var t=e.style,n=r({visibility:"visible"},t);return o.default.createElement("span",{className:"spinner",style:n})}},function(e,t,n){"use strict";n.d(t,"a",function(){return i});var r=n(3),o=n.n(r);function i(e){return e instanceof HTMLElement?e:o.a.findDOMNode(e)}},function(e,t,n){"use strict";(function(e){var r;n.d(t,"a",function(){return $}),n.d(t,"b",function(){return q}),n.d(t,"c",function(){return u}),n.d(t,"d",function(){return c}),n.d(t,"e",function(){return B});var o="undefined"!=typeof Symbol?Symbol("immer-nothing"):((r={})["immer-nothing"]=!0,r),i="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-draftable"):"__$immer_draftable",a="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-state"):"__$immer_state";function u(e){return!!e&&!!e[a]}function l(e){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return!0;var t=Object.getPrototypeOf(e);return!t||t===Object.prototype||(!!e[i]||!!e.constructor[i])}function c(e){if(e&&e[a])return e[a].base}var s=Object.assign||function(e,t){for(var n in t)h(t,n)&&(e[n]=t[n]);return e},f="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Object.getOwnPropertyNames;function p(e,t){if(void 0===t&&(t=!1),Array.isArray(e))return e.slice();var n=Object.create(Object.getPrototypeOf(e));return f(e).forEach(function(r){if(r!==a){var o=Object.getOwnPropertyDescriptor(e,r),i=o.value;o.get&&t&&(i=o.get.call(e)),o.enumerable?n[r]=i:t&&Object.defineProperty(n,r,{value:i,writable:!0,configurable:!0})}}),n}function d(e,t){if(Array.isArray(e))for(var n=0;n<e.length;n++)t(n,e[n],e);else f(e).forEach(function(n){return t(n,e[n],e)})}function y(e,t){var n=Object.getOwnPropertyDescriptor(e,t);return!!n&&n.enumerable}function h(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function m(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}var v=function(e){this.drafts=[],this.parent=e,this.canAutoFreeze=!0,this.patches=null};function b(e){e[a].revoke()}v.prototype.usePatches=function(e){e&&(this.patches=[],this.inversePatches=[],this.patchListener=e)},v.prototype.revoke=function(){this.leave(),this.drafts.forEach(b),this.drafts=null},v.prototype.leave=function(){this===v.current&&(v.current=this.parent)},v.current=null,v.enter=function(){return this.current=new v(this.current)};var g={};function w(e,t){var n=Array.isArray(e),r=x(e);d(r,function(t){!function(e,t,n){var r=g[t];r?r.enumerable=n:g[t]=r={configurable:!0,enumerable:n,get:function(){return function(e,t){j(e);var n=S(E(e),t);if(e.finalizing)return n;if(n===S(e.base,t)&&l(n))return P(e),e.copy[t]=w(n,e);return n}(this[a],t)},set:function(e){!function(e,t,n){if(j(e),e.assigned[t]=!0,!e.modified){if(m(n,S(E(e),t)))return;_(e),P(e)}e.copy[t]=n}(this[a],t,e)}};Object.defineProperty(e,t,r)}(r,t,n||y(e,t))});var o=t?t.scope:v.current;return function(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!1,writable:!0})}(r,a,{scope:o,modified:!1,finalizing:!1,finalized:!1,assigned:{},parent:t,base:e,draft:r,copy:null,revoke:O,revoked:!1}),o.drafts.push(r),r}function O(){this.revoked=!0}function E(e){return e.copy||e.base}function S(e,t){var n=e[a];if(n&&!n.finalizing){n.finalizing=!0;var r=e[t];return n.finalizing=!1,r}return e[t]}function _(e){e.modified||(e.modified=!0,e.parent&&_(e.parent))}function P(e){e.copy||(e.copy=x(e.base))}function x(e){var t=e&&e[a];if(t){t.finalizing=!0;var n=p(t.draft,!0);return t.finalizing=!1,n}return p(e)}function j(e){if(!0===e.revoked)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+JSON.stringify(E(e)))}function C(e){for(var t=e.length-1;t>=0;t--){var n=e[t][a];n.modified||(Array.isArray(n.base)?T(n)&&_(n):k(n)&&_(n))}}function k(e){for(var t=e.base,n=e.draft,r=Object.keys(n),o=r.length-1;o>=0;o--){var i=r[o],u=t[i];if(void 0===u&&!h(t,i))return!0;var l=n[i],c=l&&l[a];if(c?c.base!==u:!m(l,u))return!0}return r.length!==Object.keys(t).length}function T(e){var t=e.draft;if(t.length!==e.base.length)return!0;var n=Object.getOwnPropertyDescriptor(t,t.length-1);return!(!n||n.get)}var M=Object.freeze({willFinalize:function(e,t,n){e.drafts.forEach(function(e){e[a].finalizing=!0}),n?u(t)&&t[a].scope===e&&C(e.drafts):(e.patches&&function e(t){if(t&&"object"==typeof t){var n=t[a];if(n){var r=n.base,o=n.draft,i=n.assigned;if(Array.isArray(t)){if(T(n)){if(_(n),i.length=!0,o.length<r.length)for(var u=o.length;u<r.length;u++)i[u]=!1;else for(var l=r.length;l<o.length;l++)i[l]=!0;for(var c=0;c<o.length;c++)void 0===i[c]&&e(o[c])}}else Object.keys(o).forEach(function(t){void 0!==r[t]||h(r,t)?i[t]||e(o[t]):(i[t]=!0,_(n))}),Object.keys(r).forEach(function(e){void 0!==o[e]||h(o,e)||(i[e]=!1,_(n))})}}}(e.drafts[0]),C(e.drafts))},createProxy:w});function A(e,t){var n=t?t.scope:v.current,r={scope:n,modified:!1,finalized:!1,assigned:{},parent:t,base:e,draft:null,drafts:{},copy:null,revoke:null},o=Array.isArray(e)?Proxy.revocable([r],R):Proxy.revocable(r,N),i=o.revoke,a=o.proxy;return r.draft=a,r.revoke=i,n.drafts.push(a),a}var N={get:function(e,t){if(t===a)return e;var n=e.drafts;if(!e.modified&&h(n,t))return n[t];var r=D(e)[t];if(e.finalized||!l(r))return r;if(e.modified){if(r!==I(e.base,t))return r;n=e.copy}return n[t]=A(r,e)},has:function(e,t){return t in D(e)},ownKeys:function(e){return Reflect.ownKeys(D(e))},set:function(e,t,n){if(!e.modified){var r=I(e.base,t),o=n?m(r,n)||n===e.drafts[t]:m(r,n)&&t in e.base;if(o)return!0;F(e)}return e.assigned[t]=!0,e.copy[t]=n,!0},deleteProperty:function(e,t){(void 0!==I(e.base,t)||t in e.base)&&(e.assigned[t]=!1,F(e));e.copy&&delete e.copy[t];return!0},getOwnPropertyDescriptor:function(e,t){var n=D(e),r=Reflect.getOwnPropertyDescriptor(n,t);r&&(r.writable=!0,r.configurable=!Array.isArray(n)||"length"!==t);return r},defineProperty:function(){throw new Error("Object.defineProperty() cannot be used on an Immer draft")},getPrototypeOf:function(e){return Object.getPrototypeOf(e.base)},setPrototypeOf:function(){throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft")}},R={};function D(e){return e.copy||e.base}function I(e,t){var n=e[a],r=Reflect.getOwnPropertyDescriptor(n?D(n):e,t);return r&&r.value}function F(e){e.modified||(e.modified=!0,e.copy=s(p(e.base),e.drafts),e.drafts=null,e.parent&&F(e.parent))}d(N,function(e,t){R[e]=function(){return arguments[0]=arguments[0][0],t.apply(this,arguments)}}),R.deleteProperty=function(e,t){if(isNaN(parseInt(t)))throw new Error("Immer only supports deleting array indices");return N.deleteProperty.call(this,e[0],t)},R.set=function(e,t,n){if("length"!==t&&isNaN(parseInt(t)))throw new Error("Immer only supports setting array indices and the 'length' property");return N.set.call(this,e[0],t,n)};var L=Object.freeze({willFinalize:function(){},createProxy:A});function z(e,t,n,r){Array.isArray(e.base)?function(e,t,n,r){var o,i,a=e.base,u=e.copy,l=e.assigned;u.length<a.length&&(a=(o=[u,a])[0],u=o[1],n=(i=[r,n])[0],r=i[1]);var c=u.length-a.length,s=0;for(;a[s]===u[s]&&s<a.length;)++s;var f=a.length;for(;f>s&&a[f-1]===u[f+c-1];)--f;for(var p=s;p<f;++p)if(l[p]&&u[p]!==a[p]){var d=t.concat([p]);n.push({op:"replace",path:d,value:u[p]}),r.push({op:"replace",path:d,value:a[p]})}for(var y=f!=a.length,h=n.length,m=f+c-1;m>=f;--m){var v=t.concat([m]);n[h+m-f]={op:"add",path:v,value:u[m]},y&&r.push({op:"remove",path:v})}y||r.push({op:"replace",path:t.concat(["length"]),value:a.length})}(e,t,n,r):function(e,t,n,r){var o=e.base,i=e.copy;d(e.assigned,function(e,a){var u=o[e],l=i[e],c=a?e in o?"replace":"add":"remove";if(u!==l||"replace"!==c){var s=t.concat(e);n.push("remove"===c?{op:c,path:s}:{op:c,path:s,value:l}),r.push("add"===c?{op:"remove",path:s}:"remove"===c?{op:"add",path:s,value:u}:{op:"replace",path:s,value:u})}})}(e,t,n,r)}function V(e,t){for(var n=0;n<t.length;n++){var r=t[n],o=r.path;if(0===o.length&&"replace"===r.op)e=r.value;else{for(var i=e,a=0;a<o.length-1;a++)if(!(i=i[o[a]])||"object"!=typeof i)throw new Error("Cannot apply patch, path doesn't resolve: "+o.join("/"));var u=o[o.length-1];switch(r.op){case"replace":i[u]=r.value;break;case"add":Array.isArray(i)?i.splice(u,0,r.value):i[u]=r.value;break;case"remove":Array.isArray(i)?i.splice(u,1):delete i[u];break;default:throw new Error("Unsupported patch operation: "+r.op)}}}return e}var W={useProxies:"undefined"!=typeof Proxy&&"undefined"!=typeof Reflect,autoFreeze:void 0===e&&"verifyMinified"===function(){}.name,onAssign:null,onDelete:null,onCopy:null},U=function(e){s(this,W,e),this.setUseProxies(this.useProxies),this.produce=this.produce.bind(this)};U.prototype.produce=function(e,t,n){var r,i=this;if("function"==typeof e&&"function"!=typeof t){var a=t;t=e;var u=this;return function(e){var n=this;void 0===e&&(e=a);for(var r=[],o=arguments.length-1;o-- >0;)r[o]=arguments[o+1];return u.produce(e,function(e){return t.call.apply(t,[n,e].concat(r))})}}if("function"!=typeof t)throw new Error("The first or second argument to `produce` must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("The third argument to `produce` must be a function or undefined");if(l(e)){var c=v.enter(),s=this.createProxy(e),f=!0;try{r=t(s),f=!1}finally{f?c.revoke():c.leave()}return r instanceof Promise?r.then(function(e){return c.usePatches(n),i.processResult(e,c)},function(e){throw c.revoke(),e}):(c.usePatches(n),this.processResult(r,c))}return void 0===(r=t(e))?e:r!==o?r:void 0},U.prototype.createDraft=function(e){if(!l(e))throw new Error("First argument to `createDraft` must be a plain object, an array, or an immerable object");var t=v.enter(),n=this.createProxy(e);return n[a].isManual=!0,t.leave(),n},U.prototype.finishDraft=function(e,t){var n=e&&e[a];if(!n||!n.isManual)throw new Error("First argument to `finishDraft` must be a draft returned by `createDraft`");if(n.finalized)throw new Error("The given draft is already finalized");var r=n.scope;return r.usePatches(t),this.processResult(void 0,r)},U.prototype.setAutoFreeze=function(e){this.autoFreeze=e},U.prototype.setUseProxies=function(e){this.useProxies=e,s(this,e?L:M)},U.prototype.applyPatches=function(e,t){return u(e)?V(e,t):this.produce(e,function(e){return V(e,t)})},U.prototype.processResult=function(e,t){var n=t.drafts[0],r=void 0!==e&&e!==n;if(this.willFinalize(t,e,r),r){if(n[a].modified)throw t.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");l(e)&&(e=this.finalize(e,null,t)),t.patches&&(t.patches.push({op:"replace",path:[],value:e}),t.inversePatches.push({op:"replace",path:[],value:n[a].base}))}else e=this.finalize(n,[],t);return t.revoke(),t.patches&&t.patchListener(t.patches,t.inversePatches),e!==o?e:void 0},U.prototype.finalize=function(e,t,n){var r=this,o=e[a];if(!o)return Object.isFrozen(e)?e:this.finalizeTree(e,null,n);if(o.scope!==n)return e;if(!o.modified)return o.base;if(!o.finalized){if(o.finalized=!0,this.finalizeTree(o.draft,t,n),this.onDelete)if(this.useProxies){var i=o.assigned;for(var u in i)i[u]||this.onDelete(o,u)}else{var l=o.base,c=o.copy;d(l,function(e){h(c,e)||r.onDelete(o,e)})}this.onCopy&&this.onCopy(o),this.autoFreeze&&n.canAutoFreeze&&Object.freeze(o.copy),t&&n.patches&&z(o,t,n.patches,n.inversePatches)}return o.copy},U.prototype.finalizeTree=function(e,t,n){var r=this,o=e[a];o&&(this.useProxies||(o.copy=p(o.draft,!0)),e=o.copy);var i=!!t&&!!n.patches,c=function(a,s,f){if(s===f)throw Error("Immer forbids circular references");var p=!!o&&f===e;if(u(s)){var h=p&&i&&!o.assigned[a]?t.concat(a):null;if(u(s=r.finalize(s,h,n))&&(n.canAutoFreeze=!1),Array.isArray(f)||y(f,a)?f[a]=s:Object.defineProperty(f,a,{value:s}),p&&s===o.base[a])return}else{if(p&&m(s,o.base[a]))return;l(s)&&!Object.isFrozen(s)&&d(s,c)}p&&r.onAssign&&r.onAssign(o,a,s)};return d(e,c),e};var H=new U,B=(H.produce,H.setAutoFreeze.bind(H)),$=(H.setUseProxies.bind(H),H.applyPatches.bind(H),H.createDraft.bind(H)),q=H.finishDraft.bind(H)}).call(this,n(74))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=wcmlMultiCurrency.strings},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(0),o=n.n(r),i=n(107);function a(e){var t=[];return o.a.Children.forEach(e,function(e){void 0!==e&&null!==e&&(Array.isArray(e)?t=t.concat(a(e)):Object(i.isFragment)(e)&&e.props?t=t.concat(a(e.props.children)):t.push(e))}),t}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){"use strict";function r(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}return!1}n.d(t,"a",function(){return r})},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){e.exports=!n(31)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t){var n=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=n)},function(e,t,n){e.exports=n(106)},function(e,t,n){var r=n(65)("wks"),o=n(38),i=n(17).Symbol,a="function"==typeof i;(e.exports=function(e){return r[e]||(r[e]=a&&i[e]||(a?i:o)("Symbol."+e))}).store=r},function(e,t,n){var r=n(96),o=n(68);e.exports=function(e){return r(o(e))}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){var r=n(32),o=n(99),i=n(69),a=Object.defineProperty;t.f=n(20)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){var r=n(26),o=n(41);e.exports=n(20)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){"use strict";n.r(t);var r=function(){return!1},o=function(){return!0},i={"@@functional/placeholder":!0};function a(e){return null!=e&&"object"==typeof e&&!0===e["@@functional/placeholder"]}function u(e){return function t(n){return 0===arguments.length||a(n)?t:e.apply(this,arguments)}}function l(e){return function t(n,r){switch(arguments.length){case 0:return t;case 1:return a(n)?t:u(function(t){return e(n,t)});default:return a(n)&&a(r)?t:a(n)?u(function(t){return e(t,r)}):a(r)?u(function(t){return e(n,t)}):e(n,r)}}}var c=l(function(e,t){return Number(e)+Number(t)});function s(e,t){var n;e=e||[],t=t||[];var r=e.length,o=t.length,i=[];for(n=0;n<r;)i[i.length]=e[n],n+=1;for(n=0;n<o;)i[i.length]=t[n],n+=1;return i}function f(e,t){switch(e){case 0:return function(){return t.apply(this,arguments)};case 1:return function(e){return t.apply(this,arguments)};case 2:return function(e,n){return t.apply(this,arguments)};case 3:return function(e,n,r){return t.apply(this,arguments)};case 4:return function(e,n,r,o){return t.apply(this,arguments)};case 5:return function(e,n,r,o,i){return t.apply(this,arguments)};case 6:return function(e,n,r,o,i,a){return t.apply(this,arguments)};case 7:return function(e,n,r,o,i,a,u){return t.apply(this,arguments)};case 8:return function(e,n,r,o,i,a,u,l){return t.apply(this,arguments)};case 9:return function(e,n,r,o,i,a,u,l,c){return t.apply(this,arguments)};case 10:return function(e,n,r,o,i,a,u,l,c,s){return t.apply(this,arguments)};default:throw new Error("First argument to _arity must be a non-negative integer no greater than ten")}}function p(e,t,n){return function(){for(var r=[],o=0,i=e,u=0;u<t.length||o<arguments.length;){var l;u<t.length&&(!a(t[u])||o>=arguments.length)?l=t[u]:(l=arguments[o],o+=1),r[u]=l,a(l)||(i-=1),u+=1}return i<=0?n.apply(this,r):f(i,p(e,r,n))}}var d=l(function(e,t){return 1===e?u(t):f(e,p(e,[],t))}),y=u(function(e){return d(e.length,function(){var t=0,n=arguments[0],r=arguments[arguments.length-1],o=Array.prototype.slice.call(arguments,0);return o[0]=function(){var e=n.apply(this,s(arguments,[t,r]));return t+=1,e},e.apply(this,o)})});function h(e){return function t(n,r,o){switch(arguments.length){case 0:return t;case 1:return a(n)?t:l(function(t,r){return e(n,t,r)});case 2:return a(n)&&a(r)?t:a(n)?l(function(t,n){return e(t,r,n)}):a(r)?l(function(t,r){return e(n,t,r)}):u(function(t){return e(n,r,t)});default:return a(n)&&a(r)&&a(o)?t:a(n)&&a(r)?l(function(t,n){return e(t,n,o)}):a(n)&&a(o)?l(function(t,n){return e(t,r,n)}):a(r)&&a(o)?l(function(t,r){return e(n,t,r)}):a(n)?u(function(t){return e(t,r,o)}):a(r)?u(function(t){return e(n,t,o)}):a(o)?u(function(t){return e(n,r,t)}):e(n,r,o)}}}var m=h(function(e,t,n){if(e>=n.length||e<-n.length)return n;var r=(e<0?n.length:0)+e,o=s(n);return o[r]=t(n[r]),o}),v=Array.isArray||function(e){return null!=e&&e.length>=0&&"[object Array]"===Object.prototype.toString.call(e)};function b(e){return null!=e&&"function"==typeof e["@@transducer/step"]}function g(e,t,n){return function(){if(0===arguments.length)return n();var r=Array.prototype.slice.call(arguments,0),o=r.pop();if(!v(o)){for(var i=0;i<e.length;){if("function"==typeof o[e[i]])return o[e[i]].apply(o,r);i+=1}if(b(o))return t.apply(null,r)(o)}return n.apply(this,arguments)}}function w(e){return e&&e["@@transducer/reduced"]?e:{"@@transducer/value":e,"@@transducer/reduced":!0}}var O={init:function(){return this.xf["@@transducer/init"]()},result:function(e){return this.xf["@@transducer/result"](e)}},E=function(){function e(e,t){this.xf=t,this.f=e,this.all=!0}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.all&&(e=this.xf["@@transducer/step"](e,!0)),this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)||(this.all=!1,e=w(this.xf["@@transducer/step"](e,!1))),e},e}(),S=l(g(["all"],l(function(e,t){return new E(e,t)}),function(e,t){for(var n=0;n<t.length;){if(!e(t[n]))return!1;n+=1}return!0})),_=l(function(e,t){return t>e?t:e});function P(e,t){for(var n=0,r=t.length,o=Array(r);n<r;)o[n]=e(t[n]),n+=1;return o}function x(e){return"[object String]"===Object.prototype.toString.call(e)}var j=u(function(e){return!!v(e)||!!e&&("object"==typeof e&&(!x(e)&&(1===e.nodeType?!!e.length:0===e.length||e.length>0&&(e.hasOwnProperty(0)&&e.hasOwnProperty(e.length-1)))))}),C=function(){function e(e){this.f=e}return e.prototype["@@transducer/init"]=function(){throw new Error("init not implemented on XWrap")},e.prototype["@@transducer/result"]=function(e){return e},e.prototype["@@transducer/step"]=function(e,t){return this.f(e,t)},e}();function k(e){return new C(e)}var T=l(function(e,t){return f(e.length,function(){return e.apply(t,arguments)})});function M(e,t,n){for(var r=n.next();!r.done;){if((t=e["@@transducer/step"](t,r.value))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}r=n.next()}return e["@@transducer/result"](t)}function A(e,t,n,r){return e["@@transducer/result"](n[r](T(e["@@transducer/step"],e),t))}var N="undefined"!=typeof Symbol?Symbol.iterator:"@@iterator";function R(e,t,n){if("function"==typeof e&&(e=k(e)),j(n))return function(e,t,n){for(var r=0,o=n.length;r<o;){if((t=e["@@transducer/step"](t,n[r]))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}r+=1}return e["@@transducer/result"](t)}(e,t,n);if("function"==typeof n["fantasy-land/reduce"])return A(e,t,n,"fantasy-land/reduce");if(null!=n[N])return M(e,t,n[N]());if("function"==typeof n.next)return M(e,t,n);if("function"==typeof n.reduce)return A(e,t,n,"reduce");throw new TypeError("reduce: list must be array or iterable")}var D=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.xf["@@transducer/step"](e,this.f(t))},e}(),I=l(function(e,t){return new D(e,t)});function F(e,t){return Object.prototype.hasOwnProperty.call(t,e)}var L=Object.prototype.toString,z=function(){return"[object Arguments]"===L.call(arguments)?function(e){return"[object Arguments]"===L.call(e)}:function(e){return F("callee",e)}}(),V=!{toString:null}.propertyIsEnumerable("toString"),W=["constructor","valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"],U=function(){return arguments.propertyIsEnumerable("length")}(),H=function(e,t){for(var n=0;n<e.length;){if(e[n]===t)return!0;n+=1}return!1},B="function"!=typeof Object.keys||U?u(function(e){if(Object(e)!==e)return[];var t,n,r=[],o=U&&z(e);for(t in e)!F(t,e)||o&&"length"===t||(r[r.length]=t);if(V)for(n=W.length-1;n>=0;)F(t=W[n],e)&&!H(r,t)&&(r[r.length]=t),n-=1;return r}):u(function(e){return Object(e)!==e?[]:Object.keys(e)}),$=l(g(["fantasy-land/map","map"],I,function(e,t){switch(Object.prototype.toString.call(t)){case"[object Function]":return d(t.length,function(){return e.call(this,t.apply(this,arguments))});case"[object Object]":return R(function(n,r){return n[r]=e(t[r]),n},{},B(t));default:return P(e,t)}})),q=Number.isInteger||function(e){return e<<0===e},K=l(function(e,t){var n=e<0?t.length+e:e;return x(t)?t.charAt(n):t[n]}),Y=l(function(e,t){return e.map(function(e){for(var n,r=t,o=0;o<e.length;){if(null==r)return;n=e[o],r=q(n)?K(n,r):r[n],o+=1}return r})}),X=l(function(e,t){return Y([e],t)[0]}),Q=l(function(e,t){return X([e],t)}),G=l(function(e,t){return $(Q(e),t)}),J=h(R),Z=u(function(e){return d(J(_,0,G("length",e)),function(){for(var t=0,n=e.length;t<n;){if(!e[t].apply(this,arguments))return!1;t+=1}return!0})}),ee=u(function(e){return function(){return e}}),te=l(function(e,t){return e&&t}),ne=function(){function e(e,t){this.xf=t,this.f=e,this.any=!1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.any||(e=this.xf["@@transducer/step"](e,!1)),this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)&&(this.any=!0,e=w(this.xf["@@transducer/step"](e,!0))),e},e}(),re=l(g(["any"],l(function(e,t){return new ne(e,t)}),function(e,t){for(var n=0;n<t.length;){if(e(t[n]))return!0;n+=1}return!1})),oe=u(function(e){return d(J(_,0,G("length",e)),function(){for(var t=0,n=e.length;t<n;){if(e[t].apply(this,arguments))return!0;t+=1}return!1})}),ie=l(function(e,t){return"function"==typeof t["fantasy-land/ap"]?t["fantasy-land/ap"](e):"function"==typeof e.ap?e.ap(t):"function"==typeof e?function(n){return e(n)(t(n))}:R(function(e,n){return s(e,$(n,t))},[],e)});var ae=function(){function e(e,t){this.xf=t,this.pos=0,this.full=!1,this.acc=new Array(e)}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.acc=null,this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.store(t),this.full?this.xf["@@transducer/step"](e,this.getCopy()):e},e.prototype.store=function(e){this.acc[this.pos]=e,this.pos+=1,this.pos===this.acc.length&&(this.pos=0,this.full=!0)},e.prototype.getCopy=function(){return s(Array.prototype.slice.call(this.acc,this.pos),Array.prototype.slice.call(this.acc,0,this.pos))},e}(),ue=l(g([],l(function(e,t){return new ae(e,t)}),function(e,t){for(var n=0,r=t.length-(e-1),o=new Array(r>=0?r:0);n<r;)o[n]=Array.prototype.slice.call(t,n,n+e),n+=1;return o})),le=l(function(e,t){return s(t,[e])}),ce=l(function(e,t){return e.apply(this,t)}),se=u(function(e){for(var t=B(e),n=t.length,r=[],o=0;o<n;)r[o]=e[t[o]],o+=1;return r});function fe(e,t){return B(t).reduce(function(n,r){return n[r]=e(t[r]),n},{})}var pe=u(function e(t){return t=fe(function(t){return"function"==typeof t?t:e(t)},t),d(J(_,0,G("length",se(t))),function(){var e=arguments;return fe(function(t){return ce(t,e)},t)})}),de=l(function(e,t){return t(e)}),ye=h(function(e,t,n){var r=e(t),o=e(n);return r<o?-1:r>o?1:0}),he=h(function(e,t,n){var r={};for(var o in n)r[o]=n[o];return r[e]=t,r}),me=u(function(e){return null==e}),ve=h(function e(t,n,r){if(0===t.length)return n;var o=t[0];if(t.length>1){var i=!me(r)&&F(o,r)?r[o]:q(t[1])?[]:{};n=e(Array.prototype.slice.call(t,1),n,i)}if(q(o)&&v(r)){var a=[].concat(r);return a[o]=n,a}return he(o,n,r)}),be=l(function(e,t){switch(e){case 0:return function(){return t.call(this)};case 1:return function(e){return t.call(this,e)};case 2:return function(e,n){return t.call(this,e,n)};case 3:return function(e,n,r){return t.call(this,e,n,r)};case 4:return function(e,n,r,o){return t.call(this,e,n,r,o)};case 5:return function(e,n,r,o,i){return t.call(this,e,n,r,o,i)};case 6:return function(e,n,r,o,i,a){return t.call(this,e,n,r,o,i,a)};case 7:return function(e,n,r,o,i,a,u){return t.call(this,e,n,r,o,i,a,u)};case 8:return function(e,n,r,o,i,a,u,l){return t.call(this,e,n,r,o,i,a,u,l)};case 9:return function(e,n,r,o,i,a,u,l,c){return t.call(this,e,n,r,o,i,a,u,l,c)};case 10:return function(e,n,r,o,i,a,u,l,c,s){return t.call(this,e,n,r,o,i,a,u,l,c,s)};default:throw new Error("First argument to nAry must be a non-negative integer no greater than ten")}}),ge=u(function(e){return be(2,e)});function we(e){var t=Object.prototype.toString.call(e);return"[object Function]"===t||"[object AsyncFunction]"===t||"[object GeneratorFunction]"===t||"[object AsyncGeneratorFunction]"===t}var Oe=l(function(e,t){var n=d(e,t);return d(e,function(){return R(ie,$(n,arguments[0]),Array.prototype.slice.call(arguments,1))})}),Ee=u(function(e){return Oe(e.length,e)}),Se=l(function(e,t){return we(e)?function(){return e.apply(this,arguments)&&t.apply(this,arguments)}:Ee(te)(e,t)}),_e=u(function(e){return d(e.length,e)}),Pe=_e(function(e){return e.apply(this,Array.prototype.slice.call(arguments,1))});function xe(e){return function t(n){for(var r,o,i,a=[],u=0,l=n.length;u<l;){if(j(n[u]))for(i=0,o=(r=e?t(n[u]):n[u]).length;i<o;)a[a.length]=r[i],i+=1;else a[a.length]=n[u];u+=1}return a}}var je=function(e){var t=function(e){return{"@@transducer/init":O.init,"@@transducer/result":function(t){return e["@@transducer/result"](t)},"@@transducer/step":function(t,n){var r=e["@@transducer/step"](t,n);return r["@@transducer/reduced"]?function(e){return{"@@transducer/value":e,"@@transducer/reduced":!0}}(r):r}}}(e);return{"@@transducer/init":O.init,"@@transducer/result":function(e){return t["@@transducer/result"](e)},"@@transducer/step":function(e,n){return j(n)?R(t,e,n):R(t,e,[n])}}},Ce=l(g(["fantasy-land/chain","chain"],l(function(e,t){return $(e,je(t))}),function(e,t){return"function"==typeof t?function(n){return e(t(n))(n)}:xe(!1)($(e,t))})),ke=h(function(e,t,n){if(e>t)throw new Error("min must not be greater than max in clamp(min, max, value)");return n<e?e:n>t?t:n});function Te(e){return new RegExp(e.source,(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.sticky?"y":"")+(e.unicode?"u":""))}var Me=u(function(e){return null===e?"Null":void 0===e?"Undefined":Object.prototype.toString.call(e).slice(8,-1)});function Ae(e,t,n,r){var o=function(o){for(var i=t.length,a=0;a<i;){if(e===t[a])return n[a];a+=1}for(var u in t[a+1]=e,n[a+1]=o,e)o[u]=r?Ae(e[u],t,n,!0):e[u];return o};switch(Me(e)){case"Object":return o({});case"Array":return o([]);case"Date":return new Date(e.valueOf());case"RegExp":return Te(e);default:return e}}var Ne=u(function(e){return null!=e&&"function"==typeof e.clone?e.clone():Ae(e,[],[],!0)}),Re=u(function(e){return function(t,n){return e(t,n)?-1:e(n,t)?1:0}}),De=u(function(e){return!e}),Ie=Ee(De);function Fe(e,t){return function(){return t.call(this,e.apply(this,arguments))}}function Le(e,t){return function(){var n=arguments.length;if(0===n)return t();var r=arguments[n-1];return v(r)||"function"!=typeof r[e]?t.apply(this,arguments):r[e].apply(r,Array.prototype.slice.call(arguments,0,n-1))}}var ze=h(Le("slice",function(e,t,n){return Array.prototype.slice.call(n,e,t)})),Ve=u(Le("tail",ze(1,1/0)));function We(){if(0===arguments.length)throw new Error("pipe requires at least one argument");return f(arguments[0].length,J(Fe,arguments[0],Ve(arguments)))}var Ue=u(function(e){return x(e)?e.split("").reverse().join(""):Array.prototype.slice.call(e,0).reverse()});function He(){if(0===arguments.length)throw new Error("compose requires at least one argument");return We.apply(this,Ue(arguments))}function Be(){if(0===arguments.length)throw new Error("composeK requires at least one argument");var e=Array.prototype.slice.call(arguments),t=e.pop();return He(He.apply(this,$(Ce,e)),t)}function $e(e,t){return function(){var n=this;return e.apply(n,arguments).then(function(e){return t.call(n,e)})}}function qe(){if(0===arguments.length)throw new Error("pipeP requires at least one argument");return f(arguments[0].length,J($e,arguments[0],Ve(arguments)))}function Ke(){if(0===arguments.length)throw new Error("composeP requires at least one argument");return qe.apply(this,Ue(arguments))}var Ye=K(0);function Xe(e){return e}var Qe=u(Xe),Ge=l(function(e,t){if(t.length<=0)return Qe;var n=Ye(t),r=Ve(t);return f(n.length,function(){return R(function(t,n){return e.call(this,n,t)},n.apply(this,arguments),r)})}),Je=l(function(e,t){return Ge.apply(this,[e,Ue(t)])});function Ze(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}function et(e,t,n){for(var r=0,o=n.length;r<o;){if(e(t,n[r]))return!0;r+=1}return!1}var tt="function"==typeof Object.is?Object.is:function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t};function nt(e,t,n,r){var o=Ze(e);function i(e,t){return rt(e,t,n.slice(),r.slice())}return!et(function(e,t){return!et(i,t,e)},Ze(t),o)}function rt(e,t,n,r){if(tt(e,t))return!0;var o=Me(e);if(o!==Me(t))return!1;if(null==e||null==t)return!1;if("function"==typeof e["fantasy-land/equals"]||"function"==typeof t["fantasy-land/equals"])return"function"==typeof e["fantasy-land/equals"]&&e["fantasy-land/equals"](t)&&"function"==typeof t["fantasy-land/equals"]&&t["fantasy-land/equals"](e);if("function"==typeof e.equals||"function"==typeof t.equals)return"function"==typeof e.equals&&e.equals(t)&&"function"==typeof t.equals&&t.equals(e);switch(o){case"Arguments":case"Array":case"Object":if("function"==typeof e.constructor&&"Promise"===function(e){var t=String(e).match(/^function (\w*)/);return null==t?"":t[1]}(e.constructor))return e===t;break;case"Boolean":case"Number":case"String":if(typeof e!=typeof t||!tt(e.valueOf(),t.valueOf()))return!1;break;case"Date":if(!tt(e.valueOf(),t.valueOf()))return!1;break;case"Error":return e.name===t.name&&e.message===t.message;case"RegExp":if(e.source!==t.source||e.global!==t.global||e.ignoreCase!==t.ignoreCase||e.multiline!==t.multiline||e.sticky!==t.sticky||e.unicode!==t.unicode)return!1}for(var i=n.length-1;i>=0;){if(n[i]===e)return r[i]===t;i-=1}switch(o){case"Map":return e.size===t.size&&nt(e.entries(),t.entries(),n.concat([e]),r.concat([t]));case"Set":return e.size===t.size&&nt(e.values(),t.values(),n.concat([e]),r.concat([t]));case"Arguments":case"Array":case"Object":case"Boolean":case"Number":case"String":case"Date":case"Error":case"RegExp":case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"ArrayBuffer":break;default:return!1}var a=B(e);if(a.length!==B(t).length)return!1;var u=n.concat([e]),l=r.concat([t]);for(i=a.length-1;i>=0;){var c=a[i];if(!F(c,t)||!rt(t[c],e[c],u,l))return!1;i-=1}return!0}var ot=l(function(e,t){return rt(e,t,[],[])});function it(e,t,n){var r,o;if("function"==typeof e.indexOf)switch(typeof t){case"number":if(0===t){for(r=1/t;n<e.length;){if(0===(o=e[n])&&1/o===r)return n;n+=1}return-1}if(t!=t){for(;n<e.length;){if("number"==typeof(o=e[n])&&o!=o)return n;n+=1}return-1}return e.indexOf(t,n);case"string":case"boolean":case"function":case"undefined":return e.indexOf(t,n);case"object":if(null===t)return e.indexOf(t,n)}for(;n<e.length;){if(ot(e[n],t))return n;n+=1}return-1}function at(e,t){return it(t,e,0)>=0}function ut(e){return'"'+e.replace(/\\/g,"\\\\").replace(/[\b]/g,"\\b").replace(/\f/g,"\\f").replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t").replace(/\v/g,"\\v").replace(/\0/g,"\\0").replace(/"/g,'\\"')+'"'}var lt=function(e){return(e<10?"0":"")+e},ct="function"==typeof Date.prototype.toISOString?function(e){return e.toISOString()}:function(e){return e.getUTCFullYear()+"-"+lt(e.getUTCMonth()+1)+"-"+lt(e.getUTCDate())+"T"+lt(e.getUTCHours())+":"+lt(e.getUTCMinutes())+":"+lt(e.getUTCSeconds())+"."+(e.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z"};function st(e){return function(){return!e.apply(this,arguments)}}function ft(e,t){for(var n=0,r=t.length,o=[];n<r;)e(t[n])&&(o[o.length]=t[n]),n+=1;return o}function pt(e){return"[object Object]"===Object.prototype.toString.call(e)}var dt=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.f(t)?this.xf["@@transducer/step"](e,t):e},e}(),yt=l(g(["filter"],l(function(e,t){return new dt(e,t)}),function(e,t){return pt(t)?R(function(n,r){return e(t[r])&&(n[r]=t[r]),n},{},B(t)):ft(e,t)})),ht=l(function(e,t){return yt(st(e),t)});function mt(e,t){var n=function(n){var r=t.concat([e]);return at(n,r)?"<Circular>":mt(n,r)},r=function(e,t){return P(function(t){return ut(t)+": "+n(e[t])},t.slice().sort())};switch(Object.prototype.toString.call(e)){case"[object Arguments]":return"(function() { return arguments; }("+P(n,e).join(", ")+"))";case"[object Array]":return"["+P(n,e).concat(r(e,ht(function(e){return/^\d+$/.test(e)},B(e)))).join(", ")+"]";case"[object Boolean]":return"object"==typeof e?"new Boolean("+n(e.valueOf())+")":e.toString();case"[object Date]":return"new Date("+(isNaN(e.valueOf())?n(NaN):ut(ct(e)))+")";case"[object Null]":return"null";case"[object Number]":return"object"==typeof e?"new Number("+n(e.valueOf())+")":1/e==-1/0?"-0":e.toString(10);case"[object String]":return"object"==typeof e?"new String("+n(e.valueOf())+")":ut(e);case"[object Undefined]":return"undefined";default:if("function"==typeof e.toString){var o=e.toString();if("[object Object]"!==o)return o}return"{"+r(e,B(e)).join(", ")+"}"}}var vt=u(function(e){return mt(e,[])}),bt=l(function(e,t){if(v(e)){if(v(t))return e.concat(t);throw new TypeError(vt(t)+" is not an array")}if(x(e)){if(x(t))return e+t;throw new TypeError(vt(t)+" is not a string")}if(null!=e&&we(e["fantasy-land/concat"]))return e["fantasy-land/concat"](t);if(null!=e&&we(e.concat))return e.concat(t);throw new TypeError(vt(e)+' does not have a method named "concat" or "fantasy-land/concat"')}),gt=u(function(e){return f(J(_,0,$(function(e){return e[0].length},e)),function(){for(var t=0;t<e.length;){if(e[t][0].apply(this,arguments))return e[t][1].apply(this,arguments);t+=1}})}),wt=l(function(e,t){if(e>10)throw new Error("Constructor with greater than ten arguments");return 0===e?function(){return new t}:_e(be(e,function(e,n,r,o,i,a,u,l,c,s){switch(arguments.length){case 1:return new t(e);case 2:return new t(e,n);case 3:return new t(e,n,r);case 4:return new t(e,n,r,o);case 5:return new t(e,n,r,o,i);case 6:return new t(e,n,r,o,i,a);case 7:return new t(e,n,r,o,i,a,u);case 8:return new t(e,n,r,o,i,a,u,l);case 9:return new t(e,n,r,o,i,a,u,l,c);case 10:return new t(e,n,r,o,i,a,u,l,c,s)}}))}),Ot=u(function(e){return wt(e.length,e)}),Et=l(at),St=l(function(e,t){return d(J(_,0,G("length",t)),function(){var n=arguments,r=this;return e.apply(r,P(function(e){return e.apply(r,n)},t))})}),_t=function(){function e(e,t,n,r){this.valueFn=e,this.valueAcc=t,this.keyFn=n,this.xf=r,this.inputs={}}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){var t;for(t in this.inputs)if(F(t,this.inputs)&&(e=this.xf["@@transducer/step"](e,this.inputs[t]))["@@transducer/reduced"]){e=e["@@transducer/value"];break}return this.inputs=null,this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){var n=this.keyFn(t);return this.inputs[n]=this.inputs[n]||[n,this.valueAcc],this.inputs[n][1]=this.valueFn(this.inputs[n][1],t),e},e}(),Pt=p(4,[],g([],p(4,[],function(e,t,n,r){return new _t(e,t,n,r)}),function(e,t,n,r){return R(function(r,o){var i=n(o);return r[i]=e(F(i,r)?r[i]:Ae(t,[],[],!1),o),r},{},r)})),xt=Pt(function(e,t){return e+1},0),jt=c(-1),Ct=l(function(e,t){return null==t||t!=t?e:t}),kt=h(function(e,t,n){var r=e(t),o=e(n);return r>o?-1:r<o?1:0});function Tt(e,t,n){var r,o=typeof e;switch(o){case"string":case"number":return 0===e&&1/e==-1/0?!!n._items["-0"]||(t&&(n._items["-0"]=!0),!1):null!==n._nativeSet?t?(r=n._nativeSet.size,n._nativeSet.add(e),n._nativeSet.size===r):n._nativeSet.has(e):o in n._items?e in n._items[o]||(t&&(n._items[o][e]=!0),!1):(t&&(n._items[o]={},n._items[o][e]=!0),!1);case"boolean":if(o in n._items){var i=e?1:0;return!!n._items[o][i]||(t&&(n._items[o][i]=!0),!1)}return t&&(n._items[o]=e?[!1,!0]:[!0,!1]),!1;case"function":return null!==n._nativeSet?t?(r=n._nativeSet.size,n._nativeSet.add(e),n._nativeSet.size===r):n._nativeSet.has(e):o in n._items?!!at(e,n._items[o])||(t&&n._items[o].push(e),!1):(t&&(n._items[o]=[e]),!1);case"undefined":return!!n._items[o]||(t&&(n._items[o]=!0),!1);case"object":if(null===e)return!!n._items.null||(t&&(n._items.null=!0),!1);default:return(o=Object.prototype.toString.call(e))in n._items?!!at(e,n._items[o])||(t&&n._items[o].push(e),!1):(t&&(n._items[o]=[e]),!1)}}var Mt=function(){function e(){this._nativeSet="function"==typeof Set?new Set:null,this._items={}}return e.prototype.add=function(e){return!Tt(e,!0,this)},e.prototype.has=function(e){return Tt(e,!1,this)},e}(),At=l(function(e,t){for(var n=[],r=0,o=e.length,i=t.length,a=new Mt,u=0;u<i;u+=1)a.add(t[u]);for(;r<o;)a.add(e[r])&&(n[n.length]=e[r]),r+=1;return n}),Nt=h(function(e,t,n){for(var r=[],o=0,i=t.length;o<i;)et(e,t[o],n)||et(e,t[o],r)||r.push(t[o]),o+=1;return r}),Rt=l(function(e,t){var n={};for(var r in t)n[r]=t[r];return delete n[e],n}),Dt=h(function(e,t,n){var r=Array.prototype.slice.call(n,0);return r.splice(e,t),r}),It=h(function(e,t,n){return m(e,ee(t),n)}),Ft=l(function e(t,n){switch(t.length){case 0:return n;case 1:return q(t[0])&&v(n)?Dt(t[0],1,n):Rt(t[0],n);default:var r=t[0],o=Array.prototype.slice.call(t,1);return null==n[r]?n:q(r)&&v(n)?It(r,e(o,n[r]),n):he(r,e(o,n[r]),n)}}),Lt=l(function(e,t){return e/t}),zt=function(){function e(e,t){this.xf=t,this.n=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.n>0?(this.n-=1,e):this.xf["@@transducer/step"](e,t)},e}(),Vt=l(g(["drop"],l(function(e,t){return new zt(e,t)}),function(e,t){return ze(Math.max(0,e),1/0,t)})),Wt=function(){function e(e,t){this.xf=t,this.n=e,this.i=0}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){this.i+=1;var n=0===this.n?e:this.xf["@@transducer/step"](e,t);return this.n>=0&&this.i>=this.n?w(n):n},e}(),Ut=l(g(["take"],l(function(e,t){return new Wt(e,t)}),function(e,t){return ze(0,e<0?1/0:e,t)}));var Ht=function(){function e(e,t){this.xf=t,this.pos=0,this.full=!1,this.acc=new Array(e)}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.acc=null,this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.full&&(e=this.xf["@@transducer/step"](e,this.acc[this.pos])),this.store(t),e},e.prototype.store=function(e){this.acc[this.pos]=e,this.pos+=1,this.pos===this.acc.length&&(this.pos=0,this.full=!0)},e}(),Bt=l(g([],l(function(e,t){return new Ht(e,t)}),function(e,t){return Ut(e<t.length?t.length-e:0,t)}));var $t=function(){function e(e,t){this.f=e,this.retained=[],this.xf=t}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.retained=null,this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)?this.retain(e,t):this.flush(e,t)},e.prototype.flush=function(e,t){return e=R(this.xf["@@transducer/step"],e,this.retained),this.retained=[],this.xf["@@transducer/step"](e,t)},e.prototype.retain=function(e,t){return this.retained.push(t),e},e}(),qt=l(g([],l(function(e,t){return new $t(e,t)}),function(e,t){for(var n=t.length-1;n>=0&&e(t[n]);)n-=1;return ze(0,n+1,t)})),Kt=function(){function e(e,t){this.xf=t,this.pred=e,this.lastValue=void 0,this.seenFirstValue=!1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){var n=!1;return this.seenFirstValue?this.pred(this.lastValue,t)&&(n=!0):this.seenFirstValue=!0,this.lastValue=t,n?e:this.xf["@@transducer/step"](e,t)},e}(),Yt=l(function(e,t){return new Kt(e,t)}),Xt=K(-1),Qt=l(g([],Yt,function(e,t){var n=[],r=1,o=t.length;if(0!==o)for(n[0]=t[0];r<o;)e(Xt(n),t[r])||(n[n.length]=t[r]),r+=1;return n})),Gt=u(g([],Yt(ot),Qt(ot))),Jt=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){if(this.f){if(this.f(t))return e;this.f=null}return this.xf["@@transducer/step"](e,t)},e}(),Zt=l(g(["dropWhile"],l(function(e,t){return new Jt(e,t)}),function(e,t){for(var n=0,r=t.length;n<r&&e(t[n]);)n+=1;return ze(n,1/0,t)})),en=l(function(e,t){return e||t}),tn=l(function(e,t){return we(e)?function(){return e.apply(this,arguments)||t.apply(this,arguments)}:Ee(en)(e,t)}),nn=u(function(e){return null!=e&&"function"==typeof e["fantasy-land/empty"]?e["fantasy-land/empty"]():null!=e&&null!=e.constructor&&"function"==typeof e.constructor["fantasy-land/empty"]?e.constructor["fantasy-land/empty"]():null!=e&&"function"==typeof e.empty?e.empty():null!=e&&null!=e.constructor&&"function"==typeof e.constructor.empty?e.constructor.empty():v(e)?[]:x(e)?"":pt(e)?{}:z(e)?function(){return arguments}():void 0}),rn=l(function(e,t){return Vt(e>=0?t.length-e:0,t)}),on=l(function(e,t){return ot(rn(e.length,t),e)}),an=h(function(e,t,n){return ot(e(t),e(n))}),un=h(function(e,t,n){return ot(t[e],n[e])}),ln=l(function e(t,n){var r,o,i,a=n instanceof Array?[]:{};for(o in n)i=typeof(r=t[o]),a[o]="function"===i?r(n[o]):r&&"object"===i?e(r,n[o]):n[o];return a}),cn=function(){function e(e,t){this.xf=t,this.f=e,this.found=!1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.found||(e=this.xf["@@transducer/step"](e,void 0)),this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)&&(this.found=!0,e=w(this.xf["@@transducer/step"](e,t))),e},e}(),sn=l(g(["find"],l(function(e,t){return new cn(e,t)}),function(e,t){for(var n=0,r=t.length;n<r;){if(e(t[n]))return t[n];n+=1}})),fn=function(){function e(e,t){this.xf=t,this.f=e,this.idx=-1,this.found=!1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.found||(e=this.xf["@@transducer/step"](e,-1)),this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.idx+=1,this.f(t)&&(this.found=!0,e=w(this.xf["@@transducer/step"](e,this.idx))),e},e}(),pn=l(g([],l(function(e,t){return new fn(e,t)}),function(e,t){for(var n=0,r=t.length;n<r;){if(e(t[n]))return n;n+=1}return-1})),dn=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.xf["@@transducer/result"](this.xf["@@transducer/step"](e,this.last))},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)&&(this.last=t),e},e}(),yn=l(g([],l(function(e,t){return new dn(e,t)}),function(e,t){for(var n=t.length-1;n>=0;){if(e(t[n]))return t[n];n-=1}})),hn=function(){function e(e,t){this.xf=t,this.f=e,this.idx=-1,this.lastIdx=-1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.xf["@@transducer/result"](this.xf["@@transducer/step"](e,this.lastIdx))},e.prototype["@@transducer/step"]=function(e,t){return this.idx+=1,this.f(t)&&(this.lastIdx=this.idx),e},e}(),mn=l(g([],l(function(e,t){return new hn(e,t)}),function(e,t){for(var n=t.length-1;n>=0;){if(e(t[n]))return n;n-=1}return-1})),vn=u(xe(!0)),bn=u(function(e){return d(e.length,function(t,n){var r=Array.prototype.slice.call(arguments,0);return r[0]=n,r[1]=t,e.apply(this,r)})}),gn=l(Le("forEach",function(e,t){for(var n=t.length,r=0;r<n;)e(t[r]),r+=1;return t})),wn=l(function(e,t){for(var n=B(t),r=0;r<n.length;){var o=n[r];e(t[o],o,t),r+=1}return t}),On=u(function(e){for(var t={},n=0;n<e.length;)t[e[n][0]]=e[n][1],n+=1;return t}),En=l(Le("groupBy",Pt(function(e,t){return null==e&&(e=[]),e.push(t),e},null))),Sn=l(function(e,t){for(var n=[],r=0,o=t.length;r<o;){for(var i=r+1;i<o&&e(t[i-1],t[i]);)i+=1;n.push(t.slice(r,i)),r=i}return n}),_n=l(function(e,t){return e>t}),Pn=l(function(e,t){return e>=t}),xn=l(function(e,t){if(0===e.length||me(t))return!1;for(var n=t,r=0;r<e.length;){if(me(n)||!F(e[r],n))return!1;n=n[e[r]],r+=1}return!0}),jn=l(function(e,t){return xn([e],t)}),Cn=l(function(e,t){return e in t}),kn=l(tt),Tn=h(function(e,t,n){return d(Math.max(e.length,t.length,n.length),function(){return e.apply(this,arguments)?t.apply(this,arguments):n.apply(this,arguments)})}),Mn=c(1),An=l(at),Nn=Pt(function(e,t){return t},null),Rn=l(function(e,t){return"function"!=typeof t.indexOf||v(t)?it(t,e,0):t.indexOf(e)}),Dn=ze(0,-1),In=h(function(e,t,n){return ft(function(t){return et(e,t,n)},t)}),Fn=h(function(e,t,n){e=e<n.length&&e>=0?e:n.length;var r=Array.prototype.slice.call(n,0);return r.splice(e,0,t),r}),Ln=h(function(e,t,n){return e=e<n.length&&e>=0?e:n.length,[].concat(Array.prototype.slice.call(n,0,e),t,Array.prototype.slice.call(n,e))}),zn=l(function(e,t){for(var n,r,o=new Mt,i=[],a=0;a<t.length;)n=e(r=t[a]),o.add(n)&&i.push(r),a+=1;return i}),Vn=zn(Qe),Wn=l(function(e,t){var n,r;return e.length>t.length?(n=e,r=t):(n=t,r=e),Vn(ft(bn(at)(n),r))}),Un=l(Le("intersperse",function(e,t){for(var n=[],r=0,o=t.length;r<o;)r===o-1?n.push(t[r]):n.push(t[r],e),r+=1;return n}));var Hn="function"==typeof Object.assign?Object.assign:function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),n=1,r=arguments.length;n<r;){var o=arguments[n];if(null!=o)for(var i in o)F(i,o)&&(t[i]=o[i]);n+=1}return t},Bn=l(function(e,t){var n={};return n[e]=t,n}),$n={"@@transducer/init":Array,"@@transducer/step":function(e,t){return e.push(t),e},"@@transducer/result":Xe},qn={"@@transducer/init":String,"@@transducer/step":function(e,t){return e+t},"@@transducer/result":Xe},Kn={"@@transducer/init":Object,"@@transducer/step":function(e,t){return Hn(e,j(t)?Bn(t[0],t[1]):t)},"@@transducer/result":Xe};var Yn=h(function(e,t,n){return b(e)?R(t(e),e["@@transducer/init"](),n):R(t(function(e){if(b(e))return e;if(j(e))return $n;if("string"==typeof e)return qn;if("object"==typeof e)return Kn;throw new Error("Cannot create transformer for "+e)}(e)),Ae(e,[],[],!1),n)}),Xn=u(function(e){for(var t=B(e),n=t.length,r=0,o={};r<n;){var i=t[r],a=e[i],u=F(a,o)?o[a]:o[a]=[];u[u.length]=i,r+=1}return o}),Qn=u(function(e){for(var t=B(e),n=t.length,r=0,o={};r<n;){var i=t[r];o[e[i]]=i,r+=1}return o}),Gn=l(function(e,t){return d(e+1,function(){var n=arguments[e];if(null!=n&&we(n[t]))return n[t].apply(n,Array.prototype.slice.call(arguments,0,e));throw new TypeError(vt(n)+' does not have a method named "'+t+'"')})}),Jn=l(function(e,t){return null!=t&&t.constructor===e||t instanceof e}),Zn=u(function(e){return null!=e&&ot(e,nn(e))}),er=Gn(1,"join"),tr=u(function(e){return St(function(){return Array.prototype.slice.call(arguments,0)},e)}),nr=u(function(e){var t,n=[];for(t in e)n[n.length]=t;return n}),rr=l(function(e,t){if("function"!=typeof t.lastIndexOf||v(t)){for(var n=t.length-1;n>=0;){if(ot(t[n],e))return n;n-=1}return-1}return t.lastIndexOf(e)});function or(e){return"[object Number]"===Object.prototype.toString.call(e)}var ir=u(function(e){return null!=e&&or(e.length)?e.length:NaN}),ar=l(function(e,t){return function(n){return function(r){return $(function(e){return t(e,r)},n(e(r)))}}}),ur=u(function(e){return ar(K(e),It(e))}),lr=u(function(e){return ar(X(e),ve(e))}),cr=u(function(e){return ar(Q(e),he(e))}),sr=l(function(e,t){return e<t}),fr=l(function(e,t){return e<=t}),pr=h(function(e,t,n){for(var r=0,o=n.length,i=[],a=[t];r<o;)a=e(a[0],n[r]),i[r]=a[1],r+=1;return[a[0],i]}),dr=h(function(e,t,n){for(var r=n.length-1,o=[],i=[t];r>=0;)i=e(i[0],n[r]),o[r]=i[1],r-=1;return[i[0],o]}),yr=l(function(e,t){return R(function(n,r){return n[r]=e(t[r],r,t),n},{},B(t))}),hr=l(function(e,t){return t.match(e)||[]}),mr=l(function(e,t){return q(e)?!q(t)||t<1?NaN:(e%t+t)%t:NaN}),vr=h(function(e,t,n){return e(n)>e(t)?n:t}),br=J(c,0),gr=u(function(e){return br(e)/e.length}),wr=u(function(e){var t=e.length;if(0===t)return NaN;var n=2-t%2,r=(t-n)/2;return gr(Array.prototype.slice.call(e,0).sort(function(e,t){return e<t?-1:e>t?1:0}).slice(r,r+n))}),Or=l(function(e,t){var n={};return f(t.length,function(){var r=e.apply(this,arguments);return F(r,n)||(n[r]=t.apply(this,arguments)),n[r]})}),Er=l(function(e,t){return Hn({},e,t)}),Sr=u(function(e){return Hn.apply(null,[{}].concat(e))}),_r=h(function(e,t,n){var r,o={};for(r in t)F(r,t)&&(o[r]=F(r,n)?e(r,t[r],n[r]):t[r]);for(r in n)F(r,n)&&!F(r,o)&&(o[r]=n[r]);return o}),Pr=h(function e(t,n,r){return _r(function(n,r,o){return pt(r)&&pt(o)?e(t,r,o):t(n,r,o)},n,r)}),xr=l(function(e,t){return Pr(function(e,t,n){return t},e,t)}),jr=l(function(e,t){return Pr(function(e,t,n){return n},e,t)}),Cr=h(function(e,t,n){return Pr(function(t,n,r){return e(n,r)},t,n)}),kr=l(function(e,t){return Hn({},t,e)}),Tr=l(function(e,t){return Hn({},e,t)}),Mr=h(function(e,t,n){return _r(function(t,n,r){return e(n,r)},t,n)}),Ar=l(function(e,t){return t<e?t:e}),Nr=h(function(e,t,n){return e(n)<e(t)?n:t}),Rr=l(function(e,t){return e%t}),Dr=h(function(e,t,n){var r=n.length,o=n.slice(),i=e<0?r+e:e,a=t<0?r+t:t,u=o.splice(i,1);return i<0||i>=n.length||a<0||a>=n.length?n:[].concat(o.slice(0,a)).concat(u).concat(o.slice(a,n.length))}),Ir=l(function(e,t){return e*t}),Fr=u(function(e){return-e}),Lr=l(function(e,t){return S(st(e),t)}),zr=u(function(e){return d(e<0?1:e+1,function(){return K(e,arguments)})}),Vr=h(function(e,t,n){return e(t(n))});var Wr=u(function(e){return[e]}),Ur=l(function(e,t){for(var n={},r={},o=0,i=e.length;o<i;)r[e[o]]=1,o+=1;for(var a in t)r.hasOwnProperty(a)||(n[a]=t[a]);return n}),Hr=u(function(e){var t,n=!1;return f(e.length,function(){return n?t:(n=!0,t=e.apply(this,arguments))})});function Br(e,t){if(null==t||!we(t.then))throw new TypeError("`"+e+"` expected a Promise, received "+mt(t,[]))}var $r=l(function(e,t){return Br("otherwise",t),t.then(null,e)}),qr=function(e){return{value:e,map:function(t){return qr(t(e))}}},Kr=h(function(e,t,n){return e(function(e){return qr(t(e))})(n).value}),Yr=l(function(e,t){return[e,t]});function Xr(e){return l(function(t,n){return f(Math.max(0,t.length-n.length),function(){return t.apply(this,e(n,arguments))})})}var Qr=Xr(s),Gr=Xr(bn(s)),Jr=tr([yt,ht]),Zr=h(function(e,t,n){return ot(X(e,n),t)}),eo=h(function(e,t,n){return Ct(e,X(t,n))}),to=h(function(e,t,n){return e(X(t,n))}),no=l(function(e,t){for(var n={},r=0;r<e.length;)e[r]in t&&(n[e[r]]=t[e[r]]),r+=1;return n}),ro=l(function(e,t){for(var n={},r=0,o=e.length;r<o;){var i=e[r];n[i]=t[i],r+=1}return n}),oo=l(function(e,t){var n={};for(var r in t)e(t[r],r,t)&&(n[r]=t[r]);return n});function io(){if(0===arguments.length)throw new Error("pipeK requires at least one argument");return Be.apply(this,Ue(arguments))}var ao=l(function(e,t){return s([e],t)}),uo=J(Ir,1),lo=l(function(e,t){return d(t.length,function(){for(var n=[],r=0;r<t.length;)n.push(t[r].call(this,arguments[r])),r+=1;return e.apply(this,n.concat(Array.prototype.slice.call(arguments,t.length)))})}),co=lo(P,[ro,Qe]),so=h(function(e,t,n){return ot(t,n[e])}),fo=h(function(e,t,n){return Jn(e,n[t])}),po=h(function(e,t,n){return eo(e,[t],n)}),yo=h(function(e,t,n){return e(n[t])}),ho=l(function(e,t){return e.map(function(e){return X([e],t)})}),mo=l(function(e,t){if(!or(e)||!or(t))throw new TypeError("Both arguments to range must be numbers");for(var n=[],r=e;r<t;)n.push(r),r+=1;return n}),vo=h(function(e,t,n){for(var r=n.length-1;r>=0;)t=e(n[r],t),r-=1;return t}),bo=p(4,[],function(e,t,n,r){return R(function(n,r){return e(n,r)?t(n,r):w(n)},n,r)}),go=u(w),wo=l(function(e,t){var n,r=Number(t),o=0;if(r<0||isNaN(r))throw new RangeError("n must be a non-negative number");for(n=new Array(r);o<r;)n[o]=e(o),o+=1;return n}),Oo=l(function(e,t){return wo(ee(e),t)}),Eo=h(function(e,t,n){return n.replace(e,t)}),So=h(function(e,t,n){for(var r=0,o=n.length,i=[t];r<o;)t=e(t,n[r]),i[r+1]=t,r+=1;return i}),_o=l(function(e,t){return"function"==typeof t.sequence?t.sequence(e):vo(function(e,t){return ie($(ao,e),t)},e([]),t)}),Po=h(function(e,t,n){return Kr(e,ee(t),n)}),xo=l(function(e,t){return Array.prototype.slice.call(t,0).sort(e)}),jo=l(function(e,t){return Array.prototype.slice.call(t,0).sort(function(t,n){var r=e(t),o=e(n);return r<o?-1:r>o?1:0})}),Co=l(function(e,t){return Array.prototype.slice.call(t,0).sort(function(t,n){for(var r=0,o=0;0===r&&o<e.length;)r=e[o](t,n),o+=1;return r})}),ko=Gn(1,"split"),To=l(function(e,t){return[ze(0,e,t),ze(e,ir(t),t)]}),Mo=l(function(e,t){if(e<=0)throw new Error("First argument to splitEvery must be a positive integer");for(var n=[],r=0;r<t.length;)n.push(ze(r,r+=e,t));return n}),Ao=l(function(e,t){for(var n=0,r=t.length,o=[];n<r&&!e(t[n]);)o.push(t[n]),n+=1;return[o,Array.prototype.slice.call(t,n)]}),No=l(function(e,t){return ot(Ut(e.length,t),e)}),Ro=l(function(e,t){return Number(e)-Number(t)}),Do=l(function(e,t){return bt(At(e,t),At(t,e))}),Io=h(function(e,t,n){return bt(Nt(e,t,n),Nt(e,n,t))}),Fo=l(function(e,t){for(var n=t.length-1;n>=0&&e(t[n]);)n-=1;return ze(n+1,1/0,t)}),Lo=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.f(t)?this.xf["@@transducer/step"](e,t):w(e)},e}(),zo=l(g(["takeWhile"],l(function(e,t){return new Lo(e,t)}),function(e,t){for(var n=0,r=t.length;n<r&&e(t[n]);)n+=1;return ze(0,n,t)})),Vo=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.f(t),this.xf["@@transducer/step"](e,t)},e}(),Wo=l(g([],l(function(e,t){return new Vo(e,t)}),function(e,t){return e(t),t}));var Uo=l(function(e,t){if(!function(e){return"[object RegExp]"===Object.prototype.toString.call(e)}(e))throw new TypeError("‘test’ requires a value of type RegExp as its first argument; received "+vt(e));return Te(e).test(t)}),Ho=l(function(e,t){return Br("andThen",t),t.then(e)}),Bo=Gn(0,"toLowerCase"),$o=u(function(e){var t=[];for(var n in e)F(n,e)&&(t[t.length]=[n,e[n]]);return t}),qo=u(function(e){var t=[];for(var n in e)t[t.length]=[n,e[n]];return t}),Ko=Gn(0,"toUpperCase"),Yo=d(4,function(e,t,n,r){return R(e("function"==typeof t?k(t):t),n,r)}),Xo=u(function(e){for(var t=0,n=[];t<e.length;){for(var r=e[t],o=0;o<r.length;)void 0===n[o]&&(n[o]=[]),n[o].push(r[o]),o+=1;t+=1}return n}),Qo=h(function(e,t,n){return"function"==typeof n["fantasy-land/traverse"]?n["fantasy-land/traverse"](t,e):_o(e,$(t,n))}),Go="\t\n\v\f\r   ᠎              \u2028\u2029\ufeff",Jo=u("function"==typeof String.prototype.trim&&!Go.trim()&&"​".trim()?function(e){return e.trim()}:function(e){var t=new RegExp("^["+Go+"]["+Go+"]*"),n=new RegExp("["+Go+"]["+Go+"]*$");return e.replace(t,"").replace(n,"")}),Zo=l(function(e,t){return f(e.length,function(){try{return e.apply(this,arguments)}catch(e){return t.apply(this,s([e],arguments))}})}),ei=u(function(e){return function(){return e(Array.prototype.slice.call(arguments,0))}}),ti=u(function(e){return be(1,e)}),ni=l(function(e,t){return d(e,function(){for(var n,r=1,o=t,i=0;r<=e&&"function"==typeof o;)n=r===e?arguments.length:i+o.length,o=o.apply(this,Array.prototype.slice.call(arguments,i,n)),r+=1,i=n;return o})}),ri=l(function(e,t){for(var n=e(t),r=[];n&&n.length;)r[r.length]=n[0],n=e(n[1]);return r}),oi=l(He(Vn,s)),ii=l(function(e,t){for(var n,r=0,o=t.length,i=[];r<o;)et(e,n=t[r],i)||(i[i.length]=n),r+=1;return i}),ai=h(function(e,t,n){return ii(e,s(t,n))}),ui=h(function(e,t,n){return e(n)?n:t(n)}),li=Ce(Xe),ci=h(function(e,t,n){for(var r=n;!e(r);)r=t(r);return r}),si=u(function(e){var t,n=[];for(t in e)n[n.length]=e[t];return n}),fi=function(e){return{value:e,"fantasy-land/map":function(){return this}}},pi=l(function(e,t){return e(fi)(t).value}),di=h(function(e,t,n){return e(n)?t(n):n}),yi=l(function(e,t){for(var n in e)if(F(n,e)&&!e[n](t[n]))return!1;return!0}),hi=l(function(e,t){return yi($(ot,e),t)}),mi=l(function(e,t){return ht(bn(at)(e),t)}),vi=l(function(e,t){return Boolean(!e^!t)}),bi=l(function(e,t){for(var n,r=0,o=e.length,i=t.length,a=[];r<o;){for(n=0;n<i;)a[a.length]=[e[r],t[n]],n+=1;r+=1}return a}),gi=l(function(e,t){for(var n=[],r=0,o=Math.min(e.length,t.length);r<o;)n[r]=[e[r],t[r]],r+=1;return n}),wi=l(function(e,t){for(var n=0,r=Math.min(e.length,t.length),o={};n<r;)o[e[n]]=t[n],n+=1;return o}),Oi=h(function(e,t,n){for(var r=[],o=0,i=Math.min(t.length,n.length);o<i;)r[o]=e(t[o],n[o]),o+=1;return r}),Ei=u(function(e){return d(e.length,function(){var t=arguments;return function(){return e.apply(this,t)}})});n.d(t,"F",function(){return r}),n.d(t,"T",function(){return o}),n.d(t,"__",function(){return i}),n.d(t,"add",function(){return c}),n.d(t,"addIndex",function(){return y}),n.d(t,"adjust",function(){return m}),n.d(t,"all",function(){return S}),n.d(t,"allPass",function(){return Z}),n.d(t,"always",function(){return ee}),n.d(t,"and",function(){return te}),n.d(t,"any",function(){return re}),n.d(t,"anyPass",function(){return oe}),n.d(t,"ap",function(){return ie}),n.d(t,"aperture",function(){return ue}),n.d(t,"append",function(){return le}),n.d(t,"apply",function(){return ce}),n.d(t,"applySpec",function(){return pe}),n.d(t,"applyTo",function(){return de}),n.d(t,"ascend",function(){return ye}),n.d(t,"assoc",function(){return he}),n.d(t,"assocPath",function(){return ve}),n.d(t,"binary",function(){return ge}),n.d(t,"bind",function(){return T}),n.d(t,"both",function(){return Se}),n.d(t,"call",function(){return Pe}),n.d(t,"chain",function(){return Ce}),n.d(t,"clamp",function(){return ke}),n.d(t,"clone",function(){return Ne}),n.d(t,"comparator",function(){return Re}),n.d(t,"complement",function(){return Ie}),n.d(t,"compose",function(){return He}),n.d(t,"composeK",function(){return Be}),n.d(t,"composeP",function(){return Ke}),n.d(t,"composeWith",function(){return Je}),n.d(t,"concat",function(){return bt}),n.d(t,"cond",function(){return gt}),n.d(t,"construct",function(){return Ot}),n.d(t,"constructN",function(){return wt}),n.d(t,"contains",function(){return Et}),n.d(t,"converge",function(){return St}),n.d(t,"countBy",function(){return xt}),n.d(t,"curry",function(){return _e}),n.d(t,"curryN",function(){return d}),n.d(t,"dec",function(){return jt}),n.d(t,"defaultTo",function(){return Ct}),n.d(t,"descend",function(){return kt}),n.d(t,"difference",function(){return At}),n.d(t,"differenceWith",function(){return Nt}),n.d(t,"dissoc",function(){return Rt}),n.d(t,"dissocPath",function(){return Ft}),n.d(t,"divide",function(){return Lt}),n.d(t,"drop",function(){return Vt}),n.d(t,"dropLast",function(){return Bt}),n.d(t,"dropLastWhile",function(){return qt}),n.d(t,"dropRepeats",function(){return Gt}),n.d(t,"dropRepeatsWith",function(){return Qt}),n.d(t,"dropWhile",function(){return Zt}),n.d(t,"either",function(){return tn}),n.d(t,"empty",function(){return nn}),n.d(t,"endsWith",function(){return on}),n.d(t,"eqBy",function(){return an}),n.d(t,"eqProps",function(){return un}),n.d(t,"equals",function(){return ot}),n.d(t,"evolve",function(){return ln}),n.d(t,"filter",function(){return yt}),n.d(t,"find",function(){return sn}),n.d(t,"findIndex",function(){return pn}),n.d(t,"findLast",function(){return yn}),n.d(t,"findLastIndex",function(){return mn}),n.d(t,"flatten",function(){return vn}),n.d(t,"flip",function(){return bn}),n.d(t,"forEach",function(){return gn}),n.d(t,"forEachObjIndexed",function(){return wn}),n.d(t,"fromPairs",function(){return On}),n.d(t,"groupBy",function(){return En}),n.d(t,"groupWith",function(){return Sn}),n.d(t,"gt",function(){return _n}),n.d(t,"gte",function(){return Pn}),n.d(t,"has",function(){return jn}),n.d(t,"hasIn",function(){return Cn}),n.d(t,"hasPath",function(){return xn}),n.d(t,"head",function(){return Ye}),n.d(t,"identical",function(){return kn}),n.d(t,"identity",function(){return Qe}),n.d(t,"ifElse",function(){return Tn}),n.d(t,"inc",function(){return Mn}),n.d(t,"includes",function(){return An}),n.d(t,"indexBy",function(){return Nn}),n.d(t,"indexOf",function(){return Rn}),n.d(t,"init",function(){return Dn}),n.d(t,"innerJoin",function(){return In}),n.d(t,"insert",function(){return Fn}),n.d(t,"insertAll",function(){return Ln}),n.d(t,"intersection",function(){return Wn}),n.d(t,"intersperse",function(){return Un}),n.d(t,"into",function(){return Yn}),n.d(t,"invert",function(){return Xn}),n.d(t,"invertObj",function(){return Qn}),n.d(t,"invoker",function(){return Gn}),n.d(t,"is",function(){return Jn}),n.d(t,"isEmpty",function(){return Zn}),n.d(t,"isNil",function(){return me}),n.d(t,"join",function(){return er}),n.d(t,"juxt",function(){return tr}),n.d(t,"keys",function(){return B}),n.d(t,"keysIn",function(){return nr}),n.d(t,"last",function(){return Xt}),n.d(t,"lastIndexOf",function(){return rr}),n.d(t,"length",function(){return ir}),n.d(t,"lens",function(){return ar}),n.d(t,"lensIndex",function(){return ur}),n.d(t,"lensPath",function(){return lr}),n.d(t,"lensProp",function(){return cr}),n.d(t,"lift",function(){return Ee}),n.d(t,"liftN",function(){return Oe}),n.d(t,"lt",function(){return sr}),n.d(t,"lte",function(){return fr}),n.d(t,"map",function(){return $}),n.d(t,"mapAccum",function(){return pr}),n.d(t,"mapAccumRight",function(){return dr}),n.d(t,"mapObjIndexed",function(){return yr}),n.d(t,"match",function(){return hr}),n.d(t,"mathMod",function(){return mr}),n.d(t,"max",function(){return _}),n.d(t,"maxBy",function(){return vr}),n.d(t,"mean",function(){return gr}),n.d(t,"median",function(){return wr}),n.d(t,"memoizeWith",function(){return Or}),n.d(t,"merge",function(){return Er}),n.d(t,"mergeAll",function(){return Sr}),n.d(t,"mergeDeepLeft",function(){return xr}),n.d(t,"mergeDeepRight",function(){return jr}),n.d(t,"mergeDeepWith",function(){return Cr}),n.d(t,"mergeDeepWithKey",function(){return Pr}),n.d(t,"mergeLeft",function(){return kr}),n.d(t,"mergeRight",function(){return Tr}),n.d(t,"mergeWith",function(){return Mr}),n.d(t,"mergeWithKey",function(){return _r}),n.d(t,"min",function(){return Ar}),n.d(t,"minBy",function(){return Nr}),n.d(t,"modulo",function(){return Rr}),n.d(t,"move",function(){return Dr}),n.d(t,"multiply",function(){return Ir}),n.d(t,"nAry",function(){return be}),n.d(t,"negate",function(){return Fr}),n.d(t,"none",function(){return Lr}),n.d(t,"not",function(){return De}),n.d(t,"nth",function(){return K}),n.d(t,"nthArg",function(){return zr}),n.d(t,"o",function(){return Vr}),n.d(t,"objOf",function(){return Bn}),n.d(t,"of",function(){return Wr}),n.d(t,"omit",function(){return Ur}),n.d(t,"once",function(){return Hr}),n.d(t,"or",function(){return en}),n.d(t,"otherwise",function(){return $r}),n.d(t,"over",function(){return Kr}),n.d(t,"pair",function(){return Yr}),n.d(t,"partial",function(){return Qr}),n.d(t,"partialRight",function(){return Gr}),n.d(t,"partition",function(){return Jr}),n.d(t,"path",function(){return X}),n.d(t,"paths",function(){return Y}),n.d(t,"pathEq",function(){return Zr}),n.d(t,"pathOr",function(){return eo}),n.d(t,"pathSatisfies",function(){return to}),n.d(t,"pick",function(){return no}),n.d(t,"pickAll",function(){return ro}),n.d(t,"pickBy",function(){return oo}),n.d(t,"pipe",function(){return We}),n.d(t,"pipeK",function(){return io}),n.d(t,"pipeP",function(){return qe}),n.d(t,"pipeWith",function(){return Ge}),n.d(t,"pluck",function(){return G}),n.d(t,"prepend",function(){return ao}),n.d(t,"product",function(){return uo}),n.d(t,"project",function(){return co}),n.d(t,"prop",function(){return Q}),n.d(t,"propEq",function(){return so}),n.d(t,"propIs",function(){return fo}),n.d(t,"propOr",function(){return po}),n.d(t,"propSatisfies",function(){return yo}),n.d(t,"props",function(){return ho}),n.d(t,"range",function(){return mo}),n.d(t,"reduce",function(){return J}),n.d(t,"reduceBy",function(){return Pt}),n.d(t,"reduceRight",function(){return vo}),n.d(t,"reduceWhile",function(){return bo}),n.d(t,"reduced",function(){return go}),n.d(t,"reject",function(){return ht}),n.d(t,"remove",function(){return Dt}),n.d(t,"repeat",function(){return Oo}),n.d(t,"replace",function(){return Eo}),n.d(t,"reverse",function(){return Ue}),n.d(t,"scan",function(){return So}),n.d(t,"sequence",function(){return _o}),n.d(t,"set",function(){return Po}),n.d(t,"slice",function(){return ze}),n.d(t,"sort",function(){return xo}),n.d(t,"sortBy",function(){return jo}),n.d(t,"sortWith",function(){return Co}),n.d(t,"split",function(){return ko}),n.d(t,"splitAt",function(){return To}),n.d(t,"splitEvery",function(){return Mo}),n.d(t,"splitWhen",function(){return Ao}),n.d(t,"startsWith",function(){return No}),n.d(t,"subtract",function(){return Ro}),n.d(t,"sum",function(){return br}),n.d(t,"symmetricDifference",function(){return Do}),n.d(t,"symmetricDifferenceWith",function(){return Io}),n.d(t,"tail",function(){return Ve}),n.d(t,"take",function(){return Ut}),n.d(t,"takeLast",function(){return rn}),n.d(t,"takeLastWhile",function(){return Fo}),n.d(t,"takeWhile",function(){return zo}),n.d(t,"tap",function(){return Wo}),n.d(t,"test",function(){return Uo}),n.d(t,"andThen",function(){return Ho}),n.d(t,"times",function(){return wo}),n.d(t,"toLower",function(){return Bo}),n.d(t,"toPairs",function(){return $o}),n.d(t,"toPairsIn",function(){return qo}),n.d(t,"toString",function(){return vt}),n.d(t,"toUpper",function(){return Ko}),n.d(t,"transduce",function(){return Yo}),n.d(t,"transpose",function(){return Xo}),n.d(t,"traverse",function(){return Qo}),n.d(t,"trim",function(){return Jo}),n.d(t,"tryCatch",function(){return Zo}),n.d(t,"type",function(){return Me}),n.d(t,"unapply",function(){return ei}),n.d(t,"unary",function(){return ti}),n.d(t,"uncurryN",function(){return ni}),n.d(t,"unfold",function(){return ri}),n.d(t,"union",function(){return oi}),n.d(t,"unionWith",function(){return ai}),n.d(t,"uniq",function(){return Vn}),n.d(t,"uniqBy",function(){return zn}),n.d(t,"uniqWith",function(){return ii}),n.d(t,"unless",function(){return ui}),n.d(t,"unnest",function(){return li}),n.d(t,"until",function(){return ci}),n.d(t,"update",function(){return It}),n.d(t,"useWith",function(){return lo}),n.d(t,"values",function(){return se}),n.d(t,"valuesIn",function(){return si}),n.d(t,"view",function(){return pi}),n.d(t,"when",function(){return di}),n.d(t,"where",function(){return yi}),n.d(t,"whereEq",function(){return hi}),n.d(t,"without",function(){return mi}),n.d(t,"xor",function(){return vi}),n.d(t,"xprod",function(){return bi}),n.d(t,"zip",function(){return gi}),n.d(t,"zipObj",function(){return wi}),n.d(t,"zipWith",function(){return Oi}),n.d(t,"thunkify",function(){return Ei})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.fixControlledValue=w,t.resolveOnChange=O,t.getInputClassName=E,t.default=void 0;var r=p(n(0)),o=s(n(1)),i=s(n(30)),a=p(n(79)),u=n(6),l=s(n(35)),c=s(n(43));function s(e){return e&&e.__esModule?e:{default:e}}function f(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return f=function(){return e},e}function p(e){if(e&&e.__esModule)return e;if(null===e||"object"!==d(e)&&"function"!=typeof e)return{default:e};var t=f();if(t&&t.has(e))return t.get(e);var n={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var i=r?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(n,o,i):n[o]=e[o]}return n.default=e,t&&t.set(e,n),n}function d(e){"@babel/helpers - typeof";return(d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function y(){return(y=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function h(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function m(e,t){return(m=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function v(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}();return function(){var n,r=b(e);if(t){var o=b(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===d(t)||"function"==typeof t))return t;return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function b(e){return(b=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function g(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function w(e){return void 0===e||null===e?"":e}function O(e,t,n){if(n){var r=t;if("click"===t.type){(r=Object.create(t)).target=e,r.currentTarget=e;var o=e.value;return e.value="",n(r),void(e.value=o)}n(r)}}function E(e,t,n,r){var i;return(0,o.default)(e,(g(i={},"".concat(e,"-sm"),"small"===t),g(i,"".concat(e,"-lg"),"large"===t),g(i,"".concat(e,"-disabled"),n),g(i,"".concat(e,"-rtl"),"rtl"===r),i))}var S=function(){var e=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&m(e,t)}(n,r.Component);var t=v(n);function n(e){var u;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),(u=t.call(this,e)).direction="ltr",u.focus=function(){u.input.focus()},u.saveClearableInput=function(e){u.clearableInput=e},u.saveInput=function(e){u.input=e},u.onFocus=function(e){var t=u.props.onFocus;u.setState({focused:!0}),t&&t(e)},u.onBlur=function(e){var t=u.props.onBlur;u.setState({focused:!1}),t&&t(e)},u.handleReset=function(e){u.setValue("",function(){u.focus()}),O(u.input,e,u.props.onChange)},u.renderInput=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},a=u.props,l=a.className,c=a.addonBefore,s=a.addonAfter,f=a.size,p=a.disabled,d=(0,i.default)(u.props,["prefixCls","onPressEnter","addonBefore","addonAfter","prefix","suffix","allowClear","defaultValue","size","inputType"]);return r.createElement("input",y({autoComplete:n.autoComplete},d,{onChange:u.handleChange,onFocus:u.onFocus,onBlur:u.onBlur,onKeyDown:u.handleKeyDown,className:(0,o.default)(E(e,f||t,p,u.direction),g({},l,l&&!c&&!s)),ref:u.saveInput}))},u.clearPasswordValueAttribute=function(){u.removePasswordTimeout=setTimeout(function(){u.input&&"password"===u.input.getAttribute("type")&&u.input.hasAttribute("value")&&u.input.removeAttribute("value")})},u.handleChange=function(e){u.setValue(e.target.value,u.clearPasswordValueAttribute),O(u.input,e,u.props.onChange)},u.handleKeyDown=function(e){var t=u.props,n=t.onPressEnter,r=t.onKeyDown;13===e.keyCode&&n&&n(e),r&&r(e)},u.renderComponent=function(e){var t=e.getPrefixCls,n=e.direction,o=e.input,i=u.state,c=i.value,s=i.focused,f=t("input",u.props.prefixCls);return u.direction=n,r.createElement(l.default.Consumer,null,function(e){return r.createElement(a.default,y({size:e},u.props,{prefixCls:f,inputType:"input",value:w(c),element:u.renderInput(f,e,o),handleReset:u.handleReset,ref:u.saveClearableInput,direction:n,focused:s,triggerFocus:u.focus}))})};var c=void 0===e.value?e.defaultValue:e.value;return u.state={value:c,focused:!1,prevValue:e.value},u}return function(e,t,n){t&&h(e.prototype,t),n&&h(e,n)}(n,[{key:"componentDidMount",value:function(){this.clearPasswordValueAttribute()}},{key:"componentDidUpdate",value:function(){}},{key:"getSnapshotBeforeUpdate",value:function(e){return(0,a.hasPrefixSuffix)(e)!==(0,a.hasPrefixSuffix)(this.props)&&(0,c.default)(this.input!==document.activeElement,"Input","When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ"),null}},{key:"componentWillUnmount",value:function(){this.removePasswordTimeout&&clearTimeout(this.removePasswordTimeout)}},{key:"blur",value:function(){this.input.blur()}},{key:"select",value:function(){this.input.select()}},{key:"setValue",value:function(e,t){void 0===this.props.value&&this.setState({value:e},t)}},{key:"render",value:function(){return r.createElement(u.ConfigConsumer,null,this.renderComponent)}}],[{key:"getDerivedStateFromProps",value:function(e,t){var n=t.prevValue,r={prevValue:e.value};return void 0===e.value&&n===e.value||(r.value=e.value),r}}]),n}();return e.defaultProps={type:"text"},e}();t.default=S},function(e,t,n){"use strict";n.r(t);var r=n(8),o=n.n(r);t.default=function(e,t){for(var n=o()({},e),r=0;r<t.length;r++)delete n[t[r]];return n}},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var r=n(25);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){var r=n(17),o=n(21),i=n(100),a=n(27),u=n(19),l=function(e,t,n){var c,s,f,p=e&l.F,d=e&l.G,y=e&l.S,h=e&l.P,m=e&l.B,v=e&l.W,b=d?o:o[t]||(o[t]={}),g=b.prototype,w=d?r:y?r[t]:(r[t]||{}).prototype;for(c in d&&(n=t),n)(s=!p&&w&&void 0!==w[c])&&u(b,c)||(f=s?w[c]:n[c],b[c]=d&&"function"!=typeof w[c]?n[c]:m&&s?i(f,r):v&&w[c]==f?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(f):h&&"function"==typeof f?i(Function.call,f):f,h&&((b.virtual||(b.virtual={}))[c]=f,e&l.R&&g&&!g[c]&&a(g,c,f)))};l.F=1,l.G=2,l.S=4,l.P=8,l.B=16,l.W=32,l.U=64,l.R=128,e.exports=l},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createAjaxRequest=void 0;var r=n(227),o=function(e,t){return{body:(0,r.stringify)({action:e,nonce:wcmlMultiCurrency.nonce,data:JSON.stringify(t)})}},i={currencyForLang:function(e){var t=e.isEnabled,n=e.currencyCode,r=e.languageCode;return o("wcml_update_currency_lang",{value:t?1:0,code:n,lang:r})},defaultCurrencyForLang:function(e){var t=e.languageCode,n=e.currencyCode;return o("wcml_update_default_currency",{code:n,lang:t})},deleteCurrency:function(e){var t=e.currencyCode;return o("wcml_delete_currency",{code:t})},saveCurrency:function(e){return o("wcml_save_currency",{currency_options:e})},setCurrencyMode:function(e){return o("wcml_set_currency_mode",{mode:e})},setMaxMindKey:function(e){return o("wcml_set_max_mind_key",{MaxMindKey:e})}};t.createAjaxRequest=function(e){if(!i[e])throw new Error("The endpoint "+e+" is not defined");var t=(0,r.createAjax)();return{fetching:t.fetching,send:function(n){return t.doFetch(i[e](n))}}}},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.SizeContextProvider=void 0;var o=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var n={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var u=o?Object.getOwnPropertyDescriptor(e,a):null;u&&(u.get||u.set)?Object.defineProperty(n,a,u):n[a]=e[a]}n.default=e,t&&t.set(e,n);return n}(n(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}var a=o.createContext(void 0);t.SizeContextProvider=function(e){var t=e.children,n=e.size;return o.createElement(a.Consumer,null,function(e){return o.createElement(a.Provider,{value:n||e},t)})};var u=a;t.default=u},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.triggerModeChange=t.triggerActiveCurrenciesChange=t.validateRate=t.getCountryLabel=t.getCurrencySymbol=t.getCurrencyLabel=t.getSmallFormattedPrice=t.getFormattedPricePreview=t.capitalize=void 0;var r=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(n(28));t.capitalize=function(e){return e[0].toUpperCase()+e.slice(1)},t.getFormattedPricePreview=function(e){return o("1","234","0")(e)},t.getSmallFormattedPrice=function(e){return o("","99","9")(e)};var o=function(e,t,n){return function(r){var o=i(r.code);return a(e,t,r.position).replace(/__SYMBOL__/,o.symbol).replace(/__THOUSAND_SEP__/,e?r.thousand_sep:"").replace(/__DECIMAL_SEP__/,r.num_decimals>0?r.decimal_sep:"").replace(/__DECIMALS_NUMBER__/,n.repeat(r.num_decimals))}},i=function(e){return wcmlMultiCurrency.allCurrencies.filter(function(t){return t.code===e})[0]},a=(t.getCurrencyLabel=r.pipe(i,r.prop("label")),t.getCurrencySymbol=r.pipe(i,r.prop("symbol")),t.getCountryLabel=r.pipe(function(e){return wcmlMultiCurrency.allCountries.filter(function(t){return t.code===e})[0]},r.prop("label")),function(e,t,n){switch(n){case"left":return"__SYMBOL__"+e+"__THOUSAND_SEP__"+t+"__DECIMAL_SEP____DECIMALS_NUMBER__";case"right":return e+"__THOUSAND_SEP__"+t+"__DECIMAL_SEP____DECIMALS_NUMBER____SYMBOL__";case"left_space":return"__SYMBOL__ "+e+"__THOUSAND_SEP__"+t+"__DECIMAL_SEP____DECIMALS_NUMBER__";case"right_space":return e+"__THOUSAND_SEP__"+t+"__DECIMAL_SEP____DECIMALS_NUMBER__ __SYMBOL__"}});t.validateRate=r.allPass([r.pipe(parseFloat,isNaN,r.not),isFinite,r.gt(r.__,0)]),t.triggerActiveCurrenciesChange=function(e){e.currencyData=i(e.currency.code),document.dispatchEvent(new CustomEvent("wcmlActiveCurrenciesChange",{detail:e}))},t.triggerModeChange=function(e){document.dispatchEvent(new CustomEvent("wcmlCurrencyModeChange"),{detail:e})}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t){var n=0,r=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+r).toString(36))}},function(e,t){e.exports=!0},function(e,t,n){var r=n(97),o=n(64);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var r=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==l(e)&&"function"!=typeof e)return{default:e};var t=u();if(t&&t.has(e))return t.get(e);var n={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var i=r?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(n,o,i):n[o]=e[o]}n.default=e,t&&t.set(e,n);return n}(n(0)),o=a(n(234)),i=a(n(101));function a(e){return e&&e.__esModule?e:{default:e}}function u(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return u=function(){return e},e}function l(e){"@babel/helpers - typeof";return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function c(){return(c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function s(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function p(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}();return function(){var n,r=d(e);if(t){var o=d(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===l(t)||"function"==typeof t))return t;return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function d(e){return(d=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var y=function(){var e=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}(n,r.Component);var t=p(n);function n(){return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),t.apply(this,arguments)}return function(e,t,n){t&&s(e.prototype,t),n&&s(e,n)}(n,[{key:"getLocale",value:function(){var e=this.props,t=e.componentName,n=e.defaultLocale||o.default[t||"global"],r=this.context,i=t&&r?r[t]:{};return c(c({},"function"==typeof n?n():n),i||{})}},{key:"getLocaleCode",value:function(){var e=this.context,t=e&&e.locale;return e&&e.exist&&!t?o.default.locale:t}},{key:"render",value:function(){return this.props.children(this.getLocale(),this.getLocaleCode(),this.context)}}]),n}();return e.defaultProps={componentName:"global"},e.contextType=i.default,e}();t.default=y},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"resetWarned",{enumerable:!0,get:function(){return o.resetWarned}}),t.default=void 0;var o=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var n={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var u=o?Object.getOwnPropertyDescriptor(e,a):null;u&&(u.get||u.set)?Object.defineProperty(n,a,u):n[a]=e[a]}n.default=e,t&&t.set(e,n);return n}(n(104));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}t.default=function(e,t,n){(0,o.default)(e,"[antd: ".concat(t,"] ").concat(n))}},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.replaceElement=u,t.cloneElement=function(e,t){return u(e,e,t)},t.isValidElement=void 0;var o=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var n={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if(Object.prototype.hasOwnProperty.call(e,a)){var u=o?Object.getOwnPropertyDescriptor(e,a):null;u&&(u.get||u.set)?Object.defineProperty(n,a,u):n[a]=e[a]}n.default=e,t&&t.set(e,n);return n}(n(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}var a=o.isValidElement;function u(e,t,n){return a(e)?o.cloneElement(e,"function"==typeof n?n():n):t}t.isValidElement=a},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){"use strict";
1
+ !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=266)}([function(e,t,n){"use strict";e.exports=n(264)},function(e,t,n){var r;
2
  /*!
3
  Copyright (c) 2017 Jed Watson.
4
  Licensed under the MIT License (MIT), see
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
+ !function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var i=typeof r;if("string"===i||"number"===i)e.push(r);else if(Array.isArray(r)&&r.length){var a=o.apply(null,r);a&&e.push(a)}else if("object"===i)for(var u in r)n.call(r,u)&&r[u]&&e.push(u)}}return e.join(" ")}void 0!==e&&e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()},function(e,t,n){"use strict";n.d(t,"b",function(){return u});var r={};function o(e,t){0}function i(e,t){0}function a(e,t,n){t||r[n]||(e(!1,n),r[n]=!0)}function u(e,t){a(i,e,t)}t.a=function(e,t){a(o,e,t)}},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),e.exports=n(263)},function(e,t,n){"use strict";var r={MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,QUESTION_MARK:63,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,SLASH:191,APOSTROPHE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,WIN_IME:229,isTextModifyingKeyEvent:function(e){var t=e.keyCode;if(e.altKey&&!e.ctrlKey||e.metaKey||t>=r.F1&&t<=r.F12)return!1;switch(t){case r.ALT:case r.CAPS_LOCK:case r.CONTEXT_MENU:case r.CTRL:case r.DOWN:case r.END:case r.ESC:case r.HOME:case r.INSERT:case r.LEFT:case r.MAC_FF_META:case r.META:case r.NUMLOCK:case r.NUM_CENTER:case r.PAGE_DOWN:case r.PAGE_UP:case r.PAUSE:case r.PRINT_SCREEN:case r.RIGHT:case r.SHIFT:case r.UP:case r.WIN_KEY:case r.WIN_KEY_RIGHT:return!1;default:return!0}},isCharacterKey:function(e){if(e>=r.ZERO&&e<=r.NINE)return!0;if(e>=r.NUM_ZERO&&e<=r.NUM_MULTIPLY)return!0;if(e>=r.A&&e<=r.Z)return!0;if(-1!==window.navigator.userAgent.indexOf("WebKit")&&0===e)return!0;switch(e){case r.SPACE:case r.QUESTION_MARK:case r.NUM_PLUS:case r.NUM_MINUS:case r.NUM_PERIOD:case r.NUM_DIVISION:case r.SEMICOLON:case r.DASH:case r.EQUALS:case r.COMMA:case r.PERIOD:case r.SLASH:case r.APOSTROPHE:case r.SINGLE_QUOTE:case r.OPEN_SQUARE_BRACKET:case r.BACKSLASH:case r.CLOSE_SQUARE_BRACKET:return!0;default:return!1}}};t.a=r},function(e,t,n){e.exports=n(249)()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ConfigConsumer",{enumerable:!0,get:function(){return u.ConfigConsumer}}),Object.defineProperty(t,"ConfigContext",{enumerable:!0,get:function(){return u.ConfigContext}}),t.default=t.configConsumerProps=void 0;var r=s(n(0)),o=n(117),i=s(n(243)),a=function(e){return e&&e.__esModule?e:{default:e}}(n(46)),u=n(238),l=n(29);function c(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return c=function(){return e},e}function s(e){if(e&&e.__esModule)return e;if(null===e||"object"!==f(e)&&"function"!=typeof e)return{default:e};var t=c();if(t&&t.has(e))return t.get(e);var n={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var i=r?Object.getOwnPropertyDescriptor(e,o):null;i&&(i.get||i.set)?Object.defineProperty(n,o,i):n[o]=e[o]}return n.default=e,t&&t.set(e,n),n}function f(e){"@babel/helpers - typeof";return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function p(){return(p=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function d(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function y(e,t){return(y=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function h(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}();return function(){var n,r=m(e);if(t){var o=m(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return function(e,t){if(t&&("object"===f(t)||"function"==typeof t))return t;return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(this,n)}}function m(e){return(m=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}t.configConsumerProps=["getTargetContainer","getPopupContainer","rootPrefixCls","getPrefixCls","renderEmpty","csp","autoInsertSpaceInButton","locale","pageHeader"];var v=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&y(e,t)}(n,r.Component);var t=h(n);function n(){var e;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,n),(e=t.apply(this,arguments)).getPrefixClsWrapper=function(t){return function(n,r){var o=e.props.prefixCls;if(r)return r;var i=o||t.getPrefixCls("");return n?"".concat(i,"-").concat(n):i}},e.renderProvider=function(t,n){var a=e.props,c=a.children,s=a.getTargetContainer,f=a.getPopupContainer,d=a.renderEmpty,y=a.csp,h=a.autoInsertSpaceInButton,m=a.form,v=a.input,b=a.locale,g=a.pageHeader,w=a.componentSize,O=a.direction,E=a.space,S=p(p({},t),{getPrefixCls:e.getPrefixClsWrapper(t),csp:y,autoInsertSpaceInButton:h,locale:b||n,direction:O,space:E});s&&(S.getTargetContainer=s),f&&(S.getPopupContainer=f),d&&(S.renderEmpty=d),g&&(S.pageHeader=g),v&&(S.input=v);var _=c,P={};return b&&b.Form&&b.Form.defaultValidateMessages&&(P=b.Form.defaultValidateMessages),m&&m.validateMessages&&(P=p(p({},P),m.validateMessages)),Object.keys(P).length>0&&(_=r.createElement(o.FormProvider,{validateMessages:P},c)),r.createElement(l.SizeContextProvider,{size:w},r.createElement(u.ConfigContext.Provider,{value:S},r.createElement(i.default,{locale:b||n,_ANT_MARK__:i.ANT_MARK},_)))},e}return function(e,t,n){t&&d(e.prototype,t),n&&d(e,n)}(n,[{key:"render",value:function(){var e=this;return r.createElement(a.default,null,function(t,n,o){return r.createElement(u.ConfigConsumer,null,function(t){return e.renderProvider(t,o)})})}}]),n}();t.default=v},function(e,t,n){"use strict";t.__esModule=!0;var r=function(e){return e&&e.__esModule?e:{default:e}}(n(227));t.default=r.default||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.useStore=t.getStore=t.getStoreAction=t.getStoreProperty=t.getCurrencyIndex=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=n(81),i=n(39),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}(n(23)),u=n(38);function l(e){return function(){var t=e.apply(this,arguments);return new Promise(function(e,n){return function r(o,i){try{var a=t[o](i),u=a.value}catch(e){return void n(e)}if(!a.done)return Promise.resolve(u).then(function(e){r("next",e)},function(e){r("throw",e)});e(u)}("next")})}}t.default=function(e){var t=e.activeCurrencies,n=e.allCurrencies,s=e.allCountries,f=e.languages,p=e.gateways,d=e.mode,y=e.maxMindKeyExist,h=e.isStandalone,m=e.isAutoRateEnabled;return(0,o.createStore)({activeCurrencies:t,allCurrencies:n,allCountries:s,languages:f,gateways:p,mode:d,isMaxMindRegistered:y,isValidatingMaxMindRegistration:null,errorOnMaxMindRegistration:null,isStandalone:h,modalCurrency:null,updating:!1,isPresettingRate:!1,isAutoRateEnabled:m,setDefaultCurrencyForLang:(0,o.action)(function(e,t){var n=e.languages.findIndex(function(e){return e.code===t.language}),r=e.languages[n];r.defaultCurrency=t.currency,e.languages[n]=r}),getCurrencyIndex:(0,o.action)(function(e,t){e.activeCurrencies.findIndex(function(e){return e.code===t})}),enableCurrencyForLang:(0,o.action)(function(e,t){var n=c(e.activeCurrencies)(t.currency),o=e.activeCurrencies[n],i=t.enable?1:0;o.languages=r({},o.languages,function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}({},t.language,i)),e.activeCurrencies[n]=o}),deleteCurrency:(0,o.action)(function(e,t){var n=c(e.activeCurrencies)(t),o=r({},e.activeCurrencies[n]);e.activeCurrencies.splice(n,1),(0,i.triggerActiveCurrenciesChange)({action:"remove",currency:o})}),setModalCurrency:(0,o.action)(function(e,t){e.modalCurrency=e.setInitialGatewayCurrency(t,e.activeCurrencies)}),setInitialGatewayCurrency:function(e,t){var n=function(n){return void 0===n.currency||function(e){return t.find(function(t){return t.code===e})}(n.currency)||(n=r({},n,{currency:e.code})),n};return e&&e.gatewaysSettings&&Object.keys(e.gatewaysSettings).map(function(t){e.gatewaysSettings[t]=n(e.gatewaysSettings[t])}),e},saveModalCurrency:(0,o.action)(function(e){var t=c(e.activeCurrencies)(e.modalCurrency.code);if(t<0){var n=r({},e.modalCurrency,{isNew:!1});e.activeCurrencies.push(n),(0,i.triggerActiveCurrenciesChange)({action:"add",currency:n})}else e.activeCurrencies[t]=e.modalCurrency}),newCurrencies:(0,o.computed)(function(e){var t=e.activeCurrencies.map(function(e){return e.code});return e.allCurrencies.filter(function(e){return!t.includes(e.code)})}),defaultCurrency:(0,o.computed)(function(e){return e.activeCurrencies.filter(function(e){return e.isDefault})[0]}),setUpdating:(0,o.action)(function(e,t){e.updating=t}),setMode:(0,o.action)(function(e,t){e.mode=t,(0,i.triggerModeChange)({mode:t})}),setMaxMindKeyExist:(0,o.action)(function(e){e.maxMindKeyExist=!0}),registerMaxMindKey:(0,o.thunk)(function(){var e=l(regeneratorRuntime.mark(function e(t,n){var r,o,i,l,c;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return t._setErrorOnMaxMindRegistration(null),t._setIsValidatingMaxMindRegistration(!0),e.next=4,(0,u.doAjaxForSetMaxMindKey)(n);case 4:r=e.sent,o=r.data,t._setIsValidatingMaxMindRegistration(!1),i=a.prop("success"),l=a.prop("data"),i(o)?t._setIsMaxMindRegistered():(c=l(o),t._setErrorOnMaxMindRegistration(c||"Error"));case 10:case"end":return e.stop()}},e,void 0)}));return function(t,n){return e.apply(this,arguments)}}()),_setErrorOnMaxMindRegistration:(0,o.action)(function(e,t){e.errorOnMaxMindRegistration=t}),_setIsValidatingMaxMindRegistration:(0,o.action)(function(e,t){e.isValidatingMaxMindRegistration=t}),_setIsMaxMindRegistered:(0,o.action)(function(e){e.isMaxMindRegistered=!0}),presetExchangeRate:(0,o.thunk)(function(){var e=l(regeneratorRuntime.mark(function e(t,n,o){var i,a;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!o.getState().isAutoRateEnabled){e.next=8;break}return t._setIsPresettingRate(!0),e.next=4,(0,u.doAjaxForGetAutoExchangeRate)(n);case 4:i=e.sent,a=i.data,t._setIsPresettingRate(!1),t.setModalCurrency(r({},o.getState().modalCurrency,{rate:a.success?a.data:"invalid"}));case 8:case"end":return e.stop()}},e,void 0)}));return function(t,n,r){return e.apply(this,arguments)}}()),_setIsPresettingRate:(0,o.action)(function(e,t){e.isPresettingRate=t}),isValidModalRate:(0,o.computed)(function(e){var t=e.modalCurrency?e.modalCurrency.rate:"1";return(0,i.validateRate)(t)})})};var c=t.getCurrencyIndex=function(e){return function(t){return a.findIndex(a.propEq("code",t))(e)}},s=t.getStoreProperty=function(e){return(0,o.useStoreState)(a.path(Array.isArray(e)?e:[e]))},f=t.getStoreAction=function(e){return(0,o.useStoreActions)(a.prop(e))};t.getStore=function(e,t){return[s(e),f(t)]},t.useStore=function(e){return[s(e),f("set"+(0,i.capitalize)(e)),f("reset"+(0,i.capitalize)(e))]}},function(e,t,n){(function(t){for(var r=n(247),o="undefined"==typeof window?t:window,i=["moz","webkit"],a="AnimationFrame",u=o["request"+a],l=o["cancel"+a]||o["cancelRequest"+a],c=0;!u&&c<i.length;c++)u=o[i[c]+"Request"+a],l=o[i[c]+"Cancel"+a]||o[i[c]+"CancelRequest"+a];if(!u||!l){var s=0,f=0,p=[];u=function(e){if(0===p.length){var t=r(),n=Math.max(0,1e3/60-(t-s));s=n+t,setTimeout(function(){var e=p.slice(0);p.length=0;for(var t=0;t<e.length;t++)if(!e[t].cancelled)try{e[t].callback(s)}catch(e){setTimeout(function(){throw e},0)}},Math.round(n))}return p.push({handle:++f,callback:e,cancelled:!1}),f},l=function(e){for(var t=0;t<p.length;t++)p[t].handle===e&&(p[t].cancelled=!0)}}e.exports=function(e){return u.call(o,e)},e.exports.cancel=function(){l.apply(o,arguments)},e.exports.polyfill=function(e){e||(e=o),e.requestAnimationFrame=u,e.cancelAnimationFrame=l}}).call(this,n(49))},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var t=s();if(t&&t.has(e))return t.get(e);var n={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var a=o?Object.getOwnPropertyDescriptor(e,i):null;a&&(a.get||a.set)?Object.defineProperty(n,i,a):n[i]=e[i]}n.default=e,t&&t.set(e,n);return n}(n(0)),i=c(n(1)),a=c(n(90)),u=n(183),l=n(59);function c(e){return e&&e.__esModule?e:{default:e}}function s(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return s=function(){return e},e}function f(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(e)))return;var n=[],r=!0,o=!1,i=void 0;try{for(var a,u=e[Symbol.iterator]();!(r=(a=u.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(e){o=!0,i=e}finally{try{r||null==u.return||u.return()}finally{if(o)throw i}}return n}(e,t)||function(e,t){if(!e)return;if("string"==typeof e)return p(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);"Object"===n&&e.constructor&&(n=e.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return p(e,t)}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function d(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(0,u.setTwoToneColor)("#1890ff");var y=o.forwardRef(function(e,t){var n=e.className,r=e.icon,u=e.spin,c=e.rotate,s=e.tabIndex,p=e.onClick,y=e.twoToneColor,h=d(e,["className","icon","spin","rotate","tabIndex","onClick","twoToneColor"]),m=(0,i.default)("anticon",function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}({},"anticon-".concat(r.name),Boolean(r.name)),n),v=(0,i.default)({"anticon-spin":!!u||"loading"===r.name}),b=s;void 0===b&&p&&(b=-1);var g=c?{msTransform:"rotate(".concat(c,"deg)"),transform:"rotate(".concat(c,"deg)")}:void 0,w=f((0,l.normalizeTwoToneColors)(y),2),O=w[0],E=w[1];return o.createElement("span",Object.assign({role:"img","aria-label":r.name},h,{ref:t,tabIndex:b,onClick:p,className:m}),o.createElement(a.default,{className:v,icon:r,primaryColor:O,secondaryColor:E,style:g}))});y.displayName="AntdIcon",y.getTwoToneColor=u.getTwoToneColor,y.setTwoToneColor=u.setTwoToneColor;var h=y;t.default=h},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Spinner=t.allowBreakRules=t.getTooltip=t.InputRow=t.SelectRow=void 0;var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},o=u(n(0)),i=u(n(107)),a=n(74);function u(e){return e&&e.__esModule?e:{default:e}}t.SelectRow=function(e){var t=e.onChange,n=e.label,i=e.attrs,a=e.tooltip,u=e.children,c=e.afterSelect,s=void 0===c?null:c;return o.default.createElement("div",{className:"wpml-form-row"},o.default.createElement("label",{htmlFor:i.id},n,l(a)),o.default.createElement("select",r({onChange:t},i),u),s)},t.InputRow=function(e){var t=e.onChange,n=e.label,i=e.attrs,a=e.tooltip;return o.default.createElement("div",{className:"wpml-form-row"},o.default.createElement("label",{htmlFor:i.id},n,l(a)),o.default.createElement("input",r({},i,{onChange:t})))};var l=t.getTooltip=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"otgs-ico-help";return e&&o.default.createElement(i.default,{getPopupContainer:a.getPopupContainer,title:c(e)}," ",o.default.createElement("i",{className:"wcml-tip "+t}))},c=t.allowBreakRules=function(e){return o.default.createElement("div",{dangerouslySetInnerHTML:{__html:e}})};t.Spinner=function(e){var t=e.style,n=r({visibility:"visible"},t);return o.default.createElement("span",{className:"spinner",style:n})}},function(e,t,n){"use strict";function r(e){"@babel/helpers - typeof";return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return function(e){t.forEach(function(t){!function(e,t){"function"==typeof e?e(t):"object"===r(e)&&e&&"current"in e&&(e.current=t)}(t,e)})}}function i(e){return!(e.type&&e.type.prototype&&!e.type.prototype.render)&&!("function"==typeof e&&e.prototype&&!e.prototype.render)}n.d(t,"a",function(){return o}),n.d(t,"b",function(){return i})},function(e,t,n){"use strict";n.d(t,"a",function(){return i});var r=n(3),o=n.n(r);function i(e){return e instanceof HTMLElement?e:o.a.findDOMNode(e)}},function(e,t,n){"use strict";(function(e){var r;n.d(t,"a",function(){return $}),n.d(t,"b",function(){return q}),n.d(t,"c",function(){return u}),n.d(t,"d",function(){return c}),n.d(t,"e",function(){return B});var o="undefined"!=typeof Symbol?Symbol("immer-nothing"):((r={})["immer-nothing"]=!0,r),i="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-draftable"):"__$immer_draftable",a="undefined"!=typeof Symbol&&Symbol.for?Symbol.for("immer-state"):"__$immer_state";function u(e){return!!e&&!!e[a]}function l(e){if(!e||"object"!=typeof e)return!1;if(Array.isArray(e))return!0;var t=Object.getPrototypeOf(e);return!t||t===Object.prototype||(!!e[i]||!!e.constructor[i])}function c(e){if(e&&e[a])return e[a].base}var s=Object.assign||function(e,t){for(var n in t)h(t,n)&&(e[n]=t[n]);return e},f="undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Object.getOwnPropertyNames;function p(e,t){if(void 0===t&&(t=!1),Array.isArray(e))return e.slice();var n=Object.create(Object.getPrototypeOf(e));return f(e).forEach(function(r){if(r!==a){var o=Object.getOwnPropertyDescriptor(e,r),i=o.value;o.get&&t&&(i=o.get.call(e)),o.enumerable?n[r]=i:t&&Object.defineProperty(n,r,{value:i,writable:!0,configurable:!0})}}),n}function d(e,t){if(Array.isArray(e))for(var n=0;n<e.length;n++)t(n,e[n],e);else f(e).forEach(function(n){return t(n,e[n],e)})}function y(e,t){var n=Object.getOwnPropertyDescriptor(e,t);return!!n&&n.enumerable}function h(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function m(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}var v=function(e){this.drafts=[],this.parent=e,this.canAutoFreeze=!0,this.patches=null};function b(e){e[a].revoke()}v.prototype.usePatches=function(e){e&&(this.patches=[],this.inversePatches=[],this.patchListener=e)},v.prototype.revoke=function(){this.leave(),this.drafts.forEach(b),this.drafts=null},v.prototype.leave=function(){this===v.current&&(v.current=this.parent)},v.current=null,v.enter=function(){return this.current=new v(this.current)};var g={};function w(e,t){var n=Array.isArray(e),r=x(e);d(r,function(t){!function(e,t,n){var r=g[t];r?r.enumerable=n:g[t]=r={configurable:!0,enumerable:n,get:function(){return function(e,t){j(e);var n=S(E(e),t);if(e.finalizing)return n;if(n===S(e.base,t)&&l(n))return P(e),e.copy[t]=w(n,e);return n}(this[a],t)},set:function(e){!function(e,t,n){if(j(e),e.assigned[t]=!0,!e.modified){if(m(n,S(E(e),t)))return;_(e),P(e)}e.copy[t]=n}(this[a],t,e)}};Object.defineProperty(e,t,r)}(r,t,n||y(e,t))});var o=t?t.scope:v.current;return function(e,t,n){Object.defineProperty(e,t,{value:n,enumerable:!1,writable:!0})}(r,a,{scope:o,modified:!1,finalizing:!1,finalized:!1,assigned:{},parent:t,base:e,draft:r,copy:null,revoke:O,revoked:!1}),o.drafts.push(r),r}function O(){this.revoked=!0}function E(e){return e.copy||e.base}function S(e,t){var n=e[a];if(n&&!n.finalizing){n.finalizing=!0;var r=e[t];return n.finalizing=!1,r}return e[t]}function _(e){e.modified||(e.modified=!0,e.parent&&_(e.parent))}function P(e){e.copy||(e.copy=x(e.base))}function x(e){var t=e&&e[a];if(t){t.finalizing=!0;var n=p(t.draft,!0);return t.finalizing=!1,n}return p(e)}function j(e){if(!0===e.revoked)throw new Error("Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? "+JSON.stringify(E(e)))}function C(e){for(var t=e.length-1;t>=0;t--){var n=e[t][a];n.modified||(Array.isArray(n.base)?T(n)&&_(n):k(n)&&_(n))}}function k(e){for(var t=e.base,n=e.draft,r=Object.keys(n),o=r.length-1;o>=0;o--){var i=r[o],u=t[i];if(void 0===u&&!h(t,i))return!0;var l=n[i],c=l&&l[a];if(c?c.base!==u:!m(l,u))return!0}return r.length!==Object.keys(t).length}function T(e){var t=e.draft;if(t.length!==e.base.length)return!0;var n=Object.getOwnPropertyDescriptor(t,t.length-1);return!(!n||n.get)}var M=Object.freeze({willFinalize:function(e,t,n){e.drafts.forEach(function(e){e[a].finalizing=!0}),n?u(t)&&t[a].scope===e&&C(e.drafts):(e.patches&&function e(t){if(t&&"object"==typeof t){var n=t[a];if(n){var r=n.base,o=n.draft,i=n.assigned;if(Array.isArray(t)){if(T(n)){if(_(n),i.length=!0,o.length<r.length)for(var u=o.length;u<r.length;u++)i[u]=!1;else for(var l=r.length;l<o.length;l++)i[l]=!0;for(var c=0;c<o.length;c++)void 0===i[c]&&e(o[c])}}else Object.keys(o).forEach(function(t){void 0!==r[t]||h(r,t)?i[t]||e(o[t]):(i[t]=!0,_(n))}),Object.keys(r).forEach(function(e){void 0!==o[e]||h(o,e)||(i[e]=!1,_(n))})}}}(e.drafts[0]),C(e.drafts))},createProxy:w});function A(e,t){var n=t?t.scope:v.current,r={scope:n,modified:!1,finalized:!1,assigned:{},parent:t,base:e,draft:null,drafts:{},copy:null,revoke:null},o=Array.isArray(e)?Proxy.revocable([r],R):Proxy.revocable(r,N),i=o.revoke,a=o.proxy;return r.draft=a,r.revoke=i,n.drafts.push(a),a}var N={get:function(e,t){if(t===a)return e;var n=e.drafts;if(!e.modified&&h(n,t))return n[t];var r=D(e)[t];if(e.finalized||!l(r))return r;if(e.modified){if(r!==I(e.base,t))return r;n=e.copy}return n[t]=A(r,e)},has:function(e,t){return t in D(e)},ownKeys:function(e){return Reflect.ownKeys(D(e))},set:function(e,t,n){if(!e.modified){var r=I(e.base,t),o=n?m(r,n)||n===e.drafts[t]:m(r,n)&&t in e.base;if(o)return!0;F(e)}return e.assigned[t]=!0,e.copy[t]=n,!0},deleteProperty:function(e,t){(void 0!==I(e.base,t)||t in e.base)&&(e.assigned[t]=!1,F(e));e.copy&&delete e.copy[t];return!0},getOwnPropertyDescriptor:function(e,t){var n=D(e),r=Reflect.getOwnPropertyDescriptor(n,t);r&&(r.writable=!0,r.configurable=!Array.isArray(n)||"length"!==t);return r},defineProperty:function(){throw new Error("Object.defineProperty() cannot be used on an Immer draft")},getPrototypeOf:function(e){return Object.getPrototypeOf(e.base)},setPrototypeOf:function(){throw new Error("Object.setPrototypeOf() cannot be used on an Immer draft")}},R={};function D(e){return e.copy||e.base}function I(e,t){var n=e[a],r=Reflect.getOwnPropertyDescriptor(n?D(n):e,t);return r&&r.value}function F(e){e.modified||(e.modified=!0,e.copy=s(p(e.base),e.drafts),e.drafts=null,e.parent&&F(e.parent))}d(N,function(e,t){R[e]=function(){return arguments[0]=arguments[0][0],t.apply(this,arguments)}}),R.deleteProperty=function(e,t){if(isNaN(parseInt(t)))throw new Error("Immer only supports deleting array indices");return N.deleteProperty.call(this,e[0],t)},R.set=function(e,t,n){if("length"!==t&&isNaN(parseInt(t)))throw new Error("Immer only supports setting array indices and the 'length' property");return N.set.call(this,e[0],t,n)};var L=Object.freeze({willFinalize:function(){},createProxy:A});function z(e,t,n,r){Array.isArray(e.base)?function(e,t,n,r){var o,i,a=e.base,u=e.copy,l=e.assigned;u.length<a.length&&(a=(o=[u,a])[0],u=o[1],n=(i=[r,n])[0],r=i[1]);var c=u.length-a.length,s=0;for(;a[s]===u[s]&&s<a.length;)++s;var f=a.length;for(;f>s&&a[f-1]===u[f+c-1];)--f;for(var p=s;p<f;++p)if(l[p]&&u[p]!==a[p]){var d=t.concat([p]);n.push({op:"replace",path:d,value:u[p]}),r.push({op:"replace",path:d,value:a[p]})}for(var y=f!=a.length,h=n.length,m=f+c-1;m>=f;--m){var v=t.concat([m]);n[h+m-f]={op:"add",path:v,value:u[m]},y&&r.push({op:"remove",path:v})}y||r.push({op:"replace",path:t.concat(["length"]),value:a.length})}(e,t,n,r):function(e,t,n,r){var o=e.base,i=e.copy;d(e.assigned,function(e,a){var u=o[e],l=i[e],c=a?e in o?"replace":"add":"remove";if(u!==l||"replace"!==c){var s=t.concat(e);n.push("remove"===c?{op:c,path:s}:{op:c,path:s,value:l}),r.push("add"===c?{op:"remove",path:s}:"remove"===c?{op:"add",path:s,value:u}:{op:"replace",path:s,value:u})}})}(e,t,n,r)}function V(e,t){for(var n=0;n<t.length;n++){var r=t[n],o=r.path;if(0===o.length&&"replace"===r.op)e=r.value;else{for(var i=e,a=0;a<o.length-1;a++)if(!(i=i[o[a]])||"object"!=typeof i)throw new Error("Cannot apply patch, path doesn't resolve: "+o.join("/"));var u=o[o.length-1];switch(r.op){case"replace":i[u]=r.value;break;case"add":Array.isArray(i)?i.splice(u,0,r.value):i[u]=r.value;break;case"remove":Array.isArray(i)?i.splice(u,1):delete i[u];break;default:throw new Error("Unsupported patch operation: "+r.op)}}}return e}var W={useProxies:"undefined"!=typeof Proxy&&"undefined"!=typeof Reflect,autoFreeze:void 0===e&&"verifyMinified"===function(){}.name,onAssign:null,onDelete:null,onCopy:null},U=function(e){s(this,W,e),this.setUseProxies(this.useProxies),this.produce=this.produce.bind(this)};U.prototype.produce=function(e,t,n){var r,i=this;if("function"==typeof e&&"function"!=typeof t){var a=t;t=e;var u=this;return function(e){var n=this;void 0===e&&(e=a);for(var r=[],o=arguments.length-1;o-- >0;)r[o]=arguments[o+1];return u.produce(e,function(e){return t.call.apply(t,[n,e].concat(r))})}}if("function"!=typeof t)throw new Error("The first or second argument to `produce` must be a function");if(void 0!==n&&"function"!=typeof n)throw new Error("The third argument to `produce` must be a function or undefined");if(l(e)){var c=v.enter(),s=this.createProxy(e),f=!0;try{r=t(s),f=!1}finally{f?c.revoke():c.leave()}return r instanceof Promise?r.then(function(e){return c.usePatches(n),i.processResult(e,c)},function(e){throw c.revoke(),e}):(c.usePatches(n),this.processResult(r,c))}return void 0===(r=t(e))?e:r!==o?r:void 0},U.prototype.createDraft=function(e){if(!l(e))throw new Error("First argument to `createDraft` must be a plain object, an array, or an immerable object");var t=v.enter(),n=this.createProxy(e);return n[a].isManual=!0,t.leave(),n},U.prototype.finishDraft=function(e,t){var n=e&&e[a];if(!n||!n.isManual)throw new Error("First argument to `finishDraft` must be a draft returned by `createDraft`");if(n.finalized)throw new Error("The given draft is already finalized");var r=n.scope;return r.usePatches(t),this.processResult(void 0,r)},U.prototype.setAutoFreeze=function(e){this.autoFreeze=e},U.prototype.setUseProxies=function(e){this.useProxies=e,s(this,e?L:M)},U.prototype.applyPatches=function(e,t){return u(e)?V(e,t):this.produce(e,function(e){return V(e,t)})},U.prototype.processResult=function(e,t){var n=t.drafts[0],r=void 0!==e&&e!==n;if(this.willFinalize(t,e,r),r){if(n[a].modified)throw t.revoke(),new Error("An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.");l(e)&&(e=this.finalize(e,null,t)),t.patches&&(t.patches.push({op:"replace",path:[],value:e}),t.inversePatches.push({op:"replace",path:[],value:n[a].base}))}else e=this.finalize(n,[],t);return t.revoke(),t.patches&&t.patchListener(t.patches,t.inversePatches),e!==o?e:void 0},U.prototype.finalize=function(e,t,n){var r=this,o=e[a];if(!o)return Object.isFrozen(e)?e:this.finalizeTree(e,null,n);if(o.scope!==n)return e;if(!o.modified)return o.base;if(!o.finalized){if(o.finalized=!0,this.finalizeTree(o.draft,t,n),this.onDelete)if(this.useProxies){var i=o.assigned;for(var u in i)i[u]||this.onDelete(o,u)}else{var l=o.base,c=o.copy;d(l,function(e){h(c,e)||r.onDelete(o,e)})}this.onCopy&&this.onCopy(o),this.autoFreeze&&n.canAutoFreeze&&Object.freeze(o.copy),t&&n.patches&&z(o,t,n.patches,n.inversePatches)}return o.copy},U.prototype.finalizeTree=function(e,t,n){var r=this,o=e[a];o&&(this.useProxies||(o.copy=p(o.draft,!0)),e=o.copy);var i=!!t&&!!n.patches,c=function(a,s,f){if(s===f)throw Error("Immer forbids circular references");var p=!!o&&f===e;if(u(s)){var h=p&&i&&!o.assigned[a]?t.concat(a):null;if(u(s=r.finalize(s,h,n))&&(n.canAutoFreeze=!1),Array.isArray(f)||y(f,a)?f[a]=s:Object.defineProperty(f,a,{value:s}),p&&s===o.base[a])return}else{if(p&&m(s,o.base[a]))return;l(s)&&!Object.isFrozen(s)&&d(s,c)}p&&r.onAssign&&r.onAssign(o,a,s)};return d(e,c),e};var H=new U,B=(H.produce,H.setAutoFreeze.bind(H)),$=(H.setUseProxies.bind(H),H.applyPatches.bind(H),H.createDraft.bind(H)),q=H.finishDraft.bind(H)}).call(this,n(77))},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=wcmlMultiCurrency.strings},function(e,t,n){"use strict";n.d(t,"a",function(){return a});var r=n(0),o=n.n(r),i=n(110);function a(e){var t=[];return o.a.Children.forEach(e,function(e){void 0!==e&&null!==e&&(Array.isArray(e)?t=t.concat(a(e)):Object(i.isFragment)(e)&&e.props?t=t.concat(a(e.props.children)):t.push(e))}),t}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t,n){"use strict";function r(e,t){for(var n=t;n;){if(n===e)return!0;n=n.parentNode}return!1}n.d(t,"a",function(){return r})},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){e.exports=!n(35)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t){var n=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=n)},function(e,t,n){e.exports=n(108)},function(e,t,n){"use strict";n.r(t);var r=function(){return!1},o=function(){return!0},i={"@@functional/placeholder":!0};function a(e){return null!=e&&"object"==typeof e&&!0===e["@@functional/placeholder"]}function u(e){return function t(n){return 0===arguments.length||a(n)?t:e.apply(this,arguments)}}function l(e){return function t(n,r){switch(arguments.length){case 0:return t;case 1:return a(n)?t:u(function(t){return e(n,t)});default:return a(n)&&a(r)?t:a(n)?u(function(t){return e(t,r)}):a(r)?u(function(t){return e(n,t)}):e(n,r)}}}var c=l(function(e,t){return Number(e)+Number(t)});function s(e,t){var n;e=e||[],t=t||[];var r=e.length,o=t.length,i=[];for(n=0;n<r;)i[i.length]=e[n],n+=1;for(n=0;n<o;)i[i.length]=t[n],n+=1;return i}function f(e,t){switch(e){case 0:return function(){return t.apply(this,arguments)};case 1:return function(e){return t.apply(this,arguments)};case 2:return function(e,n){return t.apply(this,arguments)};case 3:return function(e,n,r){return t.apply(this,arguments)};case 4:return function(e,n,r,o){return t.apply(this,arguments)};case 5:return function(e,n,r,o,i){return t.apply(this,arguments)};case 6:return function(e,n,r,o,i,a){return t.apply(this,arguments)};case 7:return function(e,n,r,o,i,a,u){return t.apply(this,arguments)};case 8:return function(e,n,r,o,i,a,u,l){return t.apply(this,arguments)};case 9:return function(e,n,r,o,i,a,u,l,c){return t.apply(this,arguments)};case 10:return function(e,n,r,o,i,a,u,l,c,s){return t.apply(this,arguments)};default:throw new Error("First argument to _arity must be a non-negative integer no greater than ten")}}function p(e,t,n){return function(){for(var r=[],o=0,i=e,u=0;u<t.length||o<arguments.length;){var l;u<t.length&&(!a(t[u])||o>=arguments.length)?l=t[u]:(l=arguments[o],o+=1),r[u]=l,a(l)||(i-=1),u+=1}return i<=0?n.apply(this,r):f(i,p(e,r,n))}}var d=l(function(e,t){return 1===e?u(t):f(e,p(e,[],t))}),y=u(function(e){return d(e.length,function(){var t=0,n=arguments[0],r=arguments[arguments.length-1],o=Array.prototype.slice.call(arguments,0);return o[0]=function(){var e=n.apply(this,s(arguments,[t,r]));return t+=1,e},e.apply(this,o)})});function h(e){return function t(n,r,o){switch(arguments.length){case 0:return t;case 1:return a(n)?t:l(function(t,r){return e(n,t,r)});case 2:return a(n)&&a(r)?t:a(n)?l(function(t,n){return e(t,r,n)}):a(r)?l(function(t,r){return e(n,t,r)}):u(function(t){return e(n,r,t)});default:return a(n)&&a(r)&&a(o)?t:a(n)&&a(r)?l(function(t,n){return e(t,n,o)}):a(n)&&a(o)?l(function(t,n){return e(t,r,n)}):a(r)&&a(o)?l(function(t,r){return e(n,t,r)}):a(n)?u(function(t){return e(t,r,o)}):a(r)?u(function(t){return e(n,t,o)}):a(o)?u(function(t){return e(n,r,t)}):e(n,r,o)}}}var m=h(function(e,t,n){if(e>=n.length||e<-n.length)return n;var r=(e<0?n.length:0)+e,o=s(n);return o[r]=t(n[r]),o}),v=Array.isArray||function(e){return null!=e&&e.length>=0&&"[object Array]"===Object.prototype.toString.call(e)};function b(e){return null!=e&&"function"==typeof e["@@transducer/step"]}function g(e,t,n){return function(){if(0===arguments.length)return n();var r=Array.prototype.slice.call(arguments,0),o=r.pop();if(!v(o)){for(var i=0;i<e.length;){if("function"==typeof o[e[i]])return o[e[i]].apply(o,r);i+=1}if(b(o))return t.apply(null,r)(o)}return n.apply(this,arguments)}}function w(e){return e&&e["@@transducer/reduced"]?e:{"@@transducer/value":e,"@@transducer/reduced":!0}}var O={init:function(){return this.xf["@@transducer/init"]()},result:function(e){return this.xf["@@transducer/result"](e)}},E=function(){function e(e,t){this.xf=t,this.f=e,this.all=!0}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.all&&(e=this.xf["@@transducer/step"](e,!0)),this.xf["@@transducer/result"](e)},e.prototype["@@transducer/step"]=function(e,t){return this.f(t)||(this.all=!1,e=w(this.xf["@@transducer/step"](e,!1))),e},e}(),S=l(g(["all"],l(function(e,t){return new E(e,t)}),function(e,t){for(var n=0;n<t.length;){if(!e(t[n]))return!1;n+=1}return!0})),_=l(function(e,t){return t>e?t:e});function P(e,t){for(var n=0,r=t.length,o=Array(r);n<r;)o[n]=e(t[n]),n+=1;return o}function x(e){return"[object String]"===Object.prototype.toString.call(e)}var j=u(function(e){return!!v(e)||!!e&&("object"==typeof e&&(!x(e)&&(1===e.nodeType?!!e.length:0===e.length||e.length>0&&(e.hasOwnProperty(0)&&e.hasOwnProperty(e.length-1)))))}),C=function(){function e(e){this.f=e}return e.prototype["@@transducer/init"]=function(){throw new Error("init not implemented on XWrap")},e.prototype["@@transducer/result"]=function(e){return e},e.prototype["@@transducer/step"]=function(e,t){return this.f(e,t)},e}();function k(e){return new C(e)}var T=l(function(e,t){return f(e.length,function(){return e.apply(t,arguments)})});function M(e,t,n){for(var r=n.next();!r.done;){if((t=e["@@transducer/step"](t,r.value))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}r=n.next()}return e["@@transducer/result"](t)}function A(e,t,n,r){return e["@@transducer/result"](n[r](T(e["@@transducer/step"],e),t))}var N="undefined"!=typeof Symbol?Symbol.iterator:"@@iterator";function R(e,t,n){if("function"==typeof e&&(e=k(e)),j(n))return function(e,t,n){for(var r=0,o=n.length;r<o;){if((t=e["@@transducer/step"](t,n[r]))&&t["@@transducer/reduced"]){t=t["@@transducer/value"];break}r+=1}return e["@@transducer/result"](t)}(e,t,n);if("function"==typeof n["fantasy-land/reduce"])return A(e,t,n,"fantasy-land/reduce");if(null!=n[N])return M(e,t,n[N]());if("function"==typeof n.next)return M(e,t,n);if("function"==typeof n.reduce)return A(e,t,n,"reduce");throw new TypeError("reduce: list must be array or iterable")}var D=function(){function e(e,t){this.xf=t,this.f=e}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=O.result,e.prototype["@@transducer/step"]=function(e,t){return this.xf["@@transducer/step"](e,this.f(t))},e}(),I=l(function(e,t){return new D(e,t)});function F(e,t){return Object.prototype.hasOwnProperty.call(t,e)}var L=Object.prototype.toString,z=function(){return"[object Arguments]"===L.call(arguments)?function(e){return"[object Arguments]"===L.call(e)}:function(e){return F("callee",e)}}(),V=!{toString:null}.propertyIsEnumerable("toString"),W=["constructor","valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"],U=function(){return arguments.propertyIsEnumerable("length")}(),H=function(e,t){for(var n=0;n<e.length;){if(e[n]===t)return!0;n+=1}return!1},B="function"!=typeof Object.keys||U?u(function(e){if(Object(e)!==e)return[];var t,n,r=[],o=U&&z(e);for(t in e)!F(t,e)||o&&"length"===t||(r[r.length]=t);if(V)for(n=W.length-1;n>=0;)F(t=W[n],e)&&!H(r,t)&&(r[r.length]=t),n-=1;return r}):u(function(e){return Object(e)!==e?[]:Object.keys(e)}),$=l(g(["fantasy-land/map","map"],I,function(e,t){switch(Object.prototype.toString.call(t)){case"[object Function]":return d(t.length,function(){return e.call(this,t.apply(this,arguments))});case"[object Object]":return R(function(n,r){return n[r]=e(t[r]),n},{},B(t));default:return P(e,t)}})),q=Number.isInteger||function(e){return e<<0===e},K=l(function(e,t){var n=e<0?t.length+e:e;return x(t)?t.charAt(n):t[n]}),Y=l(function(e,t){return e.map(function(e){for(var n,r=t,o=0;o<e.length;){if(null==r)return;n=e[o],r=q(n)?K(n,r):r[n],o+=1}return r})}),X=l(function(e,t){return Y([e],t)[0]}),G=l(function(e,t){return X([e],t)}),Q=l(function(e,t){return $(G(e),t)}),J=h(R),Z=u(function(e){return d(J(_,0,Q("length",e)),function(){for(var t=0,n=e.length;t<n;){if(!e[t].apply(this,arguments))return!1;t+=1}return!0})}),ee=u(function(e){return function(){return e}}),te=l(function(e,t){return e&&t}),ne=function(){function e(e,t){this.xf=t,this.f=e,this.any=!1}return e.prototype["@@transducer/init"]=O.init,e.prototype["@@transducer/result"]=function(e){return this.any||(e=this.xf["@@transducer/step"](e,!1)),this.xf["@@trans