Version Description
- Add - Allow free trial subscriptions #580
- Fix - The Card Processing does not appear as an available payment method when manually creating an order #562
- Fix - Express buttons & Pay Later visible on variable Subscription products /w disabled vaulting #281
- Fix - Pay for order (guest) failing when no email address available #535
- Fix - Emoji in product description causing INVALID_STRING_LENGTH error #491
- Enhancement - Change cart total amount that is sent to PayPal gateway #486
- Enhancement - Include dark Visa and Mastercard gateway icon list for PayPal Card Processing #566
- Enhancement - Onboarding errors improvements #558
- Enhancement - "Place order" button visible during gateway load time when DCC gateway is selected as the default #560
Download this release
Release Info
Developer | automattic |
Plugin | WooCommerce PayPal Payments |
Version | 1.8.0 |
Comparing to | |
See all releases |
Code changes from version 1.7.1 to 1.8.0
- changelog.txt +11 -0
- modules/ppcp-api-client/services.php +13 -1
- modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php +6 -1
- modules/ppcp-api-client/src/Endpoint/PaymentTokenEndpoint.php +155 -11
- modules/ppcp-api-client/src/Entity/PaymentTokenActionLinks.php +76 -0
- modules/ppcp-api-client/src/Entity/PurchaseUnit.php +9 -0
- modules/ppcp-api-client/src/Exception/AlreadyVaultedException.php +16 -0
- modules/ppcp-api-client/src/Factory/AmountFactory.php +18 -3
- modules/ppcp-api-client/src/Factory/ItemFactory.php +1 -1
- modules/ppcp-api-client/src/Factory/PaymentTokenActionLinksFactory.php +53 -0
- modules/ppcp-api-client/src/Repository/OrderRepository.php +54 -0
- modules/ppcp-api-client/src/Repository/PayPalRequestIdRepository.php +29 -7
- modules/ppcp-button/assets/js/button.js +1 -1
- modules/ppcp-button/resources/js/button.js +34 -2
- modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js +3 -0
- modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js +3 -0
- modules/ppcp-button/resources/js/modules/ActionHandler/FreeTrialHandler.js +43 -0
- modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js +3 -0
- modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js +7 -4
- modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js +6 -1
- modules/ppcp-button/services.php +11 -1
- modules/ppcp-button/src/Assets/SmartButton.php +140 -7
- modules/ppcp-button/src/ButtonModule.php +10 -0
- modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php +24 -2
- modules/ppcp-button/src/Endpoint/StartPayPalVaultingEndpoint.php +111 -0
- modules/ppcp-onboarding/assets/js/settings.js +33 -1
- modules/ppcp-onboarding/src/OnboardingRESTController.php +2 -1
- modules/ppcp-onboarding/src/Render/OnboardingRenderer.php +5 -3
- modules/ppcp-subscription/src/FreeTrialHandlerTrait.php +94 -0
- modules/ppcp-subscription/src/Helper/SubscriptionHelper.php +8 -24
- modules/ppcp-subscription/src/SubscriptionsHandlerTrait.php +26 -0
- modules/ppcp-vaulting/services.php +13 -7
- modules/ppcp-vaulting/src/CustomerApprovalListener.php +110 -0
- modules/ppcp-vaulting/src/PaymentTokenChecker.php +29 -64
- modules/ppcp-vaulting/src/VaultingModule.php +5 -0
- modules/ppcp-vaulting/yarn.lock +3 -3
- modules/ppcp-wc-gateway/extensions.php +1 -2
- modules/ppcp-wc-gateway/services.php +50 -23
- modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php +4 -2
- modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php +1 -0
- modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php +30 -2
- modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php +34 -0
- modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php +24 -0
- modules/ppcp-wc-gateway/yarn.lock +3 -3
- modules/ppcp-webhooks/yarn.lock +3 -3
- psalm-baseline.xml +1 -57
- psalm.xml.dist +1 -0
- readme.txt +12 -1
- vendor/autoload.php +1 -1
- vendor/composer/autoload_real.php +7 -7
- vendor/composer/autoload_static.php +4 -4
- woocommerce-paypal-payments.php +3 -3
changelog.txt
CHANGED
@@ -1,5 +1,16 @@
|
|
1 |
*** Changelog ***
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
= 1.7.1 - 2022-04-06 =
|
4 |
* Fix - Hide smart buttons for free products and zero-sum carts #499
|
5 |
* Fix - Unprocessable Entity when paying with AMEX card #516
|
1 |
*** Changelog ***
|
2 |
|
3 |
+
= 1.8.0 - 2022-05-03 =
|
4 |
+
* Add - Allow free trial subscriptions #580
|
5 |
+
* Fix - The Card Processing does not appear as an available payment method when manually creating an order #562
|
6 |
+
* Fix - Express buttons & Pay Later visible on variable Subscription products /w disabled vaulting #281
|
7 |
+
* Fix - Pay for order (guest) failing when no email address available #535
|
8 |
+
* Fix - Emoji in product description causing INVALID_STRING_LENGTH error #491
|
9 |
+
* Enhancement - Change cart total amount that is sent to PayPal gateway #486
|
10 |
+
* Enhancement - Include dark Visa and Mastercard gateway icon list for PayPal Card Processing #566
|
11 |
+
* Enhancement - Onboarding errors improvements #558
|
12 |
+
* Enhancement - "Place order" button visible during gateway load time when DCC gateway is selected as the default #560
|
13 |
+
|
14 |
= 1.7.1 - 2022-04-06 =
|
15 |
* Fix - Hide smart buttons for free products and zero-sum carts #499
|
16 |
* Fix - Unprocessable Entity when paying with AMEX card #516
|
modules/ppcp-api-client/services.php
CHANGED
@@ -35,6 +35,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayeeFactory;
|
|
35 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
36 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentsFactory;
|
37 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentSourceFactory;
|
|
|
38 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
39 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlatformFeeFactory;
|
40 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
@@ -48,6 +49,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
|
48 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
49 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
50 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
|
|
|
51 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
52 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
53 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
|
@@ -112,8 +114,10 @@ return array(
|
|
112 |
$container->get( 'api.host' ),
|
113 |
$container->get( 'api.bearer' ),
|
114 |
$container->get( 'api.factory.payment-token' ),
|
|
|
115 |
$container->get( 'woocommerce.logger.woocommerce' ),
|
116 |
-
$container->get( 'api.repository.customer' )
|
|
|
117 |
);
|
118 |
},
|
119 |
'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint {
|
@@ -228,12 +232,20 @@ return array(
|
|
228 |
$prefix = $container->get( 'api.prefix' );
|
229 |
return new CustomerRepository( $prefix );
|
230 |
},
|
|
|
|
|
|
|
|
|
|
|
231 |
'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory {
|
232 |
return new ApplicationContextFactory();
|
233 |
},
|
234 |
'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory {
|
235 |
return new PaymentTokenFactory();
|
236 |
},
|
|
|
|
|
|
|
237 |
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
|
238 |
return new WebhookFactory();
|
239 |
},
|
35 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
36 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentsFactory;
|
37 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentSourceFactory;
|
38 |
+
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenActionLinksFactory;
|
39 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
40 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlatformFeeFactory;
|
41 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
49 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
|
50 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
51 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
|
52 |
+
use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository;
|
53 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData;
|
54 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository;
|
55 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
|
114 |
$container->get( 'api.host' ),
|
115 |
$container->get( 'api.bearer' ),
|
116 |
$container->get( 'api.factory.payment-token' ),
|
117 |
+
$container->get( 'api.factory.payment-token-action-links' ),
|
118 |
$container->get( 'woocommerce.logger.woocommerce' ),
|
119 |
+
$container->get( 'api.repository.customer' ),
|
120 |
+
$container->get( 'api.repository.paypal-request-id' )
|
121 |
);
|
122 |
},
|
123 |
'api.endpoint.webhook' => static function ( ContainerInterface $container ) : WebhookEndpoint {
|
232 |
$prefix = $container->get( 'api.prefix' );
|
233 |
return new CustomerRepository( $prefix );
|
234 |
},
|
235 |
+
'api.repository.order' => static function( ContainerInterface $container ): OrderRepository {
|
236 |
+
return new OrderRepository(
|
237 |
+
$container->get( 'api.endpoint.order' )
|
238 |
+
);
|
239 |
+
},
|
240 |
'api.factory.application-context' => static function ( ContainerInterface $container ) : ApplicationContextFactory {
|
241 |
return new ApplicationContextFactory();
|
242 |
},
|
243 |
'api.factory.payment-token' => static function ( ContainerInterface $container ) : PaymentTokenFactory {
|
244 |
return new PaymentTokenFactory();
|
245 |
},
|
246 |
+
'api.factory.payment-token-action-links' => static function ( ContainerInterface $container ) : PaymentTokenActionLinksFactory {
|
247 |
+
return new PaymentTokenActionLinksFactory();
|
248 |
+
},
|
249 |
'api.factory.webhook' => static function ( ContainerInterface $container ): WebhookFactory {
|
250 |
return new WebhookFactory();
|
251 |
},
|
modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php
CHANGED
@@ -226,7 +226,7 @@ class OrderEndpoint {
|
|
226 |
'application_context' => $this->application_context_repository
|
227 |
->current_context( $shipping_preference )->to_array(),
|
228 |
);
|
229 |
-
if ( $payer ) {
|
230 |
$data['payer'] = $payer->to_array();
|
231 |
}
|
232 |
if ( $payment_token ) {
|
@@ -235,6 +235,11 @@ class OrderEndpoint {
|
|
235 |
if ( $payment_method ) {
|
236 |
$data['payment_method'] = $payment_method->to_array();
|
237 |
}
|
|
|
|
|
|
|
|
|
|
|
238 |
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
239 |
$args = array(
|
240 |
'method' => 'POST',
|
226 |
'application_context' => $this->application_context_repository
|
227 |
->current_context( $shipping_preference )->to_array(),
|
228 |
);
|
229 |
+
if ( $payer && ! empty( $payer->email_address() ) && ! empty( $payer->name() ) ) {
|
230 |
$data['payer'] = $payer->to_array();
|
231 |
}
|
232 |
if ( $payment_token ) {
|
235 |
if ( $payment_method ) {
|
236 |
$data['payment_method'] = $payment_method->to_array();
|
237 |
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* The filter can be used to modify the order creation request body data.
|
241 |
+
*/
|
242 |
+
$data = apply_filters( 'ppcp_create_order_request_body_data', $data );
|
243 |
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
|
244 |
$args = array(
|
245 |
'method' => 'POST',
|
modules/ppcp-api-client/src/Endpoint/PaymentTokenEndpoint.php
CHANGED
@@ -11,11 +11,15 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint;
|
|
11 |
|
12 |
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
13 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
|
|
|
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
17 |
use Psr\Log\LoggerInterface;
|
18 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
|
|
|
19 |
|
20 |
/**
|
21 |
* Class PaymentTokenEndpoint
|
@@ -45,6 +49,13 @@ class PaymentTokenEndpoint {
|
|
45 |
*/
|
46 |
private $factory;
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
/**
|
49 |
* The logger.
|
50 |
*
|
@@ -59,28 +70,41 @@ class PaymentTokenEndpoint {
|
|
59 |
*/
|
60 |
protected $customer_repository;
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
/**
|
63 |
* PaymentTokenEndpoint constructor.
|
64 |
*
|
65 |
-
* @param string
|
66 |
-
* @param Bearer
|
67 |
-
* @param PaymentTokenFactory
|
68 |
-
* @param
|
69 |
-
* @param
|
|
|
|
|
70 |
*/
|
71 |
public function __construct(
|
72 |
string $host,
|
73 |
Bearer $bearer,
|
74 |
PaymentTokenFactory $factory,
|
|
|
75 |
LoggerInterface $logger,
|
76 |
-
CustomerRepository $customer_repository
|
|
|
77 |
) {
|
78 |
|
79 |
-
$this->host
|
80 |
-
$this->bearer
|
81 |
-
$this->factory
|
82 |
-
$this->
|
83 |
-
$this->
|
|
|
|
|
84 |
}
|
85 |
|
86 |
/**
|
@@ -183,4 +207,124 @@ class PaymentTokenEndpoint {
|
|
183 |
|
184 |
return wp_remote_retrieve_response_code( $response ) === 204;
|
185 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
}
|
11 |
|
12 |
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
13 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentTokenActionLinks;
|
15 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\AlreadyVaultedException;
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
17 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
18 |
+
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenActionLinksFactory;
|
19 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
20 |
use Psr\Log\LoggerInterface;
|
21 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
|
22 |
+
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
|
23 |
|
24 |
/**
|
25 |
* Class PaymentTokenEndpoint
|
49 |
*/
|
50 |
private $factory;
|
51 |
|
52 |
+
/**
|
53 |
+
* The PaymentTokenActionLinks factory.
|
54 |
+
*
|
55 |
+
* @var PaymentTokenActionLinksFactory
|
56 |
+
*/
|
57 |
+
private $payment_token_action_links_factory;
|
58 |
+
|
59 |
/**
|
60 |
* The logger.
|
61 |
*
|
70 |
*/
|
71 |
protected $customer_repository;
|
72 |
|
73 |
+
/**
|
74 |
+
* The request id repository.
|
75 |
+
*
|
76 |
+
* @var PayPalRequestIdRepository
|
77 |
+
*/
|
78 |
+
private $request_id_repository;
|
79 |
+
|
80 |
/**
|
81 |
* PaymentTokenEndpoint constructor.
|
82 |
*
|
83 |
+
* @param string $host The host.
|
84 |
+
* @param Bearer $bearer The bearer.
|
85 |
+
* @param PaymentTokenFactory $factory The payment token factory.
|
86 |
+
* @param PaymentTokenActionLinksFactory $payment_token_action_links_factory The PaymentTokenActionLinks factory.
|
87 |
+
* @param LoggerInterface $logger The logger.
|
88 |
+
* @param CustomerRepository $customer_repository The customer repository.
|
89 |
+
* @param PayPalRequestIdRepository $request_id_repository The request id repository.
|
90 |
*/
|
91 |
public function __construct(
|
92 |
string $host,
|
93 |
Bearer $bearer,
|
94 |
PaymentTokenFactory $factory,
|
95 |
+
PaymentTokenActionLinksFactory $payment_token_action_links_factory,
|
96 |
LoggerInterface $logger,
|
97 |
+
CustomerRepository $customer_repository,
|
98 |
+
PayPalRequestIdRepository $request_id_repository
|
99 |
) {
|
100 |
|
101 |
+
$this->host = $host;
|
102 |
+
$this->bearer = $bearer;
|
103 |
+
$this->factory = $factory;
|
104 |
+
$this->payment_token_action_links_factory = $payment_token_action_links_factory;
|
105 |
+
$this->logger = $logger;
|
106 |
+
$this->customer_repository = $customer_repository;
|
107 |
+
$this->request_id_repository = $request_id_repository;
|
108 |
}
|
109 |
|
110 |
/**
|
207 |
|
208 |
return wp_remote_retrieve_response_code( $response ) === 204;
|
209 |
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Starts the process of PayPal account vaulting (without payment), returns the links for further actions.
|
213 |
+
*
|
214 |
+
* @param int $user_id The WP user id.
|
215 |
+
* @param string $return_url The URL to which the customer is redirected after finishing the approval.
|
216 |
+
* @param string $cancel_url The URL to which the customer is redirected if cancelled the operation.
|
217 |
+
*
|
218 |
+
* @return PaymentTokenActionLinks
|
219 |
+
* @throws RuntimeException If the request fails.
|
220 |
+
* @throws PayPalApiException If the request fails.
|
221 |
+
*/
|
222 |
+
public function start_paypal_token_creation(
|
223 |
+
int $user_id,
|
224 |
+
string $return_url,
|
225 |
+
string $cancel_url
|
226 |
+
): PaymentTokenActionLinks {
|
227 |
+
$bearer = $this->bearer->bearer();
|
228 |
+
|
229 |
+
$url = trailingslashit( $this->host ) . 'v2/vault/payment-tokens';
|
230 |
+
|
231 |
+
$customer_id = $this->customer_repository->customer_id_for_user( ( $user_id ) );
|
232 |
+
$data = array(
|
233 |
+
'customer_id' => $customer_id,
|
234 |
+
'source' => array(
|
235 |
+
'paypal' => array(
|
236 |
+
'usage_type' => 'MERCHANT',
|
237 |
+
),
|
238 |
+
),
|
239 |
+
'application_context' => array(
|
240 |
+
'return_url' => $return_url,
|
241 |
+
'cancel_url' => $cancel_url,
|
242 |
+
// TODO: can use vault_on_approval to avoid /confirm-payment-token, but currently it's not working.
|
243 |
+
),
|
244 |
+
);
|
245 |
+
|
246 |
+
$request_id = uniqid( 'ppcp-vault', true );
|
247 |
+
|
248 |
+
$args = array(
|
249 |
+
'method' => 'POST',
|
250 |
+
'headers' => array(
|
251 |
+
'Authorization' => 'Bearer ' . $bearer->token(),
|
252 |
+
'Content-Type' => 'application/json',
|
253 |
+
'Request-Id' => $request_id,
|
254 |
+
),
|
255 |
+
'body' => wp_json_encode( $data ),
|
256 |
+
);
|
257 |
+
|
258 |
+
$response = $this->request( $url, $args );
|
259 |
+
|
260 |
+
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
|
261 |
+
throw new RuntimeException( 'Failed to create payment token.' );
|
262 |
+
}
|
263 |
+
|
264 |
+
$json = json_decode( $response['body'] );
|
265 |
+
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
266 |
+
if ( 200 !== $status_code ) {
|
267 |
+
throw new PayPalApiException(
|
268 |
+
$json,
|
269 |
+
$status_code
|
270 |
+
);
|
271 |
+
}
|
272 |
+
|
273 |
+
$status = $json->status;
|
274 |
+
if ( 'CUSTOMER_ACTION_REQUIRED' !== $status ) {
|
275 |
+
throw new RuntimeException( 'Unexpected payment token creation status. ' . $status );
|
276 |
+
}
|
277 |
+
|
278 |
+
$links = $this->payment_token_action_links_factory->from_paypal_response( $json );
|
279 |
+
|
280 |
+
$this->request_id_repository->set( "ppcp-vault-{$user_id}", $request_id );
|
281 |
+
|
282 |
+
return $links;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Finishes the process of PayPal account vaulting.
|
287 |
+
*
|
288 |
+
* @param string $approval_token The id of the approval token approved by the customer.
|
289 |
+
* @param int $user_id The WP user id.
|
290 |
+
*
|
291 |
+
* @return string
|
292 |
+
* @throws RuntimeException If the request fails.
|
293 |
+
* @throws PayPalApiException If the request fails.
|
294 |
+
* @throws AlreadyVaultedException When new token was not created (for example, already vaulted with this merchant).
|
295 |
+
*/
|
296 |
+
public function create_from_approval_token( string $approval_token, int $user_id ): string {
|
297 |
+
$bearer = $this->bearer->bearer();
|
298 |
+
|
299 |
+
$url = trailingslashit( $this->host ) . 'v2/vault/approval-tokens/' . $approval_token . '/confirm-payment-token';
|
300 |
+
|
301 |
+
$args = array(
|
302 |
+
'method' => 'POST',
|
303 |
+
'headers' => array(
|
304 |
+
'Authorization' => 'Bearer ' . $bearer->token(),
|
305 |
+
'Request-Id' => $this->request_id_repository->get( "ppcp-vault-{$user_id}" ),
|
306 |
+
'Content-Type' => 'application/json',
|
307 |
+
),
|
308 |
+
);
|
309 |
+
|
310 |
+
$response = $this->request( $url, $args );
|
311 |
+
|
312 |
+
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
|
313 |
+
throw new RuntimeException( 'Failed to create payment token from approval token.' );
|
314 |
+
}
|
315 |
+
|
316 |
+
$json = json_decode( $response['body'] );
|
317 |
+
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
318 |
+
if ( 200 === $status_code ) {
|
319 |
+
throw new AlreadyVaultedException( 'Already vaulted.' );
|
320 |
+
}
|
321 |
+
if ( 201 !== $status_code ) {
|
322 |
+
throw new PayPalApiException(
|
323 |
+
$json,
|
324 |
+
$status_code
|
325 |
+
);
|
326 |
+
}
|
327 |
+
|
328 |
+
return $json->id;
|
329 |
+
}
|
330 |
}
|
modules/ppcp-api-client/src/Entity/PaymentTokenActionLinks.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The links from CUSTOMER_ACTION_REQUIRED v2/vault/payment-tokens response.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class PaymentTokenActionLinks
|
14 |
+
*/
|
15 |
+
class PaymentTokenActionLinks {
|
16 |
+
/**
|
17 |
+
* The URL for customer PayPal hosted contingency flow.
|
18 |
+
*
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
private $approve_link;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The URL for a POST request to save an approved approval token and vault the underlying instrument.
|
25 |
+
*
|
26 |
+
* @var string
|
27 |
+
*/
|
28 |
+
private $confirm_link;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* The URL for a GET request to get the state of the approval token.
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
private $status_link;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* PaymentTokenActionLinks constructor.
|
39 |
+
*
|
40 |
+
* @param string $approve_link The URL for customer PayPal hosted contingency flow.
|
41 |
+
* @param string $confirm_link The URL for a POST request to save an approved approval token and vault the underlying instrument.
|
42 |
+
* @param string $status_link The URL for a GET request to get the state of the approval token.
|
43 |
+
*/
|
44 |
+
public function __construct( string $approve_link, string $confirm_link, string $status_link ) {
|
45 |
+
$this->approve_link = $approve_link;
|
46 |
+
$this->confirm_link = $confirm_link;
|
47 |
+
$this->status_link = $status_link;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Returns the URL for customer PayPal hosted contingency flow.
|
52 |
+
*
|
53 |
+
* @return string
|
54 |
+
*/
|
55 |
+
public function approve_link(): string {
|
56 |
+
return $this->approve_link;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Returns the URL for a POST request to save an approved approval token and vault the underlying instrument.
|
61 |
+
*
|
62 |
+
* @return string
|
63 |
+
*/
|
64 |
+
public function confirm_link(): string {
|
65 |
+
return $this->confirm_link;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Returns the URL for a GET request to get the state of the approval token.
|
70 |
+
*
|
71 |
+
* @return string
|
72 |
+
*/
|
73 |
+
public function status_link(): string {
|
74 |
+
return $this->status_link;
|
75 |
+
}
|
76 |
+
}
|
modules/ppcp-api-client/src/Entity/PurchaseUnit.php
CHANGED
@@ -157,6 +157,15 @@ class PurchaseUnit {
|
|
157 |
return $this->amount;
|
158 |
}
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
/**
|
161 |
* Returns the shipping.
|
162 |
*
|
157 |
return $this->amount;
|
158 |
}
|
159 |
|
160 |
+
/**
|
161 |
+
* Sets the amount.
|
162 |
+
*
|
163 |
+
* @param Amount $amount The value to set.
|
164 |
+
*/
|
165 |
+
public function set_amount( Amount $amount ): void {
|
166 |
+
$this->amount = $amount;
|
167 |
+
}
|
168 |
+
|
169 |
/**
|
170 |
* Returns the shipping.
|
171 |
*
|
modules/ppcp-api-client/src/Exception/AlreadyVaultedException.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* AlreadyVaultedException.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\ApiClient\Exception
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\ApiClient\Exception;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Class AlreadyVaultedException
|
14 |
+
*/
|
15 |
+
class AlreadyVaultedException extends RuntimeException {
|
16 |
+
}
|
modules/ppcp-api-client/src/Factory/AmountFactory.php
CHANGED
@@ -14,12 +14,16 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\AmountBreakdown;
|
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
|
|
|
|
|
|
17 |
|
18 |
/**
|
19 |
* Class AmountFactory
|
20 |
*/
|
21 |
class AmountFactory {
|
22 |
|
|
|
23 |
|
24 |
/**
|
25 |
* The item factory.
|
@@ -117,9 +121,20 @@ class AmountFactory {
|
|
117 |
* @return Amount
|
118 |
*/
|
119 |
public function from_wc_order( \WC_Order $order ): Amount {
|
120 |
-
$currency
|
121 |
-
$items
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
$item_total = new Money(
|
124 |
(float) array_reduce(
|
125 |
$items,
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
17 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
18 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
19 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
20 |
|
21 |
/**
|
22 |
* Class AmountFactory
|
23 |
*/
|
24 |
class AmountFactory {
|
25 |
|
26 |
+
use FreeTrialHandlerTrait;
|
27 |
|
28 |
/**
|
29 |
* The item factory.
|
121 |
* @return Amount
|
122 |
*/
|
123 |
public function from_wc_order( \WC_Order $order ): Amount {
|
124 |
+
$currency = $order->get_currency();
|
125 |
+
$items = $this->item_factory->from_wc_order( $order );
|
126 |
+
|
127 |
+
$total_value = (float) $order->get_total();
|
128 |
+
if ( (
|
129 |
+
CreditCardGateway::ID === $order->get_payment_method()
|
130 |
+
|| ( PayPalGateway::ID === $order->get_payment_method() && 'card' === $order->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE ) )
|
131 |
+
)
|
132 |
+
&& $this->is_free_trial_order( $order )
|
133 |
+
) {
|
134 |
+
$total_value = 1.0;
|
135 |
+
}
|
136 |
+
$total = new Money( $total_value, $currency );
|
137 |
+
|
138 |
$item_total = new Money(
|
139 |
(float) array_reduce(
|
140 |
$items,
|
modules/ppcp-api-client/src/Factory/ItemFactory.php
CHANGED
@@ -62,7 +62,7 @@ class ItemFactory {
|
|
62 |
mb_substr( $product->get_name(), 0, 127 ),
|
63 |
new Money( $price_without_tax_rounded, $this->currency ),
|
64 |
$quantity,
|
65 |
-
|
66 |
$tax,
|
67 |
$product->get_sku(),
|
68 |
( $product->is_virtual() ) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS
|
62 |
mb_substr( $product->get_name(), 0, 127 ),
|
63 |
new Money( $price_without_tax_rounded, $this->currency ),
|
64 |
$quantity,
|
65 |
+
substr( wp_strip_all_tags( $product->get_description() ), 0, 127 ) ?: '',
|
66 |
$tax,
|
67 |
$product->get_sku(),
|
68 |
( $product->is_virtual() ) ? Item::DIGITAL_GOODS : Item::PHYSICAL_GOODS
|
modules/ppcp-api-client/src/Factory/PaymentTokenActionLinksFactory.php
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The factory for links from CUSTOMER_ACTION_REQUIRED v2/vault/payment-tokens response.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
11 |
+
|
12 |
+
use stdClass;
|
13 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentTokenActionLinks;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Class PaymentTokenActionLinksFactory
|
18 |
+
*/
|
19 |
+
class PaymentTokenActionLinksFactory {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Returns a PaymentTokenActionLinks object based off a PayPal response.
|
23 |
+
*
|
24 |
+
* @param stdClass $data The JSON object.
|
25 |
+
*
|
26 |
+
* @return PaymentTokenActionLinks
|
27 |
+
* @throws RuntimeException When JSON object is malformed.
|
28 |
+
*/
|
29 |
+
public function from_paypal_response( stdClass $data ): PaymentTokenActionLinks {
|
30 |
+
if ( ! isset( $data->links ) ) {
|
31 |
+
throw new RuntimeException( 'Links not found.' );
|
32 |
+
}
|
33 |
+
|
34 |
+
$links_map = array();
|
35 |
+
foreach ( $data->links as $link ) {
|
36 |
+
if ( ! isset( $link->rel ) || ! isset( $link->href ) ) {
|
37 |
+
throw new RuntimeException( 'Invalid link data.' );
|
38 |
+
}
|
39 |
+
|
40 |
+
$links_map[ $link->rel ] = $link->href;
|
41 |
+
}
|
42 |
+
|
43 |
+
if ( ! array_key_exists( 'approve', $links_map ) ) {
|
44 |
+
throw new RuntimeException( 'Payment token approve link not found.' );
|
45 |
+
}
|
46 |
+
|
47 |
+
return new PaymentTokenActionLinks(
|
48 |
+
$links_map['approve'],
|
49 |
+
$links_map['confirm'] ?? '',
|
50 |
+
$links_map['status'] ?? ''
|
51 |
+
);
|
52 |
+
}
|
53 |
+
}
|
modules/ppcp-api-client/src/Repository/OrderRepository.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* PayPal order repository.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\ApiClient\Repository
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\ApiClient\Repository;
|
11 |
+
|
12 |
+
use WC_Order;
|
13 |
+
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
15 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
16 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Class OrderRepository
|
20 |
+
*/
|
21 |
+
class OrderRepository {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The order endpoint.
|
25 |
+
*
|
26 |
+
* @var OrderEndpoint
|
27 |
+
*/
|
28 |
+
protected $order_endpoint;
|
29 |
+
|
30 |
+
/**
|
31 |
+
* OrderRepository constructor.
|
32 |
+
*
|
33 |
+
* @param OrderEndpoint $order_endpoint The order endpoint.
|
34 |
+
*/
|
35 |
+
public function __construct( OrderEndpoint $order_endpoint ) {
|
36 |
+
$this->order_endpoint = $order_endpoint;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Gets a PayPal order for the given WooCommerce order.
|
41 |
+
*
|
42 |
+
* @param WC_Order $wc_order The WooCommerce order.
|
43 |
+
* @return Order The PayPal order.
|
44 |
+
* @throws RuntimeException When there is a problem getting the PayPal order.
|
45 |
+
*/
|
46 |
+
public function for_wc_order( WC_Order $wc_order ): Order {
|
47 |
+
$paypal_order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
48 |
+
if ( ! $paypal_order_id ) {
|
49 |
+
throw new RuntimeException( 'PayPal order ID not found in meta.' );
|
50 |
+
}
|
51 |
+
|
52 |
+
return $this->order_endpoint->order( $paypal_order_id );
|
53 |
+
}
|
54 |
+
}
|
modules/ppcp-api-client/src/Repository/PayPalRequestIdRepository.php
CHANGED
@@ -26,8 +26,7 @@ class PayPalRequestIdRepository {
|
|
26 |
* @return string
|
27 |
*/
|
28 |
public function get_for_order_id( string $order_id ): string {
|
29 |
-
|
30 |
-
return isset( $all[ $order_id ] ) ? (string) $all[ $order_id ]['id'] : '';
|
31 |
}
|
32 |
|
33 |
/**
|
@@ -50,14 +49,37 @@ class PayPalRequestIdRepository {
|
|
50 |
* @return bool
|
51 |
*/
|
52 |
public function set_for_order( Order $order, string $request_id ): bool {
|
53 |
-
$
|
54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
'id' => $request_id,
|
56 |
-
'expiration' => time() + 10 *
|
57 |
);
|
58 |
-
$all
|
59 |
update_option( self::KEY, $all );
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
/**
|
26 |
* @return string
|
27 |
*/
|
28 |
public function get_for_order_id( string $order_id ): string {
|
29 |
+
return $this->get( $order_id );
|
|
|
30 |
}
|
31 |
|
32 |
/**
|
49 |
* @return bool
|
50 |
*/
|
51 |
public function set_for_order( Order $order, string $request_id ): bool {
|
52 |
+
$this->set( $order->id(), $request_id );
|
53 |
+
return true;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Sets a request ID for the given key.
|
58 |
+
*
|
59 |
+
* @param string $key The key in the request ID storage.
|
60 |
+
* @param string $request_id The ID.
|
61 |
+
*/
|
62 |
+
public function set( string $key, string $request_id ): void {
|
63 |
+
$all = $this->all();
|
64 |
+
$day_in_seconds = 86400;
|
65 |
+
$all[ $key ] = array(
|
66 |
'id' => $request_id,
|
67 |
+
'expiration' => time() + 10 * $day_in_seconds,
|
68 |
);
|
69 |
+
$all = $this->cleanup( $all );
|
70 |
update_option( self::KEY, $all );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Returns a request ID.
|
75 |
+
*
|
76 |
+
* @param string $key The key in the request ID storage.
|
77 |
+
*
|
78 |
+
* @return string
|
79 |
+
*/
|
80 |
+
public function get( string $key ): string {
|
81 |
+
$all = $this->all();
|
82 |
+
return isset( $all[ $key ] ) ? (string) $all[ $key ]['id'] : '';
|
83 |
}
|
84 |
|
85 |
/**
|
modules/ppcp-button/assets/js/button.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
(()=>{"use strict";var __webpack_modules__={210:()=>{eval("\n;// CONCATENATED MODULE: ./resources/js/modules/ErrorHandler.js\nclass ErrorHandler {\n constructor(genericErrorText) {\n this.genericErrorText = genericErrorText;\n this.wrapper = document.querySelector('.woocommerce-notices-wrapper');\n this.messagesList = document.querySelector('ul.woocommerce-error');\n }\n\n genericError() {\n if (this.wrapper.classList.contains('ppcp-persist')) {\n return;\n }\n\n this.clear();\n this.message(this.genericErrorText);\n }\n\n appendPreparedErrorMessageElement(errorMessageElement) {\n if (this.messagesList === null) {\n this.prepareMessagesList();\n }\n\n this.messagesList.replaceWith(errorMessageElement);\n }\n\n message(text, persist = false) {\n if (!typeof String || text.length === 0) {\n throw new Error('A new message text must be a non-empty string.');\n }\n\n if (this.messagesList === null) {\n this.prepareMessagesList();\n }\n\n if (persist) {\n this.wrapper.classList.add('ppcp-persist');\n } else {\n this.wrapper.classList.remove('ppcp-persist');\n }\n\n let messageNode = this.prepareMessagesListItem(text);\n this.messagesList.appendChild(messageNode);\n jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'));\n }\n\n prepareMessagesList() {\n if (this.messagesList === null) {\n this.messagesList = document.createElement('ul');\n this.messagesList.setAttribute('class', 'woocommerce-error');\n this.messagesList.setAttribute('role', 'alert');\n this.wrapper.appendChild(this.messagesList);\n }\n }\n\n prepareMessagesListItem(message) {\n const li = document.createElement('li');\n li.innerHTML = message;\n return li;\n }\n\n sanitize(text) {\n const textarea = document.createElement('textarea');\n textarea.innerHTML = text;\n return textarea.value.replace('Error: ', '');\n }\n\n clear() {\n if (this.messagesList === null) {\n return;\n }\n\n this.messagesList.innerHTML = '';\n }\n\n}\n\n/* harmony default export */ const modules_ErrorHandler = (ErrorHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/OnApproveHandler/onApproveForContinue.js\nconst onApprove = (context, errorHandler) => {\n return (data, actions) => {\n return fetch(context.config.ajax.approve_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: context.config.ajax.approve_order.nonce,\n order_id: data.orderID,\n funding_source: window.ppcpFundingSource\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n if (!data.success) {\n errorHandler.genericError();\n return actions.restart().catch(err => {\n errorHandler.genericError();\n });\n }\n\n location.href = context.config.redirect;\n });\n };\n};\n\n/* harmony default export */ const onApproveForContinue = (onApprove);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/PayerData.js\nconst payerData = () => {\n const payer = PayPalCommerceGateway.payer;\n\n if (!payer) {\n return null;\n }\n\n const phone = document.querySelector('#billing_phone') || typeof payer.phone !== 'undefined' ? {\n phone_type: \"HOME\",\n phone_number: {\n national_number: document.querySelector('#billing_phone') ? document.querySelector('#billing_phone').value : payer.phone.phone_number.national_number\n }\n } : null;\n const payerData = {\n email_address: document.querySelector('#billing_email') ? document.querySelector('#billing_email').value : payer.email_address,\n name: {\n surname: document.querySelector('#billing_last_name') ? document.querySelector('#billing_last_name').value : payer.name.surname,\n given_name: document.querySelector('#billing_first_name') ? document.querySelector('#billing_first_name').value : payer.name.given_name\n },\n address: {\n country_code: document.querySelector('#billing_country') ? document.querySelector('#billing_country').value : payer.address.country_code,\n address_line_1: document.querySelector('#billing_address_1') ? document.querySelector('#billing_address_1').value : payer.address.address_line_1,\n address_line_2: document.querySelector('#billing_address_2') ? document.querySelector('#billing_address_2').value : payer.address.address_line_2,\n admin_area_1: document.querySelector('#billing_state') ? document.querySelector('#billing_state').value : payer.address.admin_area_1,\n admin_area_2: document.querySelector('#billing_city') ? document.querySelector('#billing_city').value : payer.address.admin_area_2,\n postal_code: document.querySelector('#billing_postcode') ? document.querySelector('#billing_postcode').value : payer.address.postal_code\n }\n };\n\n if (phone) {\n payerData.phone = phone;\n }\n\n return payerData;\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/CartActionHandler.js\n\n\n\nclass CartActionHandler {\n constructor(config, errorHandler) {\n this.config = config;\n this.errorHandler = errorHandler;\n }\n\n configuration() {\n const createOrder = (data, actions) => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n purchase_units: [],\n bn_code: bnCode,\n payer,\n context: this.config.context\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n console.error(data);\n throw Error(data.data.message);\n }\n\n return data.data.id;\n });\n };\n\n return {\n createOrder,\n onApprove: onApproveForContinue(this, this.errorHandler),\n onError: error => {\n this.errorHandler.genericError();\n }\n };\n }\n\n}\n\n/* harmony default export */ const ActionHandler_CartActionHandler = (CartActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/MiniCartBootstap.js\n\n\n\nclass MiniCartBootstap {\n constructor(gateway, renderer) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.actionHandler = null;\n }\n\n init() {\n this.actionHandler = new ActionHandler_CartActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.render();\n jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => {\n this.render();\n });\n }\n\n shouldRender() {\n return document.querySelector(this.gateway.button.mini_cart_wrapper) !== null || document.querySelector(this.gateway.hosted_fields.mini_cart_wrapper) !== null;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n this.renderer.render(this.gateway.button.mini_cart_wrapper, this.gateway.hosted_fields.mini_cart_wrapper, this.actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_MiniCartBootstap = (MiniCartBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/UpdateCart.js\n\n\nclass UpdateCart {\n constructor(endpoint, nonce) {\n this.endpoint = endpoint;\n this.nonce = nonce;\n }\n /**\n *\n * @param onResolve\n * @param {Product[]} products\n * @returns {Promise<unknown>}\n */\n\n\n update(onResolve, products) {\n return new Promise((resolve, reject) => {\n fetch(this.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.nonce,\n products\n })\n }).then(result => {\n return result.json();\n }).then(result => {\n if (!result.success) {\n reject(result.data);\n return;\n }\n\n const resolved = onResolve(result.data);\n resolve(resolved);\n });\n });\n }\n\n}\n\n/* harmony default export */ const Helper_UpdateCart = (UpdateCart);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/ButtonsToggleListener.js\n/**\n * When you can't add something to the cart, the PayPal buttons should not show.\n * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.\n */\nclass ButtonsToggleListener {\n constructor(element, showCallback, hideCallback) {\n this.element = element;\n this.showCallback = showCallback;\n this.hideCallback = hideCallback;\n this.observer = null;\n }\n\n init() {\n const config = {\n attributes: true\n };\n\n const callback = () => {\n if (this.element.classList.contains('disabled')) {\n this.hideCallback();\n return;\n }\n\n this.showCallback();\n };\n\n this.observer = new MutationObserver(callback);\n this.observer.observe(this.element, config);\n callback();\n }\n\n disconnect() {\n this.observer.disconnect();\n }\n\n}\n\n/* harmony default export */ const Helper_ButtonsToggleListener = (ButtonsToggleListener);\n;// CONCATENATED MODULE: ./resources/js/modules/Entity/Product.js\nclass Product {\n constructor(id, quantity, variations) {\n this.id = id;\n this.quantity = quantity;\n this.variations = variations;\n }\n\n data() {\n return {\n id: this.id,\n quantity: this.quantity,\n variations: this.variations\n };\n }\n\n}\n\n/* harmony default export */ const Entity_Product = (Product);\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/SingleProductActionHandler.js\n\n\n\n\n\nclass SingleProductActionHandler {\n constructor(config, updateCart, showButtonCallback, hideButtonCallback, formElement, errorHandler) {\n this.config = config;\n this.updateCart = updateCart;\n this.showButtonCallback = showButtonCallback;\n this.hideButtonCallback = hideButtonCallback;\n this.formElement = formElement;\n this.errorHandler = errorHandler;\n }\n\n configuration() {\n if (this.hasVariations()) {\n const observer = new Helper_ButtonsToggleListener(this.formElement.querySelector('.single_add_to_cart_button'), this.showButtonCallback, this.hideButtonCallback);\n observer.init();\n }\n\n return {\n createOrder: this.createOrder(),\n onApprove: onApproveForContinue(this, this.errorHandler),\n onError: error => {\n this.errorHandler.genericError();\n }\n };\n }\n\n createOrder() {\n var getProducts = null;\n\n if (!this.isGroupedProduct()) {\n getProducts = () => {\n const id = document.querySelector('[name=\"add-to-cart\"]').value;\n const qty = document.querySelector('[name=\"quantity\"]').value;\n const variations = this.variations();\n return [new Entity_Product(id, qty, variations)];\n };\n } else {\n getProducts = () => {\n const products = [];\n this.formElement.querySelectorAll('input[type=\"number\"]').forEach(element => {\n if (!element.value) {\n return;\n }\n\n const elementName = element.getAttribute('name').match(/quantity\\[([\\d]*)\\]/);\n\n if (elementName.length !== 2) {\n return;\n }\n\n const id = parseInt(elementName[1]);\n const quantity = parseInt(element.value);\n products.push(new Entity_Product(id, quantity, null));\n });\n return products;\n };\n }\n\n const createOrder = (data, actions) => {\n this.errorHandler.clear();\n\n const onResolve = purchase_units => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n purchase_units,\n payer,\n bn_code: bnCode,\n context: this.config.context\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n console.error(data);\n throw Error(data.data.message);\n }\n\n return data.data.id;\n });\n };\n\n const promise = this.updateCart.update(onResolve, getProducts());\n return promise;\n };\n\n return createOrder;\n }\n\n variations() {\n if (!this.hasVariations()) {\n return null;\n }\n\n const attributes = [...this.formElement.querySelectorAll(\"[name^='attribute_']\")].map(element => {\n return {\n value: element.value,\n name: element.name\n };\n });\n return attributes;\n }\n\n hasVariations() {\n return this.formElement.classList.contains('variations_form');\n }\n\n isGroupedProduct() {\n return this.formElement.classList.contains('grouped_form');\n }\n\n}\n\n/* harmony default export */ const ActionHandler_SingleProductActionHandler = (SingleProductActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/SingleProductBootstap.js\n\n\n\n\nclass SingleProductBootstap {\n constructor(gateway, renderer, messages) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.messages = messages;\n }\n\n handleChange() {\n if (!this.shouldRender()) {\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n this.renderer.hideButtons(this.gateway.button.wrapper);\n return;\n }\n\n this.render();\n }\n\n init() {\n document.querySelector('form.cart').addEventListener('change', this.handleChange.bind(this));\n\n if (!this.shouldRender()) {\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n return;\n }\n\n this.render();\n }\n\n shouldRender() {\n return document.querySelector('form.cart') !== null && !this.priceAmountIsZero();\n }\n\n priceAmountIsZero() {\n let priceText = \"0\";\n\n if (document.querySelector('form.cart ins .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart ins .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('form.cart .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('.product .woocommerce-Price-amount')) {\n priceText = document.querySelector('.product .woocommerce-Price-amount').innerText;\n }\n\n const amount = parseFloat(priceText.replace(/([^\\d,\\.\\s]*)/g, ''));\n return amount === 0;\n }\n\n render() {\n const actionHandler = new ActionHandler_SingleProductActionHandler(this.gateway, new Helper_UpdateCart(this.gateway.ajax.change_cart.endpoint, this.gateway.ajax.change_cart.nonce), () => {\n this.renderer.showButtons(this.gateway.button.wrapper);\n this.renderer.showButtons(this.gateway.hosted_fields.wrapper);\n let priceText = \"0\";\n\n if (document.querySelector('form.cart ins .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart ins .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('form.cart .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart .woocommerce-Price-amount').innerText;\n }\n\n const amount = parseInt(priceText.replace(/([^\\d,\\.\\s]*)/g, ''));\n this.messages.renderWithAmount(amount);\n }, () => {\n this.renderer.hideButtons(this.gateway.button.wrapper);\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n }, document.querySelector('form.cart'), new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_SingleProductBootstap = (SingleProductBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/CartBootstap.js\n\n\n\nclass CartBootstrap {\n constructor(gateway, renderer) {\n this.gateway = gateway;\n this.renderer = renderer;\n }\n\n init() {\n if (!this.shouldRender()) {\n return;\n }\n\n this.render();\n jQuery(document.body).on('updated_cart_totals updated_checkout', () => {\n this.render();\n });\n }\n\n shouldRender() {\n return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;\n }\n\n render() {\n const actionHandler = new ActionHandler_CartActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const CartBootstap = (CartBootstrap);\n;// CONCATENATED MODULE: ./resources/js/modules/OnApproveHandler/onApproveForPayNow.js\nconst onApproveForPayNow_onApprove = (context, errorHandler, spinner) => {\n return (data, actions) => {\n spinner.block();\n errorHandler.clear();\n return fetch(context.config.ajax.approve_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: context.config.ajax.approve_order.nonce,\n order_id: data.orderID,\n funding_source: window.ppcpFundingSource\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n spinner.unblock();\n\n if (!data.success) {\n if (data.data.code === 100) {\n errorHandler.message(data.data.message);\n } else {\n errorHandler.genericError();\n }\n\n if (typeof actions !== 'undefined' && typeof actions.restart !== 'undefined') {\n return actions.restart();\n }\n\n throw new Error(data.data.message);\n }\n\n document.querySelector('#place_order').click();\n });\n };\n};\n\n/* harmony default export */ const onApproveForPayNow = (onApproveForPayNow_onApprove);\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/CheckoutActionHandler.js\n\n\n\nclass CheckoutActionHandler {\n constructor(config, errorHandler, spinner) {\n this.config = config;\n this.errorHandler = errorHandler;\n this.spinner = spinner;\n }\n\n configuration() {\n const spinner = this.spinner;\n\n const createOrder = (data, actions) => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n const errorHandler = this.errorHandler;\n const formSelector = this.config.context === 'checkout' ? 'form.checkout' : 'form#order_review';\n const formValues = jQuery(formSelector).serialize();\n const createaccount = jQuery('#createaccount').is(\":checked\") ? true : false;\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n payer,\n bn_code: bnCode,\n context: this.config.context,\n order_id: this.config.order_id,\n form: formValues,\n createaccount: createaccount\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n spinner.unblock(); //handle both messages sent from Woocommerce (data.messages) and this plugin (data.data.message)\n\n if (typeof data.messages !== 'undefined') {\n const domParser = new DOMParser();\n errorHandler.appendPreparedErrorMessageElement(domParser.parseFromString(data.messages, 'text/html').querySelector('ul'));\n } else {\n errorHandler.clear();\n\n if (data.data.details.length > 0) {\n errorHandler.message(data.data.details.map(d => `${d.issue} ${d.description}`).join('<br/>'), true);\n } else {\n errorHandler.message(data.data.message, true);\n }\n }\n\n return;\n }\n\n const input = document.createElement('input');\n input.setAttribute('type', 'hidden');\n input.setAttribute('name', 'ppcp-resume-order');\n input.setAttribute('value', data.data.purchase_units[0].custom_id);\n document.querySelector(formSelector).append(input);\n return data.data.id;\n });\n };\n\n return {\n createOrder,\n onApprove: onApproveForPayNow(this, this.errorHandler, this.spinner),\n onCancel: () => {\n spinner.unblock();\n },\n onError: () => {\n this.errorHandler.genericError();\n spinner.unblock();\n }\n };\n }\n\n}\n\n/* harmony default export */ const ActionHandler_CheckoutActionHandler = (CheckoutActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Hiding.js\nconst getElement = selectorOrElement => {\n if (typeof selectorOrElement === 'string') {\n return document.querySelector(selectorOrElement);\n }\n\n return selectorOrElement;\n};\n\nconst isVisible = element => {\n return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);\n};\nconst setVisible = (selectorOrElement, show, important = false) => {\n const element = getElement(selectorOrElement);\n\n if (!element) {\n return;\n }\n\n const currentValue = element.style.getPropertyValue('display');\n\n if (!show) {\n if (currentValue === 'none') {\n return;\n }\n\n element.style.setProperty('display', 'none', important ? 'important' : '');\n } else {\n if (currentValue === 'none') {\n element.style.removeProperty('display');\n } // still not visible (if something else added display: none in CSS)\n\n\n if (!isVisible(element)) {\n element.style.setProperty('display', 'block');\n }\n }\n};\nconst hide = (selectorOrElement, important = false) => {\n setVisible(selectorOrElement, false, important);\n};\nconst show = selectorOrElement => {\n setVisible(selectorOrElement, true);\n};\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/CheckoutMethodState.js\nconst PaymentMethods = {\n PAYPAL: 'ppcp-gateway',\n CARDS: 'ppcp-credit-card-gateway'\n};\nconst ORDER_BUTTON_SELECTOR = '#place_order';\nconst getCurrentPaymentMethod = () => {\n const el = document.querySelector('input[name=\"payment_method\"]:checked');\n\n if (!el) {\n return null;\n }\n\n return el.value;\n};\nconst isSavedCardSelected = () => {\n const savedCardList = document.querySelector('#saved-credit-card');\n return savedCardList && savedCardList.value !== '';\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/CheckoutBootstap.js\n\n\n\n\n\nclass CheckoutBootstap {\n constructor(gateway, renderer, messages, spinner) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.messages = messages;\n this.spinner = spinner;\n this.standardOrderButtonSelector = ORDER_BUTTON_SELECTOR;\n this.buttonChangeObserver = new MutationObserver(el => {\n this.updateUi();\n });\n }\n\n init() {\n this.render(); // Unselect saved card.\n // WC saves form values, so with our current UI it would be a bit weird\n // if the user paid with saved, then after some time tries to pay again,\n // but wants to enter a new card, and to do that they have to choose “Select payment” in the list.\n\n jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());\n jQuery(document.body).on('updated_checkout', () => {\n this.render();\n });\n jQuery(document.body).on('updated_checkout payment_method_selected', () => {\n this.updateUi();\n });\n jQuery(document).on('hosted_fields_loaded', () => {\n jQuery('#saved-credit-card').on('change', () => {\n this.updateUi();\n });\n });\n this.updateUi();\n }\n\n shouldRender() {\n if (document.querySelector(this.gateway.button.cancel_wrapper)) {\n return false;\n }\n\n return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) {\n document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', '');\n }\n\n const actionHandler = new ActionHandler_CheckoutActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic), this.spinner);\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n this.buttonChangeObserver.observe(document.querySelector(this.standardOrderButtonSelector), {\n attributes: true\n });\n }\n\n updateUi() {\n const currentPaymentMethod = getCurrentPaymentMethod();\n const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;\n const isCard = currentPaymentMethod === PaymentMethods.CARDS;\n const isSavedCard = isCard && isSavedCardSelected();\n const isNotOurGateway = !isPaypal && !isCard;\n setVisible(this.standardOrderButtonSelector, isNotOurGateway || isSavedCard, true);\n setVisible(this.gateway.button.wrapper, isPaypal);\n setVisible(this.gateway.messages.wrapper, isPaypal);\n setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);\n\n if (isPaypal) {\n this.messages.render();\n }\n\n if (isCard) {\n if (isSavedCard) {\n this.disableCreditCardFields();\n } else {\n this.enableCreditCardFields();\n }\n }\n }\n\n disableCreditCardFields() {\n jQuery('label[for=\"ppcp-credit-card-gateway-card-number\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-number').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-expiry\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-expiry').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-cvc\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-cvc').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"vault\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').attr(\"disabled\", true);\n this.renderer.disableCreditCardFields();\n }\n\n enableCreditCardFields() {\n jQuery('label[for=\"ppcp-credit-card-gateway-card-number\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-number').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-expiry\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-expiry').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-cvc\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-cvc').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"vault\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').attr(\"disabled\", false);\n this.renderer.enableCreditCardFields();\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_CheckoutBootstap = (CheckoutBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Subscriptions.js\nconst isChangePaymentPage = () => {\n const urlParams = new URLSearchParams(window.location.search);\n return urlParams.has('change_payment_method');\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/PayNowBootstrap.js\n\n\n\nclass PayNowBootstrap extends ContextBootstrap_CheckoutBootstap {\n constructor(gateway, renderer, messages, spinner) {\n super(gateway, renderer, messages, spinner);\n }\n\n updateUi() {\n if (isChangePaymentPage()) {\n return;\n }\n\n super.updateUi();\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_PayNowBootstrap = (PayNowBootstrap);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/Renderer.js\nclass Renderer {\n constructor(creditCardRenderer, defaultConfig, onSmartButtonClick, onSmartButtonsInit) {\n this.defaultConfig = defaultConfig;\n this.creditCardRenderer = creditCardRenderer;\n this.onSmartButtonClick = onSmartButtonClick;\n this.onSmartButtonsInit = onSmartButtonsInit;\n }\n\n render(wrapper, hostedFieldsWrapper, contextConfig) {\n this.renderButtons(wrapper, contextConfig);\n this.creditCardRenderer.render(hostedFieldsWrapper, contextConfig);\n }\n\n renderButtons(wrapper, contextConfig) {\n if (!document.querySelector(wrapper) || this.isAlreadyRendered(wrapper) || 'undefined' === typeof paypal.Buttons) {\n return;\n }\n\n const style = wrapper === this.defaultConfig.button.wrapper ? this.defaultConfig.button.style : this.defaultConfig.button.mini_cart_style;\n paypal.Buttons({\n style,\n ...contextConfig,\n onClick: this.onSmartButtonClick,\n onInit: this.onSmartButtonsInit\n }).render(wrapper);\n }\n\n isAlreadyRendered(wrapper) {\n return document.querySelector(wrapper).hasChildNodes();\n }\n\n hideButtons(element) {\n const domElement = document.querySelector(element);\n\n if (!domElement) {\n return false;\n }\n\n domElement.style.display = 'none';\n return true;\n }\n\n showButtons(element) {\n const domElement = document.querySelector(element);\n\n if (!domElement) {\n return false;\n }\n\n domElement.style.display = 'block';\n return true;\n }\n\n disableCreditCardFields() {\n this.creditCardRenderer.disableFields();\n }\n\n enableCreditCardFields() {\n this.creditCardRenderer.enableFields();\n }\n\n}\n\n/* harmony default export */ const Renderer_Renderer = (Renderer);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/DccInputFactory.js\nconst dccInputFactory = original => {\n const styles = window.getComputedStyle(original);\n const newElement = document.createElement('span');\n newElement.setAttribute('id', original.id);\n Object.values(styles).forEach(prop => {\n if (!styles[prop] || !isNaN(prop)) {\n return;\n }\n\n newElement.style.setProperty(prop, '' + styles[prop]);\n });\n return newElement;\n};\n\n/* harmony default export */ const DccInputFactory = (dccInputFactory);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/CreditCardRenderer.js\n\n\nclass CreditCardRenderer {\n constructor(defaultConfig, errorHandler, spinner) {\n this.defaultConfig = defaultConfig;\n this.errorHandler = errorHandler;\n this.spinner = spinner;\n this.cardValid = false;\n this.formValid = false;\n this.currentHostedFieldsInstance = null;\n }\n\n render(wrapper, contextConfig) {\n if (this.defaultConfig.context !== 'checkout' && this.defaultConfig.context !== 'pay-now' || wrapper === null || document.querySelector(wrapper) === null) {\n return;\n }\n\n if (typeof paypal.HostedFields === 'undefined' || !paypal.HostedFields.isEligible()) {\n const wrapperElement = document.querySelector(wrapper);\n wrapperElement.parentNode.removeChild(wrapperElement);\n return;\n }\n\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.teardown().catch(err => console.error(`Hosted fields teardown error: ${err}`));\n this.currentHostedFieldsInstance = null;\n }\n\n const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway');\n const oldDisplayStyle = gateWayBox.style.display;\n gateWayBox.style.display = 'block';\n const hideDccGateway = document.querySelector('#ppcp-hide-dcc');\n\n if (hideDccGateway) {\n hideDccGateway.parentNode.removeChild(hideDccGateway);\n }\n\n const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number');\n const stylesRaw = window.getComputedStyle(cardNumberField);\n let styles = {};\n Object.values(stylesRaw).forEach(prop => {\n if (!stylesRaw[prop]) {\n return;\n }\n\n styles[prop] = '' + stylesRaw[prop];\n });\n const cardNumber = DccInputFactory(cardNumberField);\n cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField);\n const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry');\n const cardExpiry = DccInputFactory(cardExpiryField);\n cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField);\n const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc');\n const cardCode = DccInputFactory(cardCodeField);\n cardCodeField.parentNode.replaceChild(cardCode, cardCodeField);\n gateWayBox.style.display = oldDisplayStyle;\n const formWrapper = '.payment_box payment_method_ppcp-credit-card-gateway';\n\n if (this.defaultConfig.enforce_vault && document.querySelector(formWrapper + ' .ppcp-credit-card-vault')) {\n document.querySelector(formWrapper + ' .ppcp-credit-card-vault').checked = true;\n document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);\n }\n\n paypal.HostedFields.render({\n createOrder: contextConfig.createOrder,\n styles: {\n 'input': styles\n },\n fields: {\n number: {\n selector: '#ppcp-credit-card-gateway-card-number',\n placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number\n },\n cvv: {\n selector: '#ppcp-credit-card-gateway-card-cvc',\n placeholder: this.defaultConfig.hosted_fields.labels.cvv\n },\n expirationDate: {\n selector: '#ppcp-credit-card-gateway-card-expiry',\n placeholder: this.defaultConfig.hosted_fields.labels.mm_yy\n }\n }\n }).then(hostedFields => {\n document.dispatchEvent(new CustomEvent(\"hosted_fields_loaded\"));\n this.currentHostedFieldsInstance = hostedFields;\n hostedFields.on('inputSubmitRequest', () => {\n this._submit(contextConfig);\n });\n hostedFields.on('cardTypeChange', event => {\n if (!event.cards.length) {\n this.cardValid = false;\n return;\n }\n\n const validCards = this.defaultConfig.hosted_fields.valid_cards;\n this.cardValid = validCards.indexOf(event.cards[0].type) !== -1;\n });\n hostedFields.on('validityChange', event => {\n const formValid = Object.keys(event.fields).every(function (key) {\n return event.fields[key].isValid;\n });\n this.formValid = formValid;\n });\n\n if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) {\n document.querySelector(wrapper + ' button').addEventListener('click', event => {\n event.preventDefault();\n\n this._submit(contextConfig);\n });\n document.querySelector(wrapper).setAttribute('data-ppcp-subscribed', true);\n }\n });\n document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener('click', () => {\n document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click();\n });\n }\n\n disableFields() {\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.setAttribute({\n field: 'number',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.setAttribute({\n field: 'cvv',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.setAttribute({\n field: 'expirationDate',\n attribute: 'disabled'\n });\n }\n }\n\n enableFields() {\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'number',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'cvv',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'expirationDate',\n attribute: 'disabled'\n });\n }\n }\n\n _submit(contextConfig) {\n this.spinner.block();\n this.errorHandler.clear();\n\n if (this.formValid && this.cardValid) {\n const save_card = this.defaultConfig.can_save_vault_token ? true : false;\n let vault = document.getElementById('ppcp-credit-card-vault') ? document.getElementById('ppcp-credit-card-vault').checked : save_card;\n\n if (this.defaultConfig.enforce_vault) {\n vault = true;\n }\n\n const contingency = this.defaultConfig.hosted_fields.contingency;\n const hostedFieldsData = {\n vault: vault\n };\n\n if (contingency !== 'NO_3D_SECURE') {\n hostedFieldsData.contingencies = [contingency];\n }\n\n if (this.defaultConfig.payer) {\n hostedFieldsData.cardholderName = this.defaultConfig.payer.name.given_name + ' ' + this.defaultConfig.payer.name.surname;\n }\n\n if (!hostedFieldsData.cardholderName) {\n const firstName = document.getElementById('billing_first_name') ? document.getElementById('billing_first_name').value : '';\n const lastName = document.getElementById('billing_last_name') ? document.getElementById('billing_last_name').value : '';\n\n if (!firstName || !lastName) {\n this.spinner.unblock();\n this.errorHandler.message(this.defaultConfig.hosted_fields.labels.cardholder_name_required);\n return;\n }\n\n hostedFieldsData.cardholderName = firstName + ' ' + lastName;\n }\n\n this.currentHostedFieldsInstance.submit(hostedFieldsData).then(payload => {\n payload.orderID = payload.orderId;\n this.spinner.unblock();\n return contextConfig.onApprove(payload);\n }).catch(err => {\n this.spinner.unblock();\n this.errorHandler.clear();\n\n if (err.details) {\n this.errorHandler.message(err.details.map(d => `${d.issue} ${d.description}`).join('<br/>'), true);\n }\n });\n } else {\n this.spinner.unblock();\n const message = !this.cardValid ? this.defaultConfig.hosted_fields.labels.card_not_supported : this.defaultConfig.hosted_fields.labels.fields_not_valid;\n this.errorHandler.message(message);\n }\n }\n\n}\n\n/* harmony default export */ const Renderer_CreditCardRenderer = (CreditCardRenderer);\n;// CONCATENATED MODULE: ./resources/js/modules/DataClientIdAttributeHandler.js\nconst storageKey = 'ppcp-data-client-id';\n\nconst validateToken = (token, user) => {\n if (!token) {\n return false;\n }\n\n if (token.user !== user) {\n return false;\n }\n\n const currentTime = new Date().getTime();\n const isExpired = currentTime >= token.expiration * 1000;\n return !isExpired;\n};\n\nconst storedTokenForUser = user => {\n const token = JSON.parse(sessionStorage.getItem(storageKey));\n\n if (validateToken(token, user)) {\n return token.token;\n }\n\n return null;\n};\n\nconst storeToken = token => {\n sessionStorage.setItem(storageKey, JSON.stringify(token));\n};\n\nconst dataClientIdAttributeHandler = (script, config) => {\n fetch(config.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: config.nonce\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n const isValid = validateToken(data, config.user);\n\n if (!isValid) {\n return;\n }\n\n storeToken(data);\n script.setAttribute('data-client-token', data.token);\n document.body.append(script);\n });\n};\n\n/* harmony default export */ const DataClientIdAttributeHandler = (dataClientIdAttributeHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/MessageRenderer.js\nclass MessageRenderer {\n constructor(config) {\n this.config = config;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n paypal.Messages({\n amount: this.config.amount,\n placement: this.config.placement,\n style: this.config.style\n }).render(this.config.wrapper);\n }\n\n renderWithAmount(amount) {\n if (!this.shouldRender()) {\n return;\n }\n\n const newWrapper = document.createElement('div');\n newWrapper.setAttribute('id', this.config.wrapper.replace('#', ''));\n const sibling = document.querySelector(this.config.wrapper).nextSibling;\n document.querySelector(this.config.wrapper).parentElement.removeChild(document.querySelector(this.config.wrapper));\n sibling.parentElement.insertBefore(newWrapper, sibling);\n paypal.Messages({\n amount,\n placement: this.config.placement,\n style: this.config.style\n }).render(this.config.wrapper);\n }\n\n shouldRender() {\n if (typeof paypal.Messages === 'undefined' || typeof this.config.wrapper === 'undefined') {\n return false;\n }\n\n if (!document.querySelector(this.config.wrapper)) {\n return false;\n }\n\n return true;\n }\n\n}\n\n/* harmony default export */ const Renderer_MessageRenderer = (MessageRenderer);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Spinner.js\nclass Spinner {\n constructor(target = 'form.woocommerce-checkout') {\n this.target = target;\n }\n\n setTarget(target) {\n this.target = target;\n }\n\n block() {\n jQuery(this.target).block({\n message: null,\n overlayCSS: {\n background: '#fff',\n opacity: 0.6\n }\n });\n }\n\n unblock() {\n jQuery(this.target).unblock();\n }\n\n}\n\n/* harmony default export */ const Helper_Spinner = (Spinner);\n;// CONCATENATED MODULE: ./resources/js/button.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst buttonsSpinner = new Helper_Spinner('.ppc-button-wrapper');\n\nconst bootstrap = () => {\n const errorHandler = new modules_ErrorHandler(PayPalCommerceGateway.labels.error.generic);\n const spinner = new Helper_Spinner();\n const creditCardRenderer = new Renderer_CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);\n\n const onSmartButtonClick = data => {\n window.ppcpFundingSource = data.fundingSource;\n };\n\n const onSmartButtonsInit = () => {\n buttonsSpinner.unblock();\n };\n\n const renderer = new Renderer_Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit);\n const messageRenderer = new Renderer_MessageRenderer(PayPalCommerceGateway.messages);\n const context = PayPalCommerceGateway.context;\n\n if (context === 'mini-cart' || context === 'product') {\n if (PayPalCommerceGateway.mini_cart_buttons_enabled === '1') {\n const miniCartBootstrap = new ContextBootstrap_MiniCartBootstap(PayPalCommerceGateway, renderer);\n miniCartBootstrap.init();\n }\n }\n\n if (context === 'product' && PayPalCommerceGateway.single_product_buttons_enabled === '1') {\n const singleProductBootstrap = new ContextBootstrap_SingleProductBootstap(PayPalCommerceGateway, renderer, messageRenderer);\n singleProductBootstrap.init();\n }\n\n if (context === 'cart') {\n const cartBootstrap = new CartBootstap(PayPalCommerceGateway, renderer);\n cartBootstrap.init();\n }\n\n if (context === 'checkout') {\n const checkoutBootstap = new ContextBootstrap_CheckoutBootstap(PayPalCommerceGateway, renderer, messageRenderer, spinner);\n checkoutBootstap.init();\n }\n\n if (context === 'pay-now') {\n const payNowBootstrap = new ContextBootstrap_PayNowBootstrap(PayPalCommerceGateway, renderer, messageRenderer, spinner);\n payNowBootstrap.init();\n }\n\n if (context !== 'checkout') {\n messageRenderer.render();\n }\n};\n\ndocument.addEventListener('DOMContentLoaded', () => {\n if (!typeof PayPalCommerceGateway) {\n console.error('PayPal button could not be configured.');\n return;\n }\n\n if (PayPalCommerceGateway.context !== 'checkout' && PayPalCommerceGateway.data_client_id.user === 0 && PayPalCommerceGateway.data_client_id.has_subscriptions) {\n return;\n } // Sometimes PayPal script takes long time to load,\n // so we additionally hide the standard order button here to avoid failed orders.\n // Normally it is hidden later after the script load.\n\n\n const hideOrderButtonIfPpcpGateway = () => {\n // only in checkout and pay now page, otherwise it may break things (e.g. payment via product page),\n // and also the loading spinner may look weird on other pages\n if (!['checkout', 'pay-now'].includes(PayPalCommerceGateway.context) || isChangePaymentPage()) {\n return;\n }\n\n const currentPaymentMethod = getCurrentPaymentMethod();\n const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;\n setVisible(ORDER_BUTTON_SELECTOR, !isPaypal, true);\n\n if (isPaypal) {\n // stopped after the first rendering of the buttons, in onInit\n buttonsSpinner.block();\n } else {\n buttonsSpinner.unblock();\n }\n };\n\n let bootstrapped = false;\n hideOrderButtonIfPpcpGateway();\n jQuery(document.body).on('updated_checkout payment_method_selected', () => {\n if (bootstrapped) {\n return;\n }\n\n hideOrderButtonIfPpcpGateway();\n });\n const script = document.createElement('script');\n script.addEventListener('load', event => {\n bootstrapped = true;\n bootstrap();\n });\n script.setAttribute('src', PayPalCommerceGateway.button.url);\n Object.entries(PayPalCommerceGateway.script_attributes).forEach(keyValue => {\n script.setAttribute(keyValue[0], keyValue[1]);\n });\n\n if (PayPalCommerceGateway.data_client_id.set_attribute) {\n DataClientIdAttributeHandler(script, PayPalCommerceGateway.data_client_id);\n return;\n }\n\n document.body.append(script);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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LHFCQUFxQixDQUFDNlMsY0FBdEIsQ0FBcUNTLGFBQXpDLEVBQXdEO0FBQ3BEcEMsSUFBQUEsNEJBQTRCLENBQUNDLE1BQUQsRUFBU25SLHFCQUFxQixDQUFDNlMsY0FBL0IsQ0FBNUI7QUFDQTtBQUNIOztBQUVEN1csRUFBQUEsUUFBUSxDQUFDMkMsSUFBVCxDQUFjMkksTUFBZCxDQUFxQjZKLE1BQXJCO0FBQ0gsQ0F6RUwiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvRXJyb3JIYW5kbGVyLmpzP2U2NWEiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL09uQXBwcm92ZUhhbmRsZXIvb25BcHByb3ZlRm9yQ29udGludWUuanM/YzQ1NCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1BheWVyRGF0YS5qcz8yYWYxIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9BY3Rpb25IYW5kbGVyL0NhcnRBY3Rpb25IYW5kbGVyLmpzPzgyY2YiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvTWluaUNhcnRCb290c3RhcC5qcz9kNTUyIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvVXBkYXRlQ2FydC5qcz9lNDIyIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvQnV0dG9uc1RvZ2dsZUxpc3RlbmVyLmpzP2UxOTMiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0VudGl0eS9Qcm9kdWN0LmpzPzlmZmYiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0FjdGlvbkhhbmRsZXIvU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIuanM/ZDliNyIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9TaW5nbGVQcm9kdWN0Qm9vdHN0YXAuanM/N2MxOSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9DYXJ0Qm9vdHN0YXAuanM/NWU5NCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvT25BcHByb3ZlSGFuZGxlci9vbkFwcHJvdmVGb3JQYXlOb3cuanM/OTMwNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQWN0aW9uSGFuZGxlci9DaGVja291dEFjdGlvbkhhbmRsZXIuanM/ODUxNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL0hpZGluZy5qcz8xZDM2Iiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvQ2hlY2tvdXRNZXRob2RTdGF0ZS5qcz84MGEzIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9Db250ZXh0Qm9vdHN0cmFwL0NoZWNrb3V0Qm9vdHN0YXAuanM/Yzg1NSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1N1YnNjcmlwdGlvbnMuanM/Yjg3MCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9QYXlOb3dCb290c3RyYXAuanM/ZDlmNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvUmVuZGVyZXIvUmVuZGVyZXIuanM/ZmE5MyIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL0RjY0lucHV0RmFjdG9yeS5qcz8yYTJmIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9SZW5kZXJlci9DcmVkaXRDYXJkUmVuZGVyZXIuanM/Mzg3YSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvRGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlci5qcz9lZTBiIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9SZW5kZXJlci9NZXNzYWdlUmVuZGVyZXIuanM/Y2QwMiIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1NwaW5uZXIuanM/MTcwOCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL2J1dHRvbi5qcz8wNjBmIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEVycm9ySGFuZGxlciB7XG5cbiAgICBjb25zdHJ1Y3RvcihnZW5lcmljRXJyb3JUZXh0KVxuICAgIHtcbiAgICAgICAgdGhpcy5nZW5lcmljRXJyb3JUZXh0ID0gZ2VuZXJpY0Vycm9yVGV4dDtcbiAgICAgICAgdGhpcy53cmFwcGVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLndvb2NvbW1lcmNlLW5vdGljZXMtd3JhcHBlcicpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3VsLndvb2NvbW1lcmNlLWVycm9yJyk7XG4gICAgfVxuXG4gICAgZ2VuZXJpY0Vycm9yKCkge1xuICAgICAgICBpZiAodGhpcy53cmFwcGVyLmNsYXNzTGlzdC5jb250YWlucygncHBjcC1wZXJzaXN0JykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNsZWFyKCk7XG4gICAgICAgIHRoaXMubWVzc2FnZSh0aGlzLmdlbmVyaWNFcnJvclRleHQpXG4gICAgfVxuXG4gICAgYXBwZW5kUHJlcGFyZWRFcnJvck1lc3NhZ2VFbGVtZW50KGVycm9yTWVzc2FnZUVsZW1lbnQpXG4gICAge1xuICAgICAgICBpZih0aGlzLm1lc3NhZ2VzTGlzdCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5wcmVwYXJlTWVzc2FnZXNMaXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdC5yZXBsYWNlV2l0aChlcnJvck1lc3NhZ2VFbGVtZW50KTtcbiAgICB9XG5cbiAgICBtZXNzYWdlKHRleHQsIHBlcnNpc3QgPSBmYWxzZSlcbiAgICB7XG4gICAgICAgIGlmKCEgdHlwZW9mIFN0cmluZyB8fCB0ZXh0Lmxlbmd0aCA9PT0gMCl7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgbmV3IG1lc3NhZ2UgdGV4dCBtdXN0IGJlIGEgbm9uLWVtcHR5IHN0cmluZy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKHRoaXMubWVzc2FnZXNMaXN0ID09PSBudWxsKXtcbiAgICAgICAgICAgIHRoaXMucHJlcGFyZU1lc3NhZ2VzTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBlcnNpc3QpIHtcbiAgICAgICAgICAgIHRoaXMud3JhcHBlci5jbGFzc0xpc3QuYWRkKCdwcGNwLXBlcnNpc3QnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMud3JhcHBlci5jbGFzc0xpc3QucmVtb3ZlKCdwcGNwLXBlcnNpc3QnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBtZXNzYWdlTm9kZSA9IHRoaXMucHJlcGFyZU1lc3NhZ2VzTGlzdEl0ZW0odGV4dCk7XG4gICAgICAgIHRoaXMubWVzc2FnZXNMaXN0LmFwcGVuZENoaWxkKG1lc3NhZ2VOb2RlKTtcblxuICAgICAgICBqUXVlcnkuc2Nyb2xsX3RvX25vdGljZXMoalF1ZXJ5KCcud29vY29tbWVyY2Utbm90aWNlcy13cmFwcGVyJykpXG4gICAgfVxuXG4gICAgcHJlcGFyZU1lc3NhZ2VzTGlzdCgpXG4gICAge1xuICAgICAgICBpZih0aGlzLm1lc3NhZ2VzTGlzdCA9PT0gbnVsbCl7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3VsJyk7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ3dvb2NvbW1lcmNlLWVycm9yJyk7XG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdC5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAnYWxlcnQnKTtcbiAgICAgICAgICAgIHRoaXMud3JhcHBlci5hcHBlbmRDaGlsZCh0aGlzLm1lc3NhZ2VzTGlzdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcmVwYXJlTWVzc2FnZXNMaXN0SXRlbShtZXNzYWdlKVxuICAgIHtcbiAgICAgICAgY29uc3QgbGkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpO1xuICAgICAgICBsaS5pbm5lckhUTUwgPSBtZXNzYWdlO1xuXG4gICAgICAgIHJldHVybiBsaTtcbiAgICB9XG5cbiAgICBzYW5pdGl6ZSh0ZXh0KVxuICAgIHtcbiAgICAgICAgY29uc3QgdGV4dGFyZWEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZXh0YXJlYScpO1xuICAgICAgICB0ZXh0YXJlYS5pbm5lckhUTUwgPSB0ZXh0O1xuICAgICAgICByZXR1cm4gdGV4dGFyZWEudmFsdWUucmVwbGFjZSgnRXJyb3I6ICcsICcnKTtcbiAgICB9XG5cbiAgICBjbGVhcigpXG4gICAge1xuICAgICAgICBpZiAodGhpcy5tZXNzYWdlc0xpc3QgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVzc2FnZXNMaXN0LmlubmVySFRNTCA9ICcnO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRXJyb3JIYW5kbGVyO1xuIiwiY29uc3Qgb25BcHByb3ZlID0gKGNvbnRleHQsIGVycm9ySGFuZGxlcikgPT4ge1xuICAgIHJldHVybiAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICByZXR1cm4gZmV0Y2goY29udGV4dC5jb25maWcuYWpheC5hcHByb3ZlX29yZGVyLmVuZHBvaW50LCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICBub25jZTogY29udGV4dC5jb25maWcuYWpheC5hcHByb3ZlX29yZGVyLm5vbmNlLFxuICAgICAgICAgICAgICAgIG9yZGVyX2lkOmRhdGEub3JkZXJJRCxcbiAgICAgICAgICAgICAgICBmdW5kaW5nX3NvdXJjZTogd2luZG93LnBwY3BGdW5kaW5nU291cmNlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSkudGhlbigocmVzKT0+e1xuICAgICAgICAgICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gICAgICAgIH0pLnRoZW4oKGRhdGEpPT57XG4gICAgICAgICAgICBpZiAoIWRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlci5nZW5lcmljRXJyb3IoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5yZXN0YXJ0KCkuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IGNvbnRleHQuY29uZmlnLnJlZGlyZWN0O1xuICAgICAgICB9KTtcblxuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgb25BcHByb3ZlO1xuIiwiZXhwb3J0IGNvbnN0IHBheWVyRGF0YSA9ICgpID0+IHtcbiAgICBjb25zdCBwYXllciA9IFBheVBhbENvbW1lcmNlR2F0ZXdheS5wYXllcjtcbiAgICBpZiAoISBwYXllcikge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBwaG9uZSA9IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19waG9uZScpIHx8IHR5cGVvZiBwYXllci5waG9uZSAhPT0gJ3VuZGVmaW5lZCcpID9cbiAgICB7XG4gICAgICAgIHBob25lX3R5cGU6XCJIT01FXCIsXG4gICAgICAgICAgICBwaG9uZV9udW1iZXI6e1xuICAgICAgICAgICAgbmF0aW9uYWxfbnVtYmVyIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3Bob25lJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfcGhvbmUnKS52YWx1ZSA6IHBheWVyLnBob25lLnBob25lX251bWJlci5uYXRpb25hbF9udW1iZXJcbiAgICAgICAgfVxuICAgIH0gOiBudWxsO1xuICAgIGNvbnN0IHBheWVyRGF0YSA9IHtcbiAgICAgICAgZW1haWxfYWRkcmVzczooZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfZW1haWwnKSkgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19lbWFpbCcpLnZhbHVlIDogcGF5ZXIuZW1haWxfYWRkcmVzcyxcbiAgICAgICAgbmFtZSA6IHtcbiAgICAgICAgICAgIHN1cm5hbWU6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19sYXN0X25hbWUnKSkgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19sYXN0X25hbWUnKS52YWx1ZSA6IHBheWVyLm5hbWUuc3VybmFtZSxcbiAgICAgICAgICAgIGdpdmVuX25hbWU6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19maXJzdF9uYW1lJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfZmlyc3RfbmFtZScpLnZhbHVlIDogcGF5ZXIubmFtZS5naXZlbl9uYW1lXG4gICAgICAgIH0sXG4gICAgICAgIGFkZHJlc3MgOiB7XG4gICAgICAgICAgICBjb3VudHJ5X2NvZGUgOiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfY291bnRyeScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2NvdW50cnknKS52YWx1ZSA6IHBheWVyLmFkZHJlc3MuY291bnRyeV9jb2RlLFxuICAgICAgICAgICAgYWRkcmVzc19saW5lXzEgOiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfYWRkcmVzc18xJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfYWRkcmVzc18xJykudmFsdWUgOiBwYXllci5hZGRyZXNzLmFkZHJlc3NfbGluZV8xLFxuICAgICAgICAgICAgYWRkcmVzc19saW5lXzIgOiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfYWRkcmVzc18yJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfYWRkcmVzc18yJykudmFsdWUgOiBwYXllci5hZGRyZXNzLmFkZHJlc3NfbGluZV8yLFxuICAgICAgICAgICAgYWRtaW5fYXJlYV8xIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3N0YXRlJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfc3RhdGUnKS52YWx1ZSA6IHBheWVyLmFkZHJlc3MuYWRtaW5fYXJlYV8xLFxuICAgICAgICAgICAgYWRtaW5fYXJlYV8yIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2NpdHknKSkgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19jaXR5JykudmFsdWUgOiBwYXllci5hZGRyZXNzLmFkbWluX2FyZWFfMixcbiAgICAgICAgICAgIHBvc3RhbF9jb2RlIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3Bvc3Rjb2RlJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfcG9zdGNvZGUnKS52YWx1ZSA6IHBheWVyLmFkZHJlc3MucG9zdGFsX2NvZGVcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAocGhvbmUpIHtcbiAgICAgICAgcGF5ZXJEYXRhLnBob25lID0gcGhvbmU7XG4gICAgfVxuICAgIHJldHVybiBwYXllckRhdGE7XG59XG4iLCJpbXBvcnQgb25BcHByb3ZlIGZyb20gJy4uL09uQXBwcm92ZUhhbmRsZXIvb25BcHByb3ZlRm9yQ29udGludWUuanMnO1xuaW1wb3J0IHtwYXllckRhdGF9IGZyb20gXCIuLi9IZWxwZXIvUGF5ZXJEYXRhXCI7XG5cbmNsYXNzIENhcnRBY3Rpb25IYW5kbGVyIHtcblxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZywgZXJyb3JIYW5kbGVyKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcbiAgICB9XG5cbiAgICBjb25maWd1cmF0aW9uKCkge1xuICAgICAgICBjb25zdCBjcmVhdGVPcmRlciA9IChkYXRhLCBhY3Rpb25zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXllciA9IHBheWVyRGF0YSgpO1xuICAgICAgICAgICAgY29uc3QgYm5Db2RlID0gdHlwZW9mIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdICE9PSAndW5kZWZpbmVkJyA/XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcuYm5fY29kZXNbdGhpcy5jb25maWcuY29udGV4dF0gOiAnJztcbiAgICAgICAgICAgIHJldHVybiBmZXRjaCh0aGlzLmNvbmZpZy5hamF4LmNyZWF0ZV9vcmRlci5lbmRwb2ludCwge1xuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgbm9uY2U6IHRoaXMuY29uZmlnLmFqYXguY3JlYXRlX29yZGVyLm5vbmNlLFxuICAgICAgICAgICAgICAgICAgICBwdXJjaGFzZV91bml0czogW10sXG4gICAgICAgICAgICAgICAgICAgIGJuX2NvZGU6Ym5Db2RlLFxuICAgICAgICAgICAgICAgICAgICBwYXllcixcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDp0aGlzLmNvbmZpZy5jb250ZXh0XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uKHJlcykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXMuanNvbigpO1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbihkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoZGF0YS5kYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5kYXRhLmlkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNyZWF0ZU9yZGVyLFxuICAgICAgICAgICAgb25BcHByb3ZlOiBvbkFwcHJvdmUodGhpcywgdGhpcy5lcnJvckhhbmRsZXIpLFxuICAgICAgICAgICAgb25FcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIuZ2VuZXJpY0Vycm9yKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDYXJ0QWN0aW9uSGFuZGxlcjtcbiIsImltcG9ydCBFcnJvckhhbmRsZXIgZnJvbSAnLi4vRXJyb3JIYW5kbGVyJztcbmltcG9ydCBDYXJ0QWN0aW9uSGFuZGxlciBmcm9tICcuLi9BY3Rpb25IYW5kbGVyL0NhcnRBY3Rpb25IYW5kbGVyJztcblxuY2xhc3MgTWluaUNhcnRCb290c3RhcCB7XG4gICAgY29uc3RydWN0b3IoZ2F0ZXdheSwgcmVuZGVyZXIpIHtcbiAgICAgICAgdGhpcy5nYXRld2F5ID0gZ2F0ZXdheTtcbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IHJlbmRlcmVyO1xuICAgICAgICB0aGlzLmFjdGlvbkhhbmRsZXIgPSBudWxsO1xuICAgIH1cblxuICAgIGluaXQoKSB7XG5cbiAgICAgICAgdGhpcy5hY3Rpb25IYW5kbGVyID0gbmV3IENhcnRBY3Rpb25IYW5kbGVyKFxuICAgICAgICAgICAgUGF5UGFsQ29tbWVyY2VHYXRld2F5LFxuICAgICAgICAgICAgbmV3IEVycm9ySGFuZGxlcih0aGlzLmdhdGV3YXkubGFiZWxzLmVycm9yLmdlbmVyaWMpLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuXG4gICAgICAgIGpRdWVyeShkb2N1bWVudC5ib2R5KS5vbignd2NfZnJhZ21lbnRzX2xvYWRlZCB3Y19mcmFnbWVudHNfcmVmcmVzaGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2hvdWxkUmVuZGVyKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuYnV0dG9uLm1pbmlfY2FydF93cmFwcGVyKSAhPT0gbnVsbFxuICAgICAgICAgICAgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy5taW5pX2NhcnRfd3JhcHBlcikgIT09IG51bGw7XG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVuZGVyKFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5LmJ1dHRvbi5taW5pX2NhcnRfd3JhcHBlcixcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLm1pbmlfY2FydF93cmFwcGVyLFxuICAgICAgICAgICAgdGhpcy5hY3Rpb25IYW5kbGVyLmNvbmZpZ3VyYXRpb24oKVxuICAgICAgICApO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWluaUNhcnRCb290c3RhcDtcbiIsImltcG9ydCBQcm9kdWN0IGZyb20gXCIuLi9FbnRpdHkvUHJvZHVjdFwiO1xuY2xhc3MgVXBkYXRlQ2FydCB7XG5cbiAgICBjb25zdHJ1Y3RvcihlbmRwb2ludCwgbm9uY2UpXG4gICAge1xuICAgICAgICB0aGlzLmVuZHBvaW50ID0gZW5kcG9pbnQ7XG4gICAgICAgIHRoaXMubm9uY2UgPSBub25jZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEBwYXJhbSBvblJlc29sdmVcbiAgICAgKiBAcGFyYW0ge1Byb2R1Y3RbXX0gcHJvZHVjdHNcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx1bmtub3duPn1cbiAgICAgKi9cbiAgICB1cGRhdGUob25SZXNvbHZlLCBwcm9kdWN0cylcbiAgICB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBmZXRjaChcbiAgICAgICAgICAgICAgICB0aGlzLmVuZHBvaW50LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vbmNlOiB0aGlzLm5vbmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvZHVjdHMsXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKS50aGVuKFxuICAgICAgICAgICAgICAgIChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0Lmpzb24oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLnRoZW4oKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghIHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChyZXN1bHQuZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWQgPSBvblJlc29sdmUocmVzdWx0LmRhdGEpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHJlc29sdmVkKTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFVwZGF0ZUNhcnQ7IiwiLyoqXG4gKiBXaGVuIHlvdSBjYW4ndCBhZGQgc29tZXRoaW5nIHRvIHRoZSBjYXJ0LCB0aGUgUGF5UGFsIGJ1dHRvbnMgc2hvdWxkIG5vdCBzaG93LlxuICogVGhlcmVmb3JlIHdlIGxpc3RlbiBmb3IgY2hhbmdlcyBvbiB0aGUgYWRkIHRvIGNhcnQgYnV0dG9uIGFuZCBzaG93L2hpZGUgdGhlIGJ1dHRvbnMgYWNjb3JkaW5nbHkuXG4gKi9cblxuY2xhc3MgQnV0dG9uc1RvZ2dsZUxpc3RlbmVyIHtcbiAgICBjb25zdHJ1Y3RvcihlbGVtZW50LCBzaG93Q2FsbGJhY2ssIGhpZGVDYWxsYmFjaylcbiAgICB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHRoaXMuc2hvd0NhbGxiYWNrID0gc2hvd0NhbGxiYWNrO1xuICAgICAgICB0aGlzLmhpZGVDYWxsYmFjayA9IGhpZGVDYWxsYmFjaztcbiAgICAgICAgdGhpcy5vYnNlcnZlciA9IG51bGw7XG4gICAgfVxuXG4gICAgaW5pdCgpXG4gICAge1xuICAgICAgICBjb25zdCBjb25maWcgPSB7IGF0dHJpYnV0ZXMgOiB0cnVlIH07XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpZGVDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuc2hvd0NhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKGNhbGxiYWNrKTtcbiAgICAgICAgdGhpcy5vYnNlcnZlci5vYnNlcnZlKHRoaXMuZWxlbWVudCwgY29uZmlnKTtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBkaXNjb25uZWN0KClcbiAgICB7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQnV0dG9uc1RvZ2dsZUxpc3RlbmVyOyIsImNsYXNzIFByb2R1Y3Qge1xuXG4gICAgY29uc3RydWN0b3IoaWQsIHF1YW50aXR5LCB2YXJpYXRpb25zKSB7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgdGhpcy5xdWFudGl0eSA9IHF1YW50aXR5O1xuICAgICAgICB0aGlzLnZhcmlhdGlvbnMgPSB2YXJpYXRpb25zO1xuICAgIH1cblxuICAgIGRhdGEoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDp0aGlzLmlkLFxuICAgICAgICAgICAgcXVhbnRpdHk6dGhpcy5xdWFudGl0eSxcbiAgICAgICAgICAgIHZhcmlhdGlvbnM6dGhpcy52YXJpYXRpb25zXG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFByb2R1Y3Q7IiwiaW1wb3J0IEJ1dHRvbnNUb2dnbGVMaXN0ZW5lciBmcm9tICcuLi9IZWxwZXIvQnV0dG9uc1RvZ2dsZUxpc3RlbmVyJztcbmltcG9ydCBQcm9kdWN0IGZyb20gJy4uL0VudGl0eS9Qcm9kdWN0JztcbmltcG9ydCBvbkFwcHJvdmUgZnJvbSAnLi4vT25BcHByb3ZlSGFuZGxlci9vbkFwcHJvdmVGb3JDb250aW51ZSc7XG5pbXBvcnQge3BheWVyRGF0YX0gZnJvbSBcIi4uL0hlbHBlci9QYXllckRhdGFcIjtcblxuY2xhc3MgU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIge1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdXBkYXRlQ2FydCxcbiAgICAgICAgc2hvd0J1dHRvbkNhbGxiYWNrLFxuICAgICAgICBoaWRlQnV0dG9uQ2FsbGJhY2ssXG4gICAgICAgIGZvcm1FbGVtZW50LFxuICAgICAgICBlcnJvckhhbmRsZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMudXBkYXRlQ2FydCA9IHVwZGF0ZUNhcnQ7XG4gICAgICAgIHRoaXMuc2hvd0J1dHRvbkNhbGxiYWNrID0gc2hvd0J1dHRvbkNhbGxiYWNrO1xuICAgICAgICB0aGlzLmhpZGVCdXR0b25DYWxsYmFjayA9IGhpZGVCdXR0b25DYWxsYmFjaztcbiAgICAgICAgdGhpcy5mb3JtRWxlbWVudCA9IGZvcm1FbGVtZW50O1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcbiAgICB9XG5cbiAgICBjb25maWd1cmF0aW9uKClcbiAgICB7XG5cbiAgICAgICAgaWYgKCB0aGlzLmhhc1ZhcmlhdGlvbnMoKSApIHtcbiAgICAgICAgICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IEJ1dHRvbnNUb2dnbGVMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5zaW5nbGVfYWRkX3RvX2NhcnRfYnV0dG9uJyksXG4gICAgICAgICAgICAgICAgdGhpcy5zaG93QnV0dG9uQ2FsbGJhY2ssXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlQnV0dG9uQ2FsbGJhY2tcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBvYnNlcnZlci5pbml0KCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY3JlYXRlT3JkZXI6IHRoaXMuY3JlYXRlT3JkZXIoKSxcbiAgICAgICAgICAgIG9uQXBwcm92ZTogb25BcHByb3ZlKHRoaXMsIHRoaXMuZXJyb3JIYW5kbGVyKSxcbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY3JlYXRlT3JkZXIoKVxuICAgIHtcbiAgICAgICAgdmFyIGdldFByb2R1Y3RzID0gbnVsbDtcbiAgICAgICAgaWYgKCEgdGhpcy5pc0dyb3VwZWRQcm9kdWN0KCkgKSB7XG4gICAgICAgICAgICBnZXRQcm9kdWN0cyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tuYW1lPVwiYWRkLXRvLWNhcnRcIl0nKS52YWx1ZTtcbiAgICAgICAgICAgICAgICBjb25zdCBxdHkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbbmFtZT1cInF1YW50aXR5XCJdJykudmFsdWU7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFyaWF0aW9ucyA9IHRoaXMudmFyaWF0aW9ucygpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbbmV3IFByb2R1Y3QoaWQsIHF0eSwgdmFyaWF0aW9ucyldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UHJvZHVjdHMgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcHJvZHVjdHMgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0W3R5cGU9XCJudW1iZXJcIl0nKS5mb3JFYWNoKChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghIGVsZW1lbnQudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50TmFtZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCduYW1lJykubWF0Y2goL3F1YW50aXR5XFxbKFtcXGRdKilcXF0vKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnROYW1lLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gcGFyc2VJbnQoZWxlbWVudE5hbWVbMV0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWFudGl0eSA9IHBhcnNlSW50KGVsZW1lbnQudmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBwcm9kdWN0cy5wdXNoKG5ldyBQcm9kdWN0KGlkLCBxdWFudGl0eSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb2R1Y3RzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNyZWF0ZU9yZGVyID0gKGRhdGEsIGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IG9uUmVzb2x2ZSA9IChwdXJjaGFzZV91bml0cykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWVyID0gcGF5ZXJEYXRhKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYm5Db2RlID0gdHlwZW9mIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdICE9PSAndW5kZWZpbmVkJyA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdIDogJyc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoKHRoaXMuY29uZmlnLmFqYXguY3JlYXRlX29yZGVyLmVuZHBvaW50LCB7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBub25jZTogdGhpcy5jb25maWcuYWpheC5jcmVhdGVfb3JkZXIubm9uY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdXJjaGFzZV91bml0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm5fY29kZTpibkNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0OnRoaXMuY29uZmlnLmNvbnRleHRcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gICAgICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGRhdGEuZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5kYXRhLmlkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMudXBkYXRlQ2FydC51cGRhdGUob25SZXNvbHZlLCBnZXRQcm9kdWN0cygpKTtcbiAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gY3JlYXRlT3JkZXI7XG4gICAgfVxuXG4gICAgdmFyaWF0aW9ucygpXG4gICAge1xuXG4gICAgICAgIGlmICghIHRoaXMuaGFzVmFyaWF0aW9ucygpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gWy4uLnRoaXMuZm9ybUVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChcIltuYW1lXj0nYXR0cmlidXRlXyddXCIpXS5tYXAoXG4gICAgICAgICAgICAoZWxlbWVudCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6ZWxlbWVudC52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbmFtZTplbGVtZW50Lm5hbWVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBhdHRyaWJ1dGVzO1xuICAgIH1cblxuICAgIGhhc1ZhcmlhdGlvbnMoKVxuICAgIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybUVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCd2YXJpYXRpb25zX2Zvcm0nKTtcbiAgICB9XG5cbiAgICBpc0dyb3VwZWRQcm9kdWN0KClcbiAgICB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1FbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnZ3JvdXBlZF9mb3JtJyk7XG4gICAgfVxufVxuZXhwb3J0IGRlZmF1bHQgU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXI7XG4iLCJpbXBvcnQgRXJyb3JIYW5kbGVyIGZyb20gJy4uL0Vycm9ySGFuZGxlcic7XG5pbXBvcnQgVXBkYXRlQ2FydCBmcm9tIFwiLi4vSGVscGVyL1VwZGF0ZUNhcnRcIjtcbmltcG9ydCBTaW5nbGVQcm9kdWN0QWN0aW9uSGFuZGxlciBmcm9tIFwiLi4vQWN0aW9uSGFuZGxlci9TaW5nbGVQcm9kdWN0QWN0aW9uSGFuZGxlclwiO1xuXG5jbGFzcyBTaW5nbGVQcm9kdWN0Qm9vdHN0YXAge1xuICAgIGNvbnN0cnVjdG9yKGdhdGV3YXksIHJlbmRlcmVyLCBtZXNzYWdlcykge1xuICAgICAgICB0aGlzLmdhdGV3YXkgPSBnYXRld2F5O1xuICAgICAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7XG4gICAgICAgIHRoaXMubWVzc2FnZXMgPSBtZXNzYWdlcztcbiAgICB9XG5cblxuICAgIGhhbmRsZUNoYW5nZSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcigpKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmhpZGVCdXR0b25zKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5oaWRlQnV0dG9ucyh0aGlzLmdhdGV3YXkuYnV0dG9uLndyYXBwZXIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICB9XG5cbiAgICBpbml0KCkge1xuXG4gICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCcpLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuaGFuZGxlQ2hhbmdlLmJpbmQodGhpcykpXG5cbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcigpKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmhpZGVCdXR0b25zKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcblxuICAgIH1cblxuICAgIHNob3VsZFJlbmRlcigpIHtcblxuICAgICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0JykgIT09IG51bGwgJiYgIXRoaXMucHJpY2VBbW91bnRJc1plcm8oKTtcblxuICAgIH1cblxuICAgIHByaWNlQW1vdW50SXNaZXJvKCkge1xuXG4gICAgICAgIGxldCBwcmljZVRleHQgPSBcIjBcIjtcbiAgICAgICAgaWYgKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCBpbnMgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpKSB7XG4gICAgICAgICAgICBwcmljZVRleHQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQgaW5zIC53b29jb21tZXJjZS1QcmljZS1hbW91bnQnKS5pbm5lclRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IC53b29jb21tZXJjZS1QcmljZS1hbW91bnQnKSkge1xuICAgICAgICAgICAgcHJpY2VUZXh0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IC53b29jb21tZXJjZS1QcmljZS1hbW91bnQnKS5pbm5lclRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnByb2R1Y3QgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpKSB7XG4gICAgICAgICAgICBwcmljZVRleHQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcucHJvZHVjdCAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykuaW5uZXJUZXh0O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGFtb3VudCA9IHBhcnNlRmxvYXQocHJpY2VUZXh0LnJlcGxhY2UoLyhbXlxcZCxcXC5cXHNdKikvZywgJycpKTtcbiAgICAgICAgcmV0dXJuIGFtb3VudCA9PT0gMDtcblxuICAgIH1cblxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgY29uc3QgYWN0aW9uSGFuZGxlciA9IG5ldyBTaW5nbGVQcm9kdWN0QWN0aW9uSGFuZGxlcihcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheSxcbiAgICAgICAgICAgIG5ldyBVcGRhdGVDYXJ0KFxuICAgICAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5hamF4LmNoYW5nZV9jYXJ0LmVuZHBvaW50LFxuICAgICAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5hamF4LmNoYW5nZV9jYXJ0Lm5vbmNlLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNob3dCdXR0b25zKHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5zaG93QnV0dG9ucyh0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy53cmFwcGVyKTtcbiAgICAgICAgICAgICAgICBsZXQgcHJpY2VUZXh0ID0gXCIwXCI7XG4gICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCBpbnMgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByaWNlVGV4dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCBpbnMgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpLmlubmVyVGV4dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IC53b29jb21tZXJjZS1QcmljZS1hbW91bnQnKSkge1xuICAgICAgICAgICAgICAgICAgICBwcmljZVRleHQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpLmlubmVyVGV4dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgYW1vdW50ID0gcGFyc2VJbnQocHJpY2VUZXh0LnJlcGxhY2UoLyhbXlxcZCxcXC5cXHNdKikvZywgJycpKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lc3NhZ2VzLnJlbmRlcldpdGhBbW91bnQoYW1vdW50KVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmhpZGVCdXR0b25zKHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcik7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5oaWRlQnV0dG9ucyh0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy53cmFwcGVyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQnKSxcbiAgICAgICAgICAgIG5ldyBFcnJvckhhbmRsZXIodGhpcy5nYXRld2F5LmxhYmVscy5lcnJvci5nZW5lcmljKSxcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcihcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcixcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIsXG4gICAgICAgICAgICBhY3Rpb25IYW5kbGVyLmNvbmZpZ3VyYXRpb24oKSxcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNpbmdsZVByb2R1Y3RCb290c3RhcDtcbiIsImltcG9ydCBDYXJ0QWN0aW9uSGFuZGxlciBmcm9tICcuLi9BY3Rpb25IYW5kbGVyL0NhcnRBY3Rpb25IYW5kbGVyJztcbmltcG9ydCBFcnJvckhhbmRsZXIgZnJvbSAnLi4vRXJyb3JIYW5kbGVyJztcblxuY2xhc3MgQ2FydEJvb3RzdHJhcCB7XG4gICAgY29uc3RydWN0b3IoZ2F0ZXdheSwgcmVuZGVyZXIpIHtcbiAgICAgICAgdGhpcy5nYXRld2F5ID0gZ2F0ZXdheTtcbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IHJlbmRlcmVyO1xuICAgIH1cblxuICAgIGluaXQoKSB7XG4gICAgICAgIGlmICghdGhpcy5zaG91bGRSZW5kZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQuYm9keSkub24oJ3VwZGF0ZWRfY2FydF90b3RhbHMgdXBkYXRlZF9jaGVja291dCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHNob3VsZFJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyKSAhPT1cbiAgICAgICAgICAgIG51bGwgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy53cmFwcGVyKSAhPT1cbiAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCBhY3Rpb25IYW5kbGVyID0gbmV3IENhcnRBY3Rpb25IYW5kbGVyKFxuICAgICAgICAgICAgUGF5UGFsQ29tbWVyY2VHYXRld2F5LFxuICAgICAgICAgICAgbmV3IEVycm9ySGFuZGxlcih0aGlzLmdhdGV3YXkubGFiZWxzLmVycm9yLmdlbmVyaWMpLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVuZGVyKFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyLFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlcixcbiAgICAgICAgICAgIGFjdGlvbkhhbmRsZXIuY29uZmlndXJhdGlvbigpLFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ2FydEJvb3RzdHJhcDtcbiIsImNvbnN0IG9uQXBwcm92ZSA9IChjb250ZXh0LCBlcnJvckhhbmRsZXIsIHNwaW5uZXIpID0+IHtcbiAgICByZXR1cm4gKGRhdGEsIGFjdGlvbnMpID0+IHtcbiAgICAgICAgc3Bpbm5lci5ibG9jaygpO1xuICAgICAgICBlcnJvckhhbmRsZXIuY2xlYXIoKTtcblxuICAgICAgICByZXR1cm4gZmV0Y2goY29udGV4dC5jb25maWcuYWpheC5hcHByb3ZlX29yZGVyLmVuZHBvaW50LCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICBub25jZTogY29udGV4dC5jb25maWcuYWpheC5hcHByb3ZlX29yZGVyLm5vbmNlLFxuICAgICAgICAgICAgICAgIG9yZGVyX2lkOmRhdGEub3JkZXJJRCxcbiAgICAgICAgICAgICAgICBmdW5kaW5nX3NvdXJjZTogd2luZG93LnBwY3BGdW5kaW5nU291cmNlLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSkudGhlbigocmVzKT0+e1xuICAgICAgICAgICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gICAgICAgIH0pLnRoZW4oKGRhdGEpPT57XG4gICAgICAgICAgICBzcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuZGF0YS5jb2RlID09PSAxMDApIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLm1lc3NhZ2UoZGF0YS5kYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlci5nZW5lcmljRXJyb3IoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhY3Rpb25zICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgYWN0aW9ucy5yZXN0YXJ0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5yZXN0YXJ0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihkYXRhLmRhdGEubWVzc2FnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcGxhY2Vfb3JkZXInKS5jbGljaygpXG4gICAgICAgIH0pO1xuXG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBvbkFwcHJvdmU7XG4iLCJpbXBvcnQgb25BcHByb3ZlIGZyb20gJy4uL09uQXBwcm92ZUhhbmRsZXIvb25BcHByb3ZlRm9yUGF5Tm93LmpzJztcbmltcG9ydCB7cGF5ZXJEYXRhfSBmcm9tIFwiLi4vSGVscGVyL1BheWVyRGF0YVwiO1xuXG5jbGFzcyBDaGVja291dEFjdGlvbkhhbmRsZXIge1xuXG4gICAgY29uc3RydWN0b3IoY29uZmlnLCBlcnJvckhhbmRsZXIsIHNwaW5uZXIpIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyID0gZXJyb3JIYW5kbGVyO1xuICAgICAgICB0aGlzLnNwaW5uZXIgPSBzcGlubmVyO1xuICAgIH1cblxuICAgIGNvbmZpZ3VyYXRpb24oKSB7XG4gICAgICAgIGNvbnN0IHNwaW5uZXIgPSB0aGlzLnNwaW5uZXI7XG4gICAgICAgIGNvbnN0IGNyZWF0ZU9yZGVyID0gKGRhdGEsIGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWVyID0gcGF5ZXJEYXRhKCk7XG4gICAgICAgICAgICBjb25zdCBibkNvZGUgPSB0eXBlb2YgdGhpcy5jb25maWcuYm5fY29kZXNbdGhpcy5jb25maWcuY29udGV4dF0gIT09ICd1bmRlZmluZWQnID9cbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5ibl9jb2Rlc1t0aGlzLmNvbmZpZy5jb250ZXh0XSA6ICcnO1xuXG4gICAgICAgICAgICBjb25zdCBlcnJvckhhbmRsZXIgPSB0aGlzLmVycm9ySGFuZGxlcjtcblxuICAgICAgICAgICAgY29uc3QgZm9ybVNlbGVjdG9yID0gdGhpcy5jb25maWcuY29udGV4dCA9PT0gJ2NoZWNrb3V0JyA/ICdmb3JtLmNoZWNrb3V0JyA6ICdmb3JtI29yZGVyX3Jldmlldyc7XG4gICAgICAgICAgICBjb25zdCBmb3JtVmFsdWVzID0galF1ZXJ5KGZvcm1TZWxlY3Rvcikuc2VyaWFsaXplKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGNyZWF0ZWFjY291bnQgPSBqUXVlcnkoJyNjcmVhdGVhY2NvdW50JykuaXMoXCI6Y2hlY2tlZFwiKSA/IHRydWUgOiBmYWxzZTtcblxuICAgICAgICAgICAgcmV0dXJuIGZldGNoKHRoaXMuY29uZmlnLmFqYXguY3JlYXRlX29yZGVyLmVuZHBvaW50LCB7XG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBub25jZTogdGhpcy5jb25maWcuYWpheC5jcmVhdGVfb3JkZXIubm9uY2UsXG4gICAgICAgICAgICAgICAgICAgIHBheWVyLFxuICAgICAgICAgICAgICAgICAgICBibl9jb2RlOmJuQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dDp0aGlzLmNvbmZpZy5jb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBvcmRlcl9pZDp0aGlzLmNvbmZpZy5vcmRlcl9pZCxcbiAgICAgICAgICAgICAgICAgICAgZm9ybTpmb3JtVmFsdWVzLFxuICAgICAgICAgICAgICAgICAgICBjcmVhdGVhY2NvdW50OiBjcmVhdGVhY2NvdW50XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXMuanNvbigpO1xuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgICAgICAgICAvL2hhbmRsZSBib3RoIG1lc3NhZ2VzIHNlbnQgZnJvbSBXb29jb21tZXJjZSAoZGF0YS5tZXNzYWdlcykgYW5kIHRoaXMgcGx1Z2luIChkYXRhLmRhdGEubWVzc2FnZSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZihkYXRhLm1lc3NhZ2VzKSAhPT0gJ3VuZGVmaW5lZCcgKVxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkb21QYXJzZXIgPSBuZXcgRE9NUGFyc2VyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsZXIuYXBwZW5kUHJlcGFyZWRFcnJvck1lc3NhZ2VFbGVtZW50KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbVBhcnNlci5wYXJzZUZyb21TdHJpbmcoZGF0YS5tZXNzYWdlcywgJ3RleHQvaHRtbCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5xdWVyeVNlbGVjdG9yKCd1bCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5kYXRhLmRldGFpbHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlci5tZXNzYWdlKGRhdGEuZGF0YS5kZXRhaWxzLm1hcChkID0+IGAke2QuaXNzdWV9ICR7ZC5kZXNjcmlwdGlvbn1gKS5qb2luKCc8YnIvPicpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLm1lc3NhZ2UoZGF0YS5kYXRhLm1lc3NhZ2UsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XG4gICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2hpZGRlbicpO1xuICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnbmFtZScsICdwcGNwLXJlc3VtZS1vcmRlcicpO1xuICAgICAgICAgICAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgndmFsdWUnLCBkYXRhLmRhdGEucHVyY2hhc2VfdW5pdHNbMF0uY3VzdG9tX2lkKTtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGZvcm1TZWxlY3RvcikuYXBwZW5kKGlucHV0KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGF0YS5kYXRhLmlkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNyZWF0ZU9yZGVyLFxuICAgICAgICAgICAgb25BcHByb3ZlOm9uQXBwcm92ZSh0aGlzLCB0aGlzLmVycm9ySGFuZGxlciwgdGhpcy5zcGlubmVyKSxcbiAgICAgICAgICAgIG9uQ2FuY2VsOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25FcnJvcjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgICAgIHNwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDaGVja291dEFjdGlvbkhhbmRsZXI7XG4iLCJjb25zdCBnZXRFbGVtZW50ID0gKHNlbGVjdG9yT3JFbGVtZW50KSA9PiB7XG4gICAgaWYgKHR5cGVvZiBzZWxlY3Rvck9yRWxlbWVudCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Ioc2VsZWN0b3JPckVsZW1lbnQpO1xuICAgIH1cbiAgICByZXR1cm4gc2VsZWN0b3JPckVsZW1lbnQ7XG59XG5cbmV4cG9ydCBjb25zdCBpc1Zpc2libGUgPSAoZWxlbWVudCkgPT4ge1xuICAgIHJldHVybiAhIShlbGVtZW50Lm9mZnNldFdpZHRoIHx8IGVsZW1lbnQub2Zmc2V0SGVpZ2h0IHx8IGVsZW1lbnQuZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGgpO1xufVxuXG5leHBvcnQgY29uc3Qgc2V0VmlzaWJsZSA9IChzZWxlY3Rvck9yRWxlbWVudCwgc2hvdywgaW1wb3J0YW50ID0gZmFsc2UpID0+IHtcbiAgICBjb25zdCBlbGVtZW50ID0gZ2V0RWxlbWVudChzZWxlY3Rvck9yRWxlbWVudCk7XG4gICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBlbGVtZW50LnN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2Rpc3BsYXknKTtcblxuICAgIGlmICghc2hvdykge1xuICAgICAgICBpZiAoY3VycmVudFZhbHVlID09PSAnbm9uZScpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoJ2Rpc3BsYXknLCAnbm9uZScsIGltcG9ydGFudCA/ICdpbXBvcnRhbnQnIDogJycpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjdXJyZW50VmFsdWUgPT09ICdub25lJykge1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgnZGlzcGxheScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3RpbGwgbm90IHZpc2libGUgKGlmIHNvbWV0aGluZyBlbHNlIGFkZGVkIGRpc3BsYXk6IG5vbmUgaW4gQ1NTKVxuICAgICAgICBpZiAoIWlzVmlzaWJsZShlbGVtZW50KSkge1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5zZXRQcm9wZXJ0eSgnZGlzcGxheScsICdibG9jaycpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGhpZGUgPSAoc2VsZWN0b3JPckVsZW1lbnQsIGltcG9ydGFudCA9IGZhbHNlKSA9PiB7XG4gICAgc2V0VmlzaWJsZShzZWxlY3Rvck9yRWxlbWVudCwgZmFsc2UsIGltcG9ydGFudCk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2hvdyA9IChzZWxlY3Rvck9yRWxlbWVudCkgPT4ge1xuICAgIHNldFZpc2libGUoc2VsZWN0b3JPckVsZW1lbnQsIHRydWUpO1xufTtcbiIsImV4cG9ydCBjb25zdCBQYXltZW50TWV0aG9kcyA9IHtcbiAgICBQQVlQQUw6ICdwcGNwLWdhdGV3YXknLFxuICAgIENBUkRTOiAncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5Jyxcbn07XG5cbmV4cG9ydCBjb25zdCBPUkRFUl9CVVRUT05fU0VMRUNUT1IgPSAnI3BsYWNlX29yZGVyJztcblxuZXhwb3J0IGNvbnN0IGdldEN1cnJlbnRQYXltZW50TWV0aG9kID0gKCkgPT4ge1xuICAgIGNvbnN0IGVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXRbbmFtZT1cInBheW1lbnRfbWV0aG9kXCJdOmNoZWNrZWQnKTtcbiAgICBpZiAoIWVsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBlbC52YWx1ZTtcbn07XG5cbmV4cG9ydCBjb25zdCBpc1NhdmVkQ2FyZFNlbGVjdGVkID0gKCkgPT4ge1xuICAgIGNvbnN0IHNhdmVkQ2FyZExpc3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjc2F2ZWQtY3JlZGl0LWNhcmQnKTtcbiAgICByZXR1cm4gc2F2ZWRDYXJkTGlzdCAmJiBzYXZlZENhcmRMaXN0LnZhbHVlICE9PSAnJztcbn07XG4iLCJpbXBvcnQgRXJyb3JIYW5kbGVyIGZyb20gJy4uL0Vycm9ySGFuZGxlcic7XG5pbXBvcnQgQ2hlY2tvdXRBY3Rpb25IYW5kbGVyIGZyb20gJy4uL0FjdGlvbkhhbmRsZXIvQ2hlY2tvdXRBY3Rpb25IYW5kbGVyJztcbmltcG9ydCB7IHNldFZpc2libGUgfSBmcm9tICcuLi9IZWxwZXIvSGlkaW5nJztcbmltcG9ydCB7XG4gICAgZ2V0Q3VycmVudFBheW1lbnRNZXRob2QsXG4gICAgaXNTYXZlZENhcmRTZWxlY3RlZCwgT1JERVJfQlVUVE9OX1NFTEVDVE9SLFxuICAgIFBheW1lbnRNZXRob2RzXG59IGZyb20gXCIuLi9IZWxwZXIvQ2hlY2tvdXRNZXRob2RTdGF0ZVwiO1xuXG5jbGFzcyBDaGVja291dEJvb3RzdGFwIHtcbiAgICBjb25zdHJ1Y3RvcihnYXRld2F5LCByZW5kZXJlciwgbWVzc2FnZXMsIHNwaW5uZXIpIHtcbiAgICAgICAgdGhpcy5nYXRld2F5ID0gZ2F0ZXdheTtcbiAgICAgICAgdGhpcy5yZW5kZXJlciA9IHJlbmRlcmVyO1xuICAgICAgICB0aGlzLm1lc3NhZ2VzID0gbWVzc2FnZXM7XG4gICAgICAgIHRoaXMuc3Bpbm5lciA9IHNwaW5uZXI7XG5cbiAgICAgICAgdGhpcy5zdGFuZGFyZE9yZGVyQnV0dG9uU2VsZWN0b3IgPSBPUkRFUl9CVVRUT05fU0VMRUNUT1I7XG5cbiAgICAgICAgdGhpcy5idXR0b25DaGFuZ2VPYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKChlbCkgPT4ge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVVaSgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBpbml0KCkge1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuXG4gICAgICAgIC8vIFVuc2VsZWN0IHNhdmVkIGNhcmQuXG4gICAgICAgIC8vIFdDIHNhdmVzIGZvcm0gdmFsdWVzLCBzbyB3aXRoIG91ciBjdXJyZW50IFVJIGl0IHdvdWxkIGJlIGEgYml0IHdlaXJkXG4gICAgICAgIC8vIGlmIHRoZSB1c2VyIHBhaWQgd2l0aCBzYXZlZCwgdGhlbiBhZnRlciBzb21lIHRpbWUgdHJpZXMgdG8gcGF5IGFnYWluLFxuICAgICAgICAvLyBidXQgd2FudHMgdG8gZW50ZXIgYSBuZXcgY2FyZCwgYW5kIHRvIGRvIHRoYXQgdGhleSBoYXZlIHRvIGNob29zZSDigJxTZWxlY3QgcGF5bWVudOKAnSBpbiB0aGUgbGlzdC5cbiAgICAgICAgalF1ZXJ5KCcjc2F2ZWQtY3JlZGl0LWNhcmQnKS52YWwoalF1ZXJ5KCcjc2F2ZWQtY3JlZGl0LWNhcmQgb3B0aW9uOmZpcnN0JykudmFsKCkpO1xuXG4gICAgICAgIGpRdWVyeShkb2N1bWVudC5ib2R5KS5vbigndXBkYXRlZF9jaGVja291dCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyKClcbiAgICAgICAgfSk7XG5cbiAgICAgICAgalF1ZXJ5KGRvY3VtZW50LmJvZHkpLm9uKCd1cGRhdGVkX2NoZWNrb3V0IHBheW1lbnRfbWV0aG9kX3NlbGVjdGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVVaSgpO1xuICAgICAgICB9KTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQpLm9uKCdob3N0ZWRfZmllbGRzX2xvYWRlZCcsICgpID0+IHtcbiAgICAgICAgICAgIGpRdWVyeSgnI3NhdmVkLWNyZWRpdC1jYXJkJykub24oJ2NoYW5nZScsICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVVpKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnVwZGF0ZVVpKCk7XG4gICAgfVxuXG4gICAgc2hvdWxkUmVuZGVyKCkge1xuICAgICAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuYnV0dG9uLmNhbmNlbF93cmFwcGVyKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyKSAhPT0gbnVsbCB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpICE9PSBudWxsO1xuICAgIH1cblxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlciArICc+ZGl2JykpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlciArICc+ZGl2Jykuc2V0QXR0cmlidXRlKCdzdHlsZScsICcnKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhY3Rpb25IYW5kbGVyID0gbmV3IENoZWNrb3V0QWN0aW9uSGFuZGxlcihcbiAgICAgICAgICAgIFBheVBhbENvbW1lcmNlR2F0ZXdheSxcbiAgICAgICAgICAgIG5ldyBFcnJvckhhbmRsZXIodGhpcy5nYXRld2F5LmxhYmVscy5lcnJvci5nZW5lcmljKSxcbiAgICAgICAgICAgIHRoaXMuc3Bpbm5lclxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVuZGVyKFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyLFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlcixcbiAgICAgICAgICAgIGFjdGlvbkhhbmRsZXIuY29uZmlndXJhdGlvbigpLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuYnV0dG9uQ2hhbmdlT2JzZXJ2ZXIub2JzZXJ2ZShcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5zdGFuZGFyZE9yZGVyQnV0dG9uU2VsZWN0b3IpLFxuICAgICAgICAgICAge2F0dHJpYnV0ZXM6IHRydWV9XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdXBkYXRlVWkoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRQYXltZW50TWV0aG9kID0gZ2V0Q3VycmVudFBheW1lbnRNZXRob2QoKTtcbiAgICAgICAgY29uc3QgaXNQYXlwYWwgPSBjdXJyZW50UGF5bWVudE1ldGhvZCA9PT0gUGF5bWVudE1ldGhvZHMuUEFZUEFMO1xuICAgICAgICBjb25zdCBpc0NhcmQgPSBjdXJyZW50UGF5bWVudE1ldGhvZCA9PT0gUGF5bWVudE1ldGhvZHMuQ0FSRFM7XG4gICAgICAgIGNvbnN0IGlzU2F2ZWRDYXJkID0gaXNDYXJkICYmIGlzU2F2ZWRDYXJkU2VsZWN0ZWQoKTtcbiAgICAgICAgY29uc3QgaXNOb3RPdXJHYXRld2F5ID0gIWlzUGF5cGFsICYmICFpc0NhcmQ7XG5cbiAgICAgICAgc2V0VmlzaWJsZSh0aGlzLnN0YW5kYXJkT3JkZXJCdXR0b25TZWxlY3RvciwgaXNOb3RPdXJHYXRld2F5IHx8IGlzU2F2ZWRDYXJkLCB0cnVlKTtcbiAgICAgICAgc2V0VmlzaWJsZSh0aGlzLmdhdGV3YXkuYnV0dG9uLndyYXBwZXIsIGlzUGF5cGFsKTtcbiAgICAgICAgc2V0VmlzaWJsZSh0aGlzLmdhdGV3YXkubWVzc2FnZXMud3JhcHBlciwgaXNQYXlwYWwpO1xuICAgICAgICBzZXRWaXNpYmxlKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIsIGlzQ2FyZCAmJiAhaXNTYXZlZENhcmQpO1xuXG4gICAgICAgIGlmIChpc1BheXBhbCkge1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlcy5yZW5kZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0NhcmQpIHtcbiAgICAgICAgICAgIGlmIChpc1NhdmVkQ2FyZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUNyZWRpdENhcmRGaWVsZHMoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVDcmVkaXRDYXJkRmllbGRzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBkaXNhYmxlQ3JlZGl0Q2FyZEZpZWxkcygpIHtcbiAgICAgICAgalF1ZXJ5KCdsYWJlbFtmb3I9XCJwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1udW1iZXJcIl0nKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1udW1iZXInKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJ2xhYmVsW2Zvcj1cInBwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWV4cGlyeVwiXScpLmFkZENsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWV4cGlyeScpLmFkZENsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwicHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtY3ZjXCJdJykuYWRkQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtY3ZjJykuYWRkQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCdsYWJlbFtmb3I9XCJ2YXVsdFwiXScpLmFkZENsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLXZhdWx0JykuYXR0cihcImRpc2FibGVkXCIsIHRydWUpXG4gICAgICAgIHRoaXMucmVuZGVyZXIuZGlzYWJsZUNyZWRpdENhcmRGaWVsZHMoKVxuICAgIH1cblxuICAgIGVuYWJsZUNyZWRpdENhcmRGaWVsZHMoKSB7XG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwicHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyXCJdJykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyJykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCdsYWJlbFtmb3I9XCJwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1leHBpcnlcIl0nKS5yZW1vdmVDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1leHBpcnknKS5yZW1vdmVDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJ2xhYmVsW2Zvcj1cInBwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWN2Y1wiXScpLnJlbW92ZUNsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWN2YycpLnJlbW92ZUNsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwidmF1bHRcIl0nKS5yZW1vdmVDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLXZhdWx0JykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC12YXVsdCcpLmF0dHIoXCJkaXNhYmxlZFwiLCBmYWxzZSlcbiAgICAgICAgdGhpcy5yZW5kZXJlci5lbmFibGVDcmVkaXRDYXJkRmllbGRzKClcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENoZWNrb3V0Qm9vdHN0YXBcbiIsImV4cG9ydCBjb25zdCBpc0NoYW5nZVBheW1lbnRQYWdlID0gKCkgPT4ge1xuICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaClcbiAgICByZXR1cm4gdXJsUGFyYW1zLmhhcygnY2hhbmdlX3BheW1lbnRfbWV0aG9kJyk7XG59XG4iLCJpbXBvcnQgQ2hlY2tvdXRCb290c3RhcCBmcm9tICcuL0NoZWNrb3V0Qm9vdHN0YXAnXG5pbXBvcnQge2lzQ2hhbmdlUGF5bWVudFBhZ2V9IGZyb20gXCIuLi9IZWxwZXIvU3Vic2NyaXB0aW9uc1wiO1xuXG5jbGFzcyBQYXlOb3dCb290c3RyYXAgZXh0ZW5kcyBDaGVja291dEJvb3RzdGFwIHtcbiAgICBjb25zdHJ1Y3RvcihnYXRld2F5LCByZW5kZXJlciwgbWVzc2FnZXMsIHNwaW5uZXIpIHtcbiAgICAgICAgc3VwZXIoZ2F0ZXdheSwgcmVuZGVyZXIsIG1lc3NhZ2VzLCBzcGlubmVyKVxuICAgIH1cblxuICAgIHVwZGF0ZVVpKCkge1xuICAgICAgICBpZiAoaXNDaGFuZ2VQYXltZW50UGFnZSgpKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIHN1cGVyLnVwZGF0ZVVpKCk7XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBQYXlOb3dCb290c3RyYXA7XG4iLCJjbGFzcyBSZW5kZXJlciB7XG4gICAgY29uc3RydWN0b3IoY3JlZGl0Q2FyZFJlbmRlcmVyLCBkZWZhdWx0Q29uZmlnLCBvblNtYXJ0QnV0dG9uQ2xpY2ssIG9uU21hcnRCdXR0b25zSW5pdCkge1xuICAgICAgICB0aGlzLmRlZmF1bHRDb25maWcgPSBkZWZhdWx0Q29uZmlnO1xuICAgICAgICB0aGlzLmNyZWRpdENhcmRSZW5kZXJlciA9IGNyZWRpdENhcmRSZW5kZXJlcjtcbiAgICAgICAgdGhpcy5vblNtYXJ0QnV0dG9uQ2xpY2sgPSBvblNtYXJ0QnV0dG9uQ2xpY2s7XG4gICAgICAgIHRoaXMub25TbWFydEJ1dHRvbnNJbml0ID0gb25TbWFydEJ1dHRvbnNJbml0O1xuICAgIH1cblxuICAgIHJlbmRlcih3cmFwcGVyLCBob3N0ZWRGaWVsZHNXcmFwcGVyLCBjb250ZXh0Q29uZmlnKSB7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJCdXR0b25zKHdyYXBwZXIsIGNvbnRleHRDb25maWcpO1xuICAgICAgICB0aGlzLmNyZWRpdENhcmRSZW5kZXJlci5yZW5kZXIoaG9zdGVkRmllbGRzV3JhcHBlciwgY29udGV4dENvbmZpZyk7XG4gICAgfVxuXG4gICAgcmVuZGVyQnV0dG9ucyh3cmFwcGVyLCBjb250ZXh0Q29uZmlnKSB7XG4gICAgICAgIGlmICghIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iod3JhcHBlcikgfHwgdGhpcy5pc0FscmVhZHlSZW5kZXJlZCh3cmFwcGVyKSB8fCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIHBheXBhbC5CdXR0b25zICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3R5bGUgPSB3cmFwcGVyID09PSB0aGlzLmRlZmF1bHRDb25maWcuYnV0dG9uLndyYXBwZXIgPyB0aGlzLmRlZmF1bHRDb25maWcuYnV0dG9uLnN0eWxlIDogdGhpcy5kZWZhdWx0Q29uZmlnLmJ1dHRvbi5taW5pX2NhcnRfc3R5bGU7XG4gICAgICAgIHBheXBhbC5CdXR0b25zKHtcbiAgICAgICAgICAgIHN0eWxlLFxuICAgICAgICAgICAgLi4uY29udGV4dENvbmZpZyxcbiAgICAgICAgICAgIG9uQ2xpY2s6IHRoaXMub25TbWFydEJ1dHRvbkNsaWNrLFxuICAgICAgICAgICAgb25Jbml0OiB0aGlzLm9uU21hcnRCdXR0b25zSW5pdCxcbiAgICAgICAgfSkucmVuZGVyKHdyYXBwZXIpO1xuICAgIH1cblxuICAgIGlzQWxyZWFkeVJlbmRlcmVkKHdyYXBwZXIpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iod3JhcHBlcikuaGFzQ2hpbGROb2RlcygpO1xuICAgIH1cblxuICAgIGhpZGVCdXR0b25zKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZWxlbWVudCk7XG4gICAgICAgIGlmICghIGRvbUVsZW1lbnQgKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZG9tRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBzaG93QnV0dG9ucyhlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGVsZW1lbnQpO1xuICAgICAgICBpZiAoISBkb21FbGVtZW50ICkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGRvbUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGRpc2FibGVDcmVkaXRDYXJkRmllbGRzKCkge1xuICAgICAgICB0aGlzLmNyZWRpdENhcmRSZW5kZXJlci5kaXNhYmxlRmllbGRzKCk7XG4gICAgfVxuXG4gICAgZW5hYmxlQ3JlZGl0Q2FyZEZpZWxkcygpIHtcbiAgICAgICAgdGhpcy5jcmVkaXRDYXJkUmVuZGVyZXIuZW5hYmxlRmllbGRzKCk7XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBSZW5kZXJlcjtcbiIsImNvbnN0IGRjY0lucHV0RmFjdG9yeSA9IChvcmlnaW5hbCkgPT4ge1xuICAgIGNvbnN0IHN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKG9yaWdpbmFsKTtcbiAgICBjb25zdCBuZXdFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpO1xuICAgIG5ld0VsZW1lbnQuc2V0QXR0cmlidXRlKCdpZCcsIG9yaWdpbmFsLmlkKTtcbiAgICBPYmplY3QudmFsdWVzKHN0eWxlcykuZm9yRWFjaCggKHByb3ApID0+IHtcbiAgICAgICAgaWYgKCEgc3R5bGVzW3Byb3BdIHx8ICEgaXNOYU4ocHJvcCkgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbmV3RWxlbWVudC5zdHlsZS5zZXRQcm9wZXJ0eShwcm9wLCcnICsgc3R5bGVzW3Byb3BdKTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3RWxlbWVudDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGNjSW5wdXRGYWN0b3J5OyIsImltcG9ydCBkY2NJbnB1dEZhY3RvcnkgZnJvbSBcIi4uL0hlbHBlci9EY2NJbnB1dEZhY3RvcnlcIjtcblxuY2xhc3MgQ3JlZGl0Q2FyZFJlbmRlcmVyIHtcblxuICAgIGNvbnN0cnVjdG9yKGRlZmF1bHRDb25maWcsIGVycm9ySGFuZGxlciwgc3Bpbm5lcikge1xuICAgICAgICB0aGlzLmRlZmF1bHRDb25maWcgPSBkZWZhdWx0Q29uZmlnO1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcbiAgICAgICAgdGhpcy5zcGlubmVyID0gc3Bpbm5lcjtcbiAgICAgICAgdGhpcy5jYXJkVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5mb3JtVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UgPSBudWxsO1xuICAgIH1cblxuICAgIHJlbmRlcih3cmFwcGVyLCBjb250ZXh0Q29uZmlnKSB7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdENvbmZpZy5jb250ZXh0ICE9PSAnY2hlY2tvdXQnXG4gICAgICAgICAgICAgICAgJiYgdGhpcy5kZWZhdWx0Q29uZmlnLmNvbnRleHQgIT09ICdwYXktbm93J1xuICAgICAgICAgICAgKVxuICAgICAgICAgICAgfHwgd3JhcHBlciA9PT0gbnVsbFxuICAgICAgICAgICAgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih3cmFwcGVyKSA9PT0gbnVsbFxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0eXBlb2YgcGF5cGFsLkhvc3RlZEZpZWxkcyA9PT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgICAgIHx8ICEgcGF5cGFsLkhvc3RlZEZpZWxkcy5pc0VsaWdpYmxlKClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBjb25zdCB3cmFwcGVyRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iod3JhcHBlcik7XG4gICAgICAgICAgICB3cmFwcGVyRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHdyYXBwZXJFbGVtZW50KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZSkge1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UudGVhcmRvd24oKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlcnIgPT4gY29uc29sZS5lcnJvcihgSG9zdGVkIGZpZWxkcyB0ZWFyZG93biBlcnJvcjogJHtlcnJ9YCkpO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZ2F0ZVdheUJveCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5wYXltZW50X2JveC5wYXltZW50X21ldGhvZF9wcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXknKTtcbiAgICAgICAgY29uc3Qgb2xkRGlzcGxheVN0eWxlID0gZ2F0ZVdheUJveC5zdHlsZS5kaXNwbGF5O1xuICAgICAgICBnYXRlV2F5Qm94LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuXG4gICAgICAgIGNvbnN0IGhpZGVEY2NHYXRld2F5ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI3BwY3AtaGlkZS1kY2MnKTtcbiAgICAgICAgaWYgKGhpZGVEY2NHYXRld2F5KSB7XG4gICAgICAgICAgICBoaWRlRGNjR2F0ZXdheS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGhpZGVEY2NHYXRld2F5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNhcmROdW1iZXJGaWVsZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1udW1iZXInKTtcblxuICAgICAgICBjb25zdCBzdHlsZXNSYXcgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShjYXJkTnVtYmVyRmllbGQpO1xuICAgICAgICBsZXQgc3R5bGVzID0ge307XG4gICAgICAgIE9iamVjdC52YWx1ZXMoc3R5bGVzUmF3KS5mb3JFYWNoKCAocHJvcCkgPT4ge1xuICAgICAgICAgICAgaWYgKCEgc3R5bGVzUmF3W3Byb3BdKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3R5bGVzW3Byb3BdID0gJycgKyBzdHlsZXNSYXdbcHJvcF07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGNhcmROdW1iZXIgPSBkY2NJbnB1dEZhY3RvcnkoY2FyZE51bWJlckZpZWxkKTtcbiAgICAgICAgY2FyZE51bWJlckZpZWxkLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGNhcmROdW1iZXIsIGNhcmROdW1iZXJGaWVsZCk7XG5cbiAgICAgICAgY29uc3QgY2FyZEV4cGlyeUZpZWxkID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWV4cGlyeScpO1xuICAgICAgICBjb25zdCBjYXJkRXhwaXJ5ID0gZGNjSW5wdXRGYWN0b3J5KGNhcmRFeHBpcnlGaWVsZCk7XG4gICAgICAgIGNhcmRFeHBpcnlGaWVsZC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChjYXJkRXhwaXJ5LCBjYXJkRXhwaXJ5RmllbGQpO1xuXG4gICAgICAgIGNvbnN0IGNhcmRDb2RlRmllbGQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtY3ZjJyk7XG4gICAgICAgIGNvbnN0IGNhcmRDb2RlID0gZGNjSW5wdXRGYWN0b3J5KGNhcmRDb2RlRmllbGQpO1xuICAgICAgICBjYXJkQ29kZUZpZWxkLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGNhcmRDb2RlLCBjYXJkQ29kZUZpZWxkKTtcblxuICAgICAgICBnYXRlV2F5Qm94LnN0eWxlLmRpc3BsYXkgPSBvbGREaXNwbGF5U3R5bGU7XG5cbiAgICAgICAgY29uc3QgZm9ybVdyYXBwZXIgPSAnLnBheW1lbnRfYm94IHBheW1lbnRfbWV0aG9kX3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheSc7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuZGVmYXVsdENvbmZpZy5lbmZvcmNlX3ZhdWx0XG4gICAgICAgICAgICAmJiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGZvcm1XcmFwcGVyICsgJyAucHBjcC1jcmVkaXQtY2FyZC12YXVsdCcpXG4gICAgICAgICkge1xuICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihmb3JtV3JhcHBlciArICcgLnBwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKS5jaGVja2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZm9ybVdyYXBwZXIgKyAnIC5wcGNwLWNyZWRpdC1jYXJkLXZhdWx0Jykuc2V0QXR0cmlidXRlKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHBheXBhbC5Ib3N0ZWRGaWVsZHMucmVuZGVyKHtcbiAgICAgICAgICAgIGNyZWF0ZU9yZGVyOiBjb250ZXh0Q29uZmlnLmNyZWF0ZU9yZGVyLFxuICAgICAgICAgICAgc3R5bGVzOiB7XG4gICAgICAgICAgICAgICAgJ2lucHV0Jzogc3R5bGVzXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmllbGRzOiB7XG4gICAgICAgICAgICAgICAgbnVtYmVyOiB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLW51bWJlcicsXG4gICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB0aGlzLmRlZmF1bHRDb25maWcuaG9zdGVkX2ZpZWxkcy5sYWJlbHMuY3JlZGl0X2NhcmRfbnVtYmVyLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY3Z2OiB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yOiAnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWN2YycsXG4gICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyOiB0aGlzLmRlZmF1bHRDb25maWcuaG9zdGVkX2ZpZWxkcy5sYWJlbHMuY3Z2LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXhwaXJhdGlvbkRhdGU6IHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtZXhwaXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5tbV95eSxcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLnRoZW4oaG9zdGVkRmllbGRzID0+IHtcbiAgICAgICAgICAgIGRvY3VtZW50LmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KFwiaG9zdGVkX2ZpZWxkc19sb2FkZWRcIikpO1xuICAgICAgICAgICAgdGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UgPSBob3N0ZWRGaWVsZHM7XG5cbiAgICAgICAgICAgIGhvc3RlZEZpZWxkcy5vbignaW5wdXRTdWJtaXRSZXF1ZXN0JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3N1Ym1pdChjb250ZXh0Q29uZmlnKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaG9zdGVkRmllbGRzLm9uKCdjYXJkVHlwZUNoYW5nZScsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICggISBldmVudC5jYXJkcy5sZW5ndGggKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZFZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsaWRDYXJkcyA9IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLnZhbGlkX2NhcmRzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FyZFZhbGlkID0gdmFsaWRDYXJkcy5pbmRleE9mKGV2ZW50LmNhcmRzWzBdLnR5cGUpICE9PSAtMTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBob3N0ZWRGaWVsZHMub24oJ3ZhbGlkaXR5Q2hhbmdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybVZhbGlkID0gT2JqZWN0LmtleXMoZXZlbnQuZmllbGRzKS5ldmVyeShmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBldmVudC5maWVsZHNba2V5XS5pc1ZhbGlkO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgdGhpcy5mb3JtVmFsaWQgPSBmb3JtVmFsaWQ7XG5cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih3cmFwcGVyKS5nZXRBdHRyaWJ1dGUoJ2RhdGEtcHBjcC1zdWJzY3JpYmVkJykgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHdyYXBwZXIgKyAnIGJ1dHRvbicpLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICdjbGljaycsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdWJtaXQoY29udGV4dENvbmZpZyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih3cmFwcGVyKS5zZXRBdHRyaWJ1dGUoJ2RhdGEtcHBjcC1zdWJzY3JpYmVkJywgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwYXltZW50X21ldGhvZF9wcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXknKS5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgJ2NsaWNrJyxcbiAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdsYWJlbFtmb3I9cHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyXScpLmNsaWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIClcbiAgICB9XG5cbiAgICBkaXNhYmxlRmllbGRzKCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnNldEF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnNldEF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdjdnYnLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnNldEF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdleHBpcmF0aW9uRGF0ZScsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlOiAnZGlzYWJsZWQnXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZW5hYmxlRmllbGRzKCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnJlbW92ZUF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdudW1iZXInLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnJlbW92ZUF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdjdnYnLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlLnJlbW92ZUF0dHJpYnV0ZSh7XG4gICAgICAgICAgICAgICAgZmllbGQ6ICdleHBpcmF0aW9uRGF0ZScsXG4gICAgICAgICAgICAgICAgYXR0cmlidXRlOiAnZGlzYWJsZWQnXG4gICAgICAgICAgICB9KVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgX3N1Ym1pdChjb250ZXh0Q29uZmlnKSB7XG4gICAgICAgIHRoaXMuc3Bpbm5lci5ibG9jaygpO1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5jbGVhcigpO1xuXG4gICAgICAgIGlmICh0aGlzLmZvcm1WYWxpZCAmJiB0aGlzLmNhcmRWYWxpZCkge1xuICAgICAgICAgICAgY29uc3Qgc2F2ZV9jYXJkID0gdGhpcy5kZWZhdWx0Q29uZmlnLmNhbl9zYXZlX3ZhdWx0X3Rva2VuID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICAgICAgbGV0IHZhdWx0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKSA/XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKS5jaGVja2VkIDogc2F2ZV9jYXJkO1xuICAgICAgICAgICAgaWYgKHRoaXMuZGVmYXVsdENvbmZpZy5lbmZvcmNlX3ZhdWx0KSB7XG4gICAgICAgICAgICAgICAgdmF1bHQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY29udGluZ2VuY3kgPSB0aGlzLmRlZmF1bHRDb25maWcuaG9zdGVkX2ZpZWxkcy5jb250aW5nZW5jeTtcbiAgICAgICAgICAgIGNvbnN0IGhvc3RlZEZpZWxkc0RhdGEgPSB7XG4gICAgICAgICAgICAgICAgdmF1bHQ6IHZhdWx0XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKGNvbnRpbmdlbmN5ICE9PSAnTk9fM0RfU0VDVVJFJykge1xuICAgICAgICAgICAgICAgIGhvc3RlZEZpZWxkc0RhdGEuY29udGluZ2VuY2llcyA9IFtjb250aW5nZW5jeV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRlZmF1bHRDb25maWcucGF5ZXIpIHtcbiAgICAgICAgICAgICAgICBob3N0ZWRGaWVsZHNEYXRhLmNhcmRob2xkZXJOYW1lID0gdGhpcy5kZWZhdWx0Q29uZmlnLnBheWVyLm5hbWUuZ2l2ZW5fbmFtZSArICcgJyArIHRoaXMuZGVmYXVsdENvbmZpZy5wYXllci5uYW1lLnN1cm5hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWhvc3RlZEZpZWxkc0RhdGEuY2FyZGhvbGRlck5hbWUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdE5hbWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmlsbGluZ19maXJzdF9uYW1lJykgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmlsbGluZ19maXJzdF9uYW1lJykudmFsdWUgOiAnJztcbiAgICAgICAgICAgICAgICBjb25zdCBsYXN0TmFtZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdiaWxsaW5nX2xhc3RfbmFtZScpID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbGxpbmdfbGFzdF9uYW1lJykudmFsdWUgOiAnJztcblxuICAgICAgICAgICAgICAgIGlmICghZmlyc3ROYW1lIHx8ICFsYXN0TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5tZXNzYWdlKHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5jYXJkaG9sZGVyX25hbWVfcmVxdWlyZWQpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaG9zdGVkRmllbGRzRGF0YS5jYXJkaG9sZGVyTmFtZSA9IGZpcnN0TmFtZSArICcgJyArIGxhc3ROYW1lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5zdWJtaXQoaG9zdGVkRmllbGRzRGF0YSkudGhlbigocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgICAgIHBheWxvYWQub3JkZXJJRCA9IHBheWxvYWQub3JkZXJJZDtcbiAgICAgICAgICAgICAgICB0aGlzLnNwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjb250ZXh0Q29uZmlnLm9uQXBwcm92ZShwYXlsb2FkKTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5jbGVhcigpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGVyci5kZXRhaWxzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLm1lc3NhZ2UoZXJyLmRldGFpbHMubWFwKGQgPT4gYCR7ZC5pc3N1ZX0gJHtkLmRlc2NyaXB0aW9ufWApLmpvaW4oJzxici8+JyksIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSAhIHRoaXMuY2FyZFZhbGlkID8gdGhpcy5kZWZhdWx0Q29uZmlnLmhvc3RlZF9maWVsZHMubGFiZWxzLmNhcmRfbm90X3N1cHBvcnRlZCA6IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5maWVsZHNfbm90X3ZhbGlkO1xuICAgICAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIubWVzc2FnZShtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbmV4cG9ydCBkZWZhdWx0IENyZWRpdENhcmRSZW5kZXJlcjtcbiIsImNvbnN0IHN0b3JhZ2VLZXkgPSAncHBjcC1kYXRhLWNsaWVudC1pZCc7XG5cbmNvbnN0IHZhbGlkYXRlVG9rZW4gPSAodG9rZW4sIHVzZXIpID0+IHtcbiAgICBpZiAoISB0b2tlbikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmICh0b2tlbi51c2VyICE9PSB1c2VyKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICBjb25zdCBpc0V4cGlyZWQgPSBjdXJyZW50VGltZSA+PSB0b2tlbi5leHBpcmF0aW9uICogMTAwMDtcbiAgICByZXR1cm4gISBpc0V4cGlyZWQ7XG59XG5cbmNvbnN0IHN0b3JlZFRva2VuRm9yVXNlciA9ICh1c2VyKSA9PiB7XG4gICAgY29uc3QgdG9rZW4gPSBKU09OLnBhcnNlKHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oc3RvcmFnZUtleSkpO1xuICAgIGlmICh2YWxpZGF0ZVRva2VuKHRva2VuLCB1c2VyKSkge1xuICAgICAgICByZXR1cm4gdG9rZW4udG9rZW47XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5jb25zdCBzdG9yZVRva2VuID0gKHRva2VuKSA9PiB7XG4gICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShzdG9yYWdlS2V5LCBKU09OLnN0cmluZ2lmeSh0b2tlbikpO1xufVxuXG5jb25zdCBkYXRhQ2xpZW50SWRBdHRyaWJ1dGVIYW5kbGVyID0gKHNjcmlwdCwgY29uZmlnKSA9PiB7XG4gICAgZmV0Y2goY29uZmlnLmVuZHBvaW50LCB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBub25jZTogY29uZmlnLm5vbmNlXG4gICAgICAgIH0pXG4gICAgfSkudGhlbigocmVzKT0+e1xuICAgICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICB9KS50aGVuKChkYXRhKT0+e1xuICAgICAgICBjb25zdCBpc1ZhbGlkID0gdmFsaWRhdGVUb2tlbihkYXRhLCBjb25maWcudXNlcik7XG4gICAgICAgIGlmICghaXNWYWxpZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0b3JlVG9rZW4oZGF0YSk7XG4gICAgICAgIHNjcmlwdC5zZXRBdHRyaWJ1dGUoJ2RhdGEtY2xpZW50LXRva2VuJywgZGF0YS50b2tlbik7XG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kKHNjcmlwdCk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGRhdGFDbGllbnRJZEF0dHJpYnV0ZUhhbmRsZXI7XG4iLCJjbGFzcyBNZXNzYWdlUmVuZGVyZXIge1xuXG4gICAgY29uc3RydWN0b3IoY29uZmlnKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgIH1cblxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgaWYgKCEgdGhpcy5zaG91bGRSZW5kZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcGF5cGFsLk1lc3NhZ2VzKHtcbiAgICAgICAgICAgIGFtb3VudDogdGhpcy5jb25maWcuYW1vdW50LFxuICAgICAgICAgICAgcGxhY2VtZW50OiB0aGlzLmNvbmZpZy5wbGFjZW1lbnQsXG4gICAgICAgICAgICBzdHlsZTogdGhpcy5jb25maWcuc3R5bGVcbiAgICAgICAgfSkucmVuZGVyKHRoaXMuY29uZmlnLndyYXBwZXIpO1xuICAgIH1cblxuICAgIHJlbmRlcldpdGhBbW91bnQoYW1vdW50KSB7XG5cbiAgICAgICAgaWYgKCEgdGhpcy5zaG91bGRSZW5kZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbmV3V3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBuZXdXcmFwcGVyLnNldEF0dHJpYnV0ZSgnaWQnLCB0aGlzLmNvbmZpZy53cmFwcGVyLnJlcGxhY2UoJyMnLCAnJykpO1xuXG4gICAgICAgIGNvbnN0IHNpYmxpbmcgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuY29uZmlnLndyYXBwZXIpLm5leHRTaWJsaW5nO1xuICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuY29uZmlnLndyYXBwZXIpLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmNvbmZpZy53cmFwcGVyKSk7XG4gICAgICAgIHNpYmxpbmcucGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUobmV3V3JhcHBlciwgc2libGluZyk7XG4gICAgICAgIHBheXBhbC5NZXNzYWdlcyh7XG4gICAgICAgICAgICBhbW91bnQsXG4gICAgICAgICAgICBwbGFjZW1lbnQ6IHRoaXMuY29uZmlnLnBsYWNlbWVudCxcbiAgICAgICAgICAgIHN0eWxlOiB0aGlzLmNvbmZpZy5zdHlsZVxuICAgICAgICB9KS5yZW5kZXIodGhpcy5jb25maWcud3JhcHBlcik7XG4gICAgfVxuXG4gICAgc2hvdWxkUmVuZGVyKCkge1xuXG4gICAgICAgIGlmICh0eXBlb2YgcGF5cGFsLk1lc3NhZ2VzID09PSAndW5kZWZpbmVkJyB8fCB0eXBlb2YgdGhpcy5jb25maWcud3JhcHBlciA9PT0gJ3VuZGVmaW5lZCcgKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmNvbmZpZy53cmFwcGVyKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbn1cbmV4cG9ydCBkZWZhdWx0IE1lc3NhZ2VSZW5kZXJlcjsiLCJjbGFzcyBTcGlubmVyIHtcblxuICAgIGNvbnN0cnVjdG9yKHRhcmdldCA9ICdmb3JtLndvb2NvbW1lcmNlLWNoZWNrb3V0Jykge1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICB9XG5cbiAgICBzZXRUYXJnZXQodGFyZ2V0KSB7XG4gICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgIH1cblxuICAgIGJsb2NrKCkge1xuXG4gICAgICAgIGpRdWVyeSggdGhpcy50YXJnZXQgKS5ibG9jayh7XG4gICAgICAgICAgICBtZXNzYWdlOiBudWxsLFxuICAgICAgICAgICAgb3ZlcmxheUNTUzoge1xuICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICcjZmZmJyxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwLjZcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdW5ibG9jaygpIHtcblxuICAgICAgICBqUXVlcnkoIHRoaXMudGFyZ2V0ICkudW5ibG9jaygpO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgU3Bpbm5lcjtcbiIsImltcG9ydCBNaW5pQ2FydEJvb3RzdGFwIGZyb20gJy4vbW9kdWxlcy9Db250ZXh0Qm9vdHN0cmFwL01pbmlDYXJ0Qm9vdHN0YXAnO1xuaW1wb3J0IFNpbmdsZVByb2R1Y3RCb290c3RhcCBmcm9tICcuL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9TaW5nbGVQcm9kdWN0Qm9vdHN0YXAnO1xuaW1wb3J0IENhcnRCb290c3RyYXAgZnJvbSAnLi9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvQ2FydEJvb3RzdGFwJztcbmltcG9ydCBDaGVja291dEJvb3RzdGFwIGZyb20gJy4vbW9kdWxlcy9Db250ZXh0Qm9vdHN0cmFwL0NoZWNrb3V0Qm9vdHN0YXAnO1xuaW1wb3J0IFBheU5vd0Jvb3RzdHJhcCBmcm9tIFwiLi9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvUGF5Tm93Qm9vdHN0cmFwXCI7XG5pbXBvcnQgUmVuZGVyZXIgZnJvbSAnLi9tb2R1bGVzL1JlbmRlcmVyL1JlbmRlcmVyJztcbmltcG9ydCBFcnJvckhhbmRsZXIgZnJvbSAnLi9tb2R1bGVzL0Vycm9ySGFuZGxlcic7XG5pbXBvcnQgQ3JlZGl0Q2FyZFJlbmRlcmVyIGZyb20gXCIuL21vZHVsZXMvUmVuZGVyZXIvQ3JlZGl0Q2FyZFJlbmRlcmVyXCI7XG5pbXBvcnQgZGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlciBmcm9tIFwiLi9tb2R1bGVzL0RhdGFDbGllbnRJZEF0dHJpYnV0ZUhhbmRsZXJcIjtcbmltcG9ydCBNZXNzYWdlUmVuZGVyZXIgZnJvbSBcIi4vbW9kdWxlcy9SZW5kZXJlci9NZXNzYWdlUmVuZGVyZXJcIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuL21vZHVsZXMvSGVscGVyL1NwaW5uZXJcIjtcbmltcG9ydCB7XG4gICAgZ2V0Q3VycmVudFBheW1lbnRNZXRob2QsXG4gICAgT1JERVJfQlVUVE9OX1NFTEVDVE9SLFxuICAgIFBheW1lbnRNZXRob2RzXG59IGZyb20gXCIuL21vZHVsZXMvSGVscGVyL0NoZWNrb3V0TWV0aG9kU3RhdGVcIjtcbmltcG9ydCB7aGlkZSwgc2V0VmlzaWJsZX0gZnJvbSBcIi4vbW9kdWxlcy9IZWxwZXIvSGlkaW5nXCI7XG5pbXBvcnQge2lzQ2hhbmdlUGF5bWVudFBhZ2V9IGZyb20gXCIuL21vZHVsZXMvSGVscGVyL1N1YnNjcmlwdGlvbnNcIjtcblxuY29uc3QgYnV0dG9uc1NwaW5uZXIgPSBuZXcgU3Bpbm5lcignLnBwYy1idXR0b24td3JhcHBlcicpO1xuXG5jb25zdCBib290c3RyYXAgPSAoKSA9PiB7XG4gICAgY29uc3QgZXJyb3JIYW5kbGVyID0gbmV3IEVycm9ySGFuZGxlcihQYXlQYWxDb21tZXJjZUdhdGV3YXkubGFiZWxzLmVycm9yLmdlbmVyaWMpO1xuICAgIGNvbnN0IHNwaW5uZXIgPSBuZXcgU3Bpbm5lcigpO1xuICAgIGNvbnN0IGNyZWRpdENhcmRSZW5kZXJlciA9IG5ldyBDcmVkaXRDYXJkUmVuZGVyZXIoUGF5UGFsQ29tbWVyY2VHYXRld2F5LCBlcnJvckhhbmRsZXIsIHNwaW5uZXIpO1xuICAgIGNvbnN0IG9uU21hcnRCdXR0b25DbGljayA9IGRhdGEgPT4ge1xuICAgICAgICB3aW5kb3cucHBjcEZ1bmRpbmdTb3VyY2UgPSBkYXRhLmZ1bmRpbmdTb3VyY2U7XG4gICAgfTtcbiAgICBjb25zdCBvblNtYXJ0QnV0dG9uc0luaXQgPSAoKSA9PiB7XG4gICAgICAgIGJ1dHRvbnNTcGlubmVyLnVuYmxvY2soKTtcbiAgICB9O1xuICAgIGNvbnN0IHJlbmRlcmVyID0gbmV3IFJlbmRlcmVyKGNyZWRpdENhcmRSZW5kZXJlciwgUGF5UGFsQ29tbWVyY2VHYXRld2F5LCBvblNtYXJ0QnV0dG9uQ2xpY2ssIG9uU21hcnRCdXR0b25zSW5pdCk7XG4gICAgY29uc3QgbWVzc2FnZVJlbmRlcmVyID0gbmV3IE1lc3NhZ2VSZW5kZXJlcihQYXlQYWxDb21tZXJjZUdhdGV3YXkubWVzc2FnZXMpO1xuICAgIGNvbnN0IGNvbnRleHQgPSBQYXlQYWxDb21tZXJjZUdhdGV3YXkuY29udGV4dDtcbiAgICBpZiAoY29udGV4dCA9PT0gJ21pbmktY2FydCcgfHwgY29udGV4dCA9PT0gJ3Byb2R1Y3QnKSB7XG4gICAgICAgIGlmIChQYXlQYWxDb21tZXJjZUdhdGV3YXkubWluaV9jYXJ0X2J1dHRvbnNfZW5hYmxlZCA9PT0gJzEnKSB7XG4gICAgICAgICAgICBjb25zdCBtaW5pQ2FydEJvb3RzdHJhcCA9IG5ldyBNaW5pQ2FydEJvb3RzdGFwKFxuICAgICAgICAgICAgICAgIFBheVBhbENvbW1lcmNlR2F0ZXdheSxcbiAgICAgICAgICAgICAgICByZW5kZXJlclxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgbWluaUNhcnRCb290c3RyYXAuaW5pdCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgPT09ICdwcm9kdWN0JyAmJiBQYXlQYWxDb21tZXJjZUdhdGV3YXkuc2luZ2xlX3Byb2R1Y3RfYnV0dG9uc19lbmFibGVkID09PSAnMScpIHtcbiAgICAgICAgY29uc3Qgc2luZ2xlUHJvZHVjdEJvb3RzdHJhcCA9IG5ldyBTaW5nbGVQcm9kdWN0Qm9vdHN0YXAoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICByZW5kZXJlcixcbiAgICAgICAgICAgIG1lc3NhZ2VSZW5kZXJlcixcbiAgICAgICAgKTtcblxuICAgICAgICBzaW5nbGVQcm9kdWN0Qm9vdHN0cmFwLmluaXQoKTtcbiAgICB9XG5cbiAgICBpZiAoY29udGV4dCA9PT0gJ2NhcnQnKSB7XG4gICAgICAgIGNvbnN0IGNhcnRCb290c3RyYXAgPSBuZXcgQ2FydEJvb3RzdHJhcChcbiAgICAgICAgICAgIFBheVBhbENvbW1lcmNlR2F0ZXdheSxcbiAgICAgICAgICAgIHJlbmRlcmVyLFxuICAgICAgICApO1xuXG4gICAgICAgIGNhcnRCb290c3RyYXAuaW5pdCgpO1xuICAgIH1cblxuICAgIGlmIChjb250ZXh0ID09PSAnY2hlY2tvdXQnKSB7XG4gICAgICAgIGNvbnN0IGNoZWNrb3V0Qm9vdHN0YXAgPSBuZXcgQ2hlY2tvdXRCb290c3RhcChcbiAgICAgICAgICAgIFBheVBhbENvbW1lcmNlR2F0ZXdheSxcbiAgICAgICAgICAgIHJlbmRlcmVyLFxuICAgICAgICAgICAgbWVzc2FnZVJlbmRlcmVyLFxuICAgICAgICAgICAgc3Bpbm5lclxuICAgICAgICApO1xuXG4gICAgICAgIGNoZWNrb3V0Qm9vdHN0YXAuaW5pdCgpO1xuICAgIH1cblxuICAgIGlmIChjb250ZXh0ID09PSAncGF5LW5vdycgKSB7XG4gICAgICAgIGNvbnN0IHBheU5vd0Jvb3RzdHJhcCA9IG5ldyBQYXlOb3dCb290c3RyYXAoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICByZW5kZXJlcixcbiAgICAgICAgICAgIG1lc3NhZ2VSZW5kZXJlcixcbiAgICAgICAgICAgIHNwaW5uZXJcbiAgICAgICAgKTtcbiAgICAgICAgcGF5Tm93Qm9vdHN0cmFwLmluaXQoKTtcbiAgICB9XG5cbiAgICBpZiAoY29udGV4dCAhPT0gJ2NoZWNrb3V0Jykge1xuICAgICAgICBtZXNzYWdlUmVuZGVyZXIucmVuZGVyKCk7XG4gICAgfVxufTtcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgJ0RPTUNvbnRlbnRMb2FkZWQnLFxuICAgICgpID0+IHtcbiAgICAgICAgaWYgKCF0eXBlb2YgKFBheVBhbENvbW1lcmNlR2F0ZXdheSkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1BheVBhbCBidXR0b24gY291bGQgbm90IGJlIGNvbmZpZ3VyZWQuJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXkuY29udGV4dCAhPT0gJ2NoZWNrb3V0J1xuICAgICAgICAgICAgJiYgUGF5UGFsQ29tbWVyY2VHYXRld2F5LmRhdGFfY2xpZW50X2lkLnVzZXIgPT09IDBcbiAgICAgICAgICAgICYmIFBheVBhbENvbW1lcmNlR2F0ZXdheS5kYXRhX2NsaWVudF9pZC5oYXNfc3Vic2NyaXB0aW9uc1xuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvbWV0aW1lcyBQYXlQYWwgc2NyaXB0IHRha2VzIGxvbmcgdGltZSB0byBsb2FkLFxuICAgICAgICAvLyBzbyB3ZSBhZGRpdGlvbmFsbHkgaGlkZSB0aGUgc3RhbmRhcmQgb3JkZXIgYnV0dG9uIGhlcmUgdG8gYXZvaWQgZmFpbGVkIG9yZGVycy5cbiAgICAgICAgLy8gTm9ybWFsbHkgaXQgaXMgaGlkZGVuIGxhdGVyIGFmdGVyIHRoZSBzY3JpcHQgbG9hZC5cbiAgICAgICAgY29uc3QgaGlkZU9yZGVyQnV0dG9uSWZQcGNwR2F0ZXdheSA9ICgpID0+IHtcbiAgICAgICAgICAgIC8vIG9ubHkgaW4gY2hlY2tvdXQgYW5kIHBheSBub3cgcGFnZSwgb3RoZXJ3aXNlIGl0IG1heSBicmVhayB0aGluZ3MgKGUuZy4gcGF5bWVudCB2aWEgcHJvZHVjdCBwYWdlKSxcbiAgICAgICAgICAgIC8vIGFuZCBhbHNvIHRoZSBsb2FkaW5nIHNwaW5uZXIgbWF5IGxvb2sgd2VpcmQgb24gb3RoZXIgcGFnZXNcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAhWydjaGVja291dCcsICdwYXktbm93J10uaW5jbHVkZXMoUGF5UGFsQ29tbWVyY2VHYXRld2F5LmNvbnRleHQpXG4gICAgICAgICAgICAgICAgfHwgaXNDaGFuZ2VQYXltZW50UGFnZSgpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRQYXltZW50TWV0aG9kID0gZ2V0Q3VycmVudFBheW1lbnRNZXRob2QoKTtcbiAgICAgICAgICAgIGNvbnN0IGlzUGF5cGFsID0gY3VycmVudFBheW1lbnRNZXRob2QgPT09IFBheW1lbnRNZXRob2RzLlBBWVBBTDtcblxuICAgICAgICAgICAgc2V0VmlzaWJsZShPUkRFUl9CVVRUT05fU0VMRUNUT1IsICFpc1BheXBhbCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIGlmIChpc1BheXBhbCkge1xuICAgICAgICAgICAgICAgIC8vIHN0b3BwZWQgYWZ0ZXIgdGhlIGZpcnN0IHJlbmRlcmluZyBvZiB0aGUgYnV0dG9ucywgaW4gb25Jbml0XG4gICAgICAgICAgICAgICAgYnV0dG9uc1NwaW5uZXIuYmxvY2soKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYnV0dG9uc1NwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGJvb3RzdHJhcHBlZCA9IGZhbHNlO1xuXG4gICAgICAgIGhpZGVPcmRlckJ1dHRvbklmUHBjcEdhdGV3YXkoKTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQuYm9keSkub24oJ3VwZGF0ZWRfY2hlY2tvdXQgcGF5bWVudF9tZXRob2Rfc2VsZWN0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYm9vdHN0cmFwcGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoaWRlT3JkZXJCdXR0b25JZlBwY3BHYXRld2F5KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICBzY3JpcHQuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgYm9vdHN0cmFwcGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgYm9vdHN0cmFwKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCdzcmMnLCBQYXlQYWxDb21tZXJjZUdhdGV3YXkuYnV0dG9uLnVybCk7XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKFBheVBhbENvbW1lcmNlR2F0ZXdheS5zY3JpcHRfYXR0cmlidXRlcykuZm9yRWFjaChcbiAgICAgICAgICAgIChrZXlWYWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIHNjcmlwdC5zZXRBdHRyaWJ1dGUoa2V5VmFsdWVbMF0sIGtleVZhbHVlWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoUGF5UGFsQ29tbWVyY2VHYXRld2F5LmRhdGFfY2xpZW50X2lkLnNldF9hdHRyaWJ1dGUpIHtcbiAgICAgICAgICAgIGRhdGFDbGllbnRJZEF0dHJpYnV0ZUhhbmRsZXIoc2NyaXB0LCBQYXlQYWxDb21tZXJjZUdhdGV3YXkuZGF0YV9jbGllbnRfaWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQoc2NyaXB0KTtcbiAgICB9LFxuKTtcbiJdLCJuYW1lcyI6WyJFcnJvckhhbmRsZXIiLCJjb25zdHJ1Y3RvciIsImdlbmVyaWNFcnJvclRleHQiLCJ3cmFwcGVyIiwiZG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yIiwibWVzc2FnZXNMaXN0IiwiZ2VuZXJpY0Vycm9yIiwiY2xhc3NMaXN0IiwiY29udGFpbnMiLCJjbGVhciIsIm1lc3NhZ2UiLCJhcHBlbmRQcmVwYXJlZEVycm9yTWVzc2FnZUVsZW1lbnQiLCJlcnJvck1lc3NhZ2VFbGVtZW50IiwicHJlcGFyZU1lc3NhZ2VzTGlzdCIsInJlcGxhY2VXaXRoIiwidGV4dCIsInBlcnNpc3QiLCJTdHJpbmciLCJsZW5ndGgiLCJFcnJvciIsImFkZCIsInJlbW92ZSIsIm1lc3NhZ2VOb2RlIiwicHJlcGFyZU1lc3NhZ2VzTGlzdEl0ZW0iLCJhcHBlbmRDaGlsZCIsImpRdWVyeSIsInNjcm9sbF90b19ub3RpY2VzIiwiY3JlYXRlRWxlbWVudCIsInNldEF0dHJpYnV0ZSIsImxpIiwiaW5uZXJIVE1MIiwic2FuaXRpemUiLCJ0ZXh0YXJlYSIsInZhbHVlIiwicmVwbGFjZSIsIm9uQXBwcm92ZSIsImNvbnRleHQiLCJlcnJvckhhbmRsZXIiLCJkYXRhIiwiYWN0aW9ucyIsImZldGNoIiwiY29uZmlnIiwiYWpheCIsImFwcHJvdmVfb3JkZXIiLCJlbmRwb2ludCIsIm1ldGhvZCIsImJvZHkiLCJKU09OIiwic3RyaW5naWZ5Iiwibm9uY2UiLCJvcmRlcl9pZCIsIm9yZGVySUQiLCJmdW5kaW5nX3NvdXJjZSIsIndpbmRvdyIsInBwY3BGdW5kaW5nU291cmNlIiwidGhlbiIsInJlcyIsImpzb24iLCJzdWNjZXNzIiwicmVzdGFydCIsImNhdGNoIiwiZXJyIiwibG9jYXRpb24iLCJocmVmIiwicmVkaXJlY3QiLCJwYXllckRhdGEiLCJwYXllciIsIlBheVBhbENvbW1lcmNlR2F0ZXdheSIsInBob25lIiwicGhvbmVfdHlwZSIsInBob25lX251bWJlciIsIm5hdGlvbmFsX251bWJlciIsImVtYWlsX2FkZHJlc3MiLCJuYW1lIiwic3VybmFtZSIsImdpdmVuX25hbWUiLCJhZGRyZXNzIiwiY291bnRyeV9jb2RlIiwiYWRkcmVzc19saW5lXzEiLCJhZGRyZXNzX2xpbmVfMiIsImFkbWluX2FyZWFfMSIsImFkbWluX2FyZWFfMiIsInBvc3RhbF9jb2RlIiwiQ2FydEFjdGlvbkhhbmRsZXIiLCJjb25maWd1cmF0aW9uIiwiY3JlYXRlT3JkZXIiLCJibkNvZGUiLCJibl9jb2RlcyIsImNyZWF0ZV9vcmRlciIsInB1cmNoYXNlX3VuaXRzIiwiYm5fY29kZSIsImNvbnNvbGUiLCJlcnJvciIsImlkIiwib25FcnJvciIsIk1pbmlDYXJ0Qm9vdHN0YXAiLCJnYXRld2F5IiwicmVuZGVyZXIiLCJhY3Rpb25IYW5kbGVyIiwiaW5pdCIsImxhYmVscyIsImdlbmVyaWMiLCJyZW5kZXIiLCJvbiIsInNob3VsZFJlbmRlciIsImJ1dHRvbiIsIm1pbmlfY2FydF93cmFwcGVyIiwiaG9zdGVkX2ZpZWxkcyIsIlByb2R1Y3QiLCJVcGRhdGVDYXJ0IiwidXBkYXRlIiwib25SZXNvbHZlIiwicHJvZHVjdHMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInJlc3VsdCIsInJlc29sdmVkIiwiQnV0dG9uc1RvZ2dsZUxpc3RlbmVyIiwiZWxlbWVudCIsInNob3dDYWxsYmFjayIsImhpZGVDYWxsYmFjayIsIm9ic2VydmVyIiwiYXR0cmlidXRlcyIsImNhbGxiYWNrIiwiTXV0YXRpb25PYnNlcnZlciIsIm9ic2VydmUiLCJkaXNjb25uZWN0IiwicXVhbnRpdHkiLCJ2YXJpYXRpb25zIiwiU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIiLCJ1cGRhdGVDYXJ0Iiwic2hvd0J1dHRvbkNhbGxiYWNrIiwiaGlkZUJ1dHRvbkNhbGxiYWNrIiwiZm9ybUVsZW1lbnQiLCJoYXNWYXJpYXRpb25zIiwiZ2V0UHJvZHVjdHMiLCJpc0dyb3VwZWRQcm9kdWN0IiwicXR5IiwicXVlcnlTZWxlY3RvckFsbCIsImZvckVhY2giLCJlbGVtZW50TmFtZSIsImdldEF0dHJpYnV0ZSIsIm1hdGNoIiwicGFyc2VJbnQiLCJwdXNoIiwicHJvbWlzZSIsIm1hcCIsIlNpbmdsZVByb2R1Y3RCb290c3RhcCIsIm1lc3NhZ2VzIiwiaGFuZGxlQ2hhbmdlIiwiaGlkZUJ1dHRvbnMiLCJhZGRFdmVudExpc3RlbmVyIiwiYmluZCIsInByaWNlQW1vdW50SXNaZXJvIiwicHJpY2VUZXh0IiwiaW5uZXJUZXh0IiwiYW1vdW50IiwicGFyc2VGbG9hdCIsImNoYW5nZV9jYXJ0Iiwic2hvd0J1dHRvbnMiLCJyZW5kZXJXaXRoQW1vdW50IiwiQ2FydEJvb3RzdHJhcCIsInNwaW5uZXIiLCJibG9jayIsInVuYmxvY2siLCJjb2RlIiwiY2xpY2siLCJDaGVja291dEFjdGlvbkhhbmRsZXIiLCJmb3JtU2VsZWN0b3IiLCJmb3JtVmFsdWVzIiwic2VyaWFsaXplIiwiY3JlYXRlYWNjb3VudCIsImlzIiwiZm9ybSIsImRvbVBhcnNlciIsIkRPTVBhcnNlciIsInBhcnNlRnJvbVN0cmluZyIsImRldGFpbHMiLCJkIiwiaXNzdWUiLCJkZXNjcmlwdGlvbiIsImpvaW4iLCJpbnB1dCIsImN1c3RvbV9pZCIsImFwcGVuZCIsIm9uQ2FuY2VsIiwiZ2V0RWxlbWVudCIsInNlbGVjdG9yT3JFbGVtZW50IiwiaXNWaXNpYmxlIiwib2Zmc2V0V2lkdGgiLCJvZmZzZXRIZWlnaHQiLCJnZXRDbGllbnRSZWN0cyIsInNldFZpc2libGUiLCJzaG93IiwiaW1wb3J0YW50IiwiY3VycmVudFZhbHVlIiwic3R5bGUiLCJnZXRQcm9wZXJ0eVZhbHVlIiwic2V0UHJvcGVydHkiLCJyZW1vdmVQcm9wZXJ0eSIsImhpZGUiLCJQYXltZW50TWV0aG9kcyIsIlBBWVBBTCIsIkNBUkRTIiwiT1JERVJfQlVUVE9OX1NFTEVDVE9SIiwiZ2V0Q3VycmVudFBheW1lbnRNZXRob2QiLCJlbCIsImlzU2F2ZWRDYXJkU2VsZWN0ZWQiLCJzYXZlZENhcmRMaXN0IiwiQ2hlY2tvdXRCb290c3RhcCIsInN0YW5kYXJkT3JkZXJCdXR0b25TZWxlY3RvciIsImJ1dHRvbkNoYW5nZU9ic2VydmVyIiwidXBkYXRlVWkiLCJ2YWwiLCJjYW5jZWxfd3JhcHBlciIsImN1cnJlbnRQYXltZW50TWV0aG9kIiwiaXNQYXlwYWwiLCJpc0NhcmQiLCJpc1NhdmVkQ2FyZCIsImlzTm90T3VyR2F0ZXdheSIsImRpc2FibGVDcmVkaXRDYXJkRmllbGRzIiwiZW5hYmxlQ3JlZGl0Q2FyZEZpZWxkcyIsImFkZENsYXNzIiwiYXR0ciIsInJlbW92ZUNsYXNzIiwiaXNDaGFuZ2VQYXltZW50UGFnZSIsInVybFBhcmFtcyIsIlVSTFNlYXJjaFBhcmFtcyIsInNlYXJjaCIsImhhcyIsIlBheU5vd0Jvb3RzdHJhcCIsIlJlbmRlcmVyIiwiY3JlZGl0Q2FyZFJlbmRlcmVyIiwiZGVmYXVsdENvbmZpZyIsIm9uU21hcnRCdXR0b25DbGljayIsIm9uU21hcnRCdXR0b25zSW5pdCIsImhvc3RlZEZpZWxkc1dyYXBwZXIiLCJjb250ZXh0Q29uZmlnIiwicmVuZGVyQnV0dG9ucyIsImlzQWxyZWFkeVJlbmRlcmVkIiwicGF5cGFsIiwiQnV0dG9ucyIsIm1pbmlfY2FydF9zdHlsZSIsIm9uQ2xpY2siLCJvbkluaXQiLCJoYXNDaGlsZE5vZGVzIiwiZG9tRWxlbWVudCIsImRpc3BsYXkiLCJkaXNhYmxlRmllbGRzIiwiZW5hYmxlRmllbGRzIiwiZGNjSW5wdXRGYWN0b3J5Iiwib3JpZ2luYWwiLCJzdHlsZXMiLCJnZXRDb21wdXRlZFN0eWxlIiwibmV3RWxlbWVudCIsIk9iamVjdCIsInZhbHVlcyIsInByb3AiLCJpc05hTiIsIkNyZWRpdENhcmRSZW5kZXJlciIsImNhcmRWYWxpZCIsImZvcm1WYWxpZCIsImN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZSIsIkhvc3RlZEZpZWxkcyIsImlzRWxpZ2libGUiLCJ3cmFwcGVyRWxlbWVudCIsInBhcmVudE5vZGUiLCJyZW1vdmVDaGlsZCIsInRlYXJkb3duIiwiZ2F0ZVdheUJveCIsIm9sZERpc3BsYXlTdHlsZSIsImhpZGVEY2NHYXRld2F5IiwiY2FyZE51bWJlckZpZWxkIiwic3R5bGVzUmF3IiwiY2FyZE51bWJlciIsInJlcGxhY2VDaGlsZCIsImNhcmRFeHBpcnlGaWVsZCIsImNhcmRFeHBpcnkiLCJjYXJkQ29kZUZpZWxkIiwiY2FyZENvZGUiLCJmb3JtV3JhcHBlciIsImVuZm9yY2VfdmF1bHQiLCJjaGVja2VkIiwiZmllbGRzIiwibnVtYmVyIiwic2VsZWN0b3IiLCJwbGFjZWhvbGRlciIsImNyZWRpdF9jYXJkX251bWJlciIsImN2diIsImV4cGlyYXRpb25EYXRlIiwibW1feXkiLCJob3N0ZWRGaWVsZHMiLCJkaXNwYXRjaEV2ZW50IiwiQ3VzdG9tRXZlbnQiLCJfc3VibWl0IiwiZXZlbnQiLCJjYXJkcyIsInZhbGlkQ2FyZHMiLCJ2YWxpZF9jYXJkcyIsImluZGV4T2YiLCJ0eXBlIiwia2V5cyIsImV2ZXJ5Iiwia2V5IiwiaXNWYWxpZCIsInByZXZlbnREZWZhdWx0IiwiZmllbGQiLCJhdHRyaWJ1dGUiLCJyZW1vdmVBdHRyaWJ1dGUiLCJzYXZlX2NhcmQiLCJjYW5fc2F2ZV92YXVsdF90b2tlbiIsInZhdWx0IiwiZ2V0RWxlbWVudEJ5SWQiLCJjb250aW5nZW5jeSIsImhvc3RlZEZpZWxkc0RhdGEiLCJjb250aW5nZW5jaWVzIiwiY2FyZGhvbGRlck5hbWUiLCJmaXJzdE5hbWUiLCJsYXN0TmFtZSIsImNhcmRob2xkZXJfbmFtZV9yZXF1aXJlZCIsInN1Ym1pdCIsInBheWxvYWQiLCJvcmRlcklkIiwiY2FyZF9ub3Rfc3VwcG9ydGVkIiwiZmllbGRzX25vdF92YWxpZCIsInN0b3JhZ2VLZXkiLCJ2YWxpZGF0ZVRva2VuIiwidG9rZW4iLCJ1c2VyIiwiY3VycmVudFRpbWUiLCJEYXRlIiwiZ2V0VGltZSIsImlzRXhwaXJlZCIsImV4cGlyYXRpb24iLCJzdG9yZWRUb2tlbkZvclVzZXIiLCJwYXJzZSIsInNlc3Npb25TdG9yYWdlIiwiZ2V0SXRlbSIsInN0b3JlVG9rZW4iLCJzZXRJdGVtIiwiZGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlciIsInNjcmlwdCIsIk1lc3NhZ2VSZW5kZXJlciIsIk1lc3NhZ2VzIiwicGxhY2VtZW50IiwibmV3V3JhcHBlciIsInNpYmxpbmciLCJuZXh0U2libGluZyIsInBhcmVudEVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJTcGlubmVyIiwidGFyZ2V0Iiwic2V0VGFyZ2V0Iiwib3ZlcmxheUNTUyIsImJhY2tncm91bmQiLCJvcGFjaXR5IiwiYnV0dG9uc1NwaW5uZXIiLCJib290c3RyYXAiLCJmdW5kaW5nU291cmNlIiwibWVzc2FnZVJlbmRlcmVyIiwibWluaV9jYXJ0X2J1dHRvbnNfZW5hYmxlZCIsIm1pbmlDYXJ0Qm9vdHN0cmFwIiwic2luZ2xlX3Byb2R1Y3RfYnV0dG9uc19lbmFibGVkIiwic2luZ2xlUHJvZHVjdEJvb3RzdHJhcCIsImNhcnRCb290c3RyYXAiLCJjaGVja291dEJvb3RzdGFwIiwicGF5Tm93Qm9vdHN0cmFwIiwiZGF0YV9jbGllbnRfaWQiLCJoYXNfc3Vic2NyaXB0aW9ucyIsImhpZGVPcmRlckJ1dHRvbklmUHBjcEdhdGV3YXkiLCJpbmNsdWRlcyIsImJvb3RzdHJhcHBlZCIsInVybCIsImVudHJpZXMiLCJzY3JpcHRfYXR0cmlidXRlcyIsImtleVZhbHVlIiwic2V0X2F0dHJpYnV0ZSJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///210\n")}},__webpack_exports__={};__webpack_modules__[210]()})();
|
1 |
+
(()=>{"use strict";var __webpack_modules__={536:()=>{eval("\n;// CONCATENATED MODULE: ./resources/js/modules/ErrorHandler.js\nclass ErrorHandler {\n constructor(genericErrorText) {\n this.genericErrorText = genericErrorText;\n this.wrapper = document.querySelector('.woocommerce-notices-wrapper');\n this.messagesList = document.querySelector('ul.woocommerce-error');\n }\n\n genericError() {\n if (this.wrapper.classList.contains('ppcp-persist')) {\n return;\n }\n\n this.clear();\n this.message(this.genericErrorText);\n }\n\n appendPreparedErrorMessageElement(errorMessageElement) {\n if (this.messagesList === null) {\n this.prepareMessagesList();\n }\n\n this.messagesList.replaceWith(errorMessageElement);\n }\n\n message(text, persist = false) {\n if (!typeof String || text.length === 0) {\n throw new Error('A new message text must be a non-empty string.');\n }\n\n if (this.messagesList === null) {\n this.prepareMessagesList();\n }\n\n if (persist) {\n this.wrapper.classList.add('ppcp-persist');\n } else {\n this.wrapper.classList.remove('ppcp-persist');\n }\n\n let messageNode = this.prepareMessagesListItem(text);\n this.messagesList.appendChild(messageNode);\n jQuery.scroll_to_notices(jQuery('.woocommerce-notices-wrapper'));\n }\n\n prepareMessagesList() {\n if (this.messagesList === null) {\n this.messagesList = document.createElement('ul');\n this.messagesList.setAttribute('class', 'woocommerce-error');\n this.messagesList.setAttribute('role', 'alert');\n this.wrapper.appendChild(this.messagesList);\n }\n }\n\n prepareMessagesListItem(message) {\n const li = document.createElement('li');\n li.innerHTML = message;\n return li;\n }\n\n sanitize(text) {\n const textarea = document.createElement('textarea');\n textarea.innerHTML = text;\n return textarea.value.replace('Error: ', '');\n }\n\n clear() {\n if (this.messagesList === null) {\n return;\n }\n\n this.messagesList.innerHTML = '';\n }\n\n}\n\n/* harmony default export */ const modules_ErrorHandler = (ErrorHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/OnApproveHandler/onApproveForContinue.js\nconst onApprove = (context, errorHandler) => {\n return (data, actions) => {\n return fetch(context.config.ajax.approve_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: context.config.ajax.approve_order.nonce,\n order_id: data.orderID,\n funding_source: window.ppcpFundingSource\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n if (!data.success) {\n errorHandler.genericError();\n return actions.restart().catch(err => {\n errorHandler.genericError();\n });\n }\n\n location.href = context.config.redirect;\n });\n };\n};\n\n/* harmony default export */ const onApproveForContinue = (onApprove);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/PayerData.js\nconst payerData = () => {\n const payer = PayPalCommerceGateway.payer;\n\n if (!payer) {\n return null;\n }\n\n const phone = document.querySelector('#billing_phone') || typeof payer.phone !== 'undefined' ? {\n phone_type: \"HOME\",\n phone_number: {\n national_number: document.querySelector('#billing_phone') ? document.querySelector('#billing_phone').value : payer.phone.phone_number.national_number\n }\n } : null;\n const payerData = {\n email_address: document.querySelector('#billing_email') ? document.querySelector('#billing_email').value : payer.email_address,\n name: {\n surname: document.querySelector('#billing_last_name') ? document.querySelector('#billing_last_name').value : payer.name.surname,\n given_name: document.querySelector('#billing_first_name') ? document.querySelector('#billing_first_name').value : payer.name.given_name\n },\n address: {\n country_code: document.querySelector('#billing_country') ? document.querySelector('#billing_country').value : payer.address.country_code,\n address_line_1: document.querySelector('#billing_address_1') ? document.querySelector('#billing_address_1').value : payer.address.address_line_1,\n address_line_2: document.querySelector('#billing_address_2') ? document.querySelector('#billing_address_2').value : payer.address.address_line_2,\n admin_area_1: document.querySelector('#billing_state') ? document.querySelector('#billing_state').value : payer.address.admin_area_1,\n admin_area_2: document.querySelector('#billing_city') ? document.querySelector('#billing_city').value : payer.address.admin_area_2,\n postal_code: document.querySelector('#billing_postcode') ? document.querySelector('#billing_postcode').value : payer.address.postal_code\n }\n };\n\n if (phone) {\n payerData.phone = phone;\n }\n\n return payerData;\n};\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/CheckoutMethodState.js\nconst PaymentMethods = {\n PAYPAL: 'ppcp-gateway',\n CARDS: 'ppcp-credit-card-gateway'\n};\nconst ORDER_BUTTON_SELECTOR = '#place_order';\nconst getCurrentPaymentMethod = () => {\n const el = document.querySelector('input[name=\"payment_method\"]:checked');\n\n if (!el) {\n return null;\n }\n\n return el.value;\n};\nconst isSavedCardSelected = () => {\n const savedCardList = document.querySelector('#saved-credit-card');\n return savedCardList && savedCardList.value !== '';\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/CartActionHandler.js\n\n\n\n\nclass CartActionHandler {\n constructor(config, errorHandler) {\n this.config = config;\n this.errorHandler = errorHandler;\n }\n\n configuration() {\n const createOrder = (data, actions) => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n purchase_units: [],\n payment_method: PaymentMethods.PAYPAL,\n funding_source: window.ppcpFundingSource,\n bn_code: bnCode,\n payer,\n context: this.config.context\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n console.error(data);\n throw Error(data.data.message);\n }\n\n return data.data.id;\n });\n };\n\n return {\n createOrder,\n onApprove: onApproveForContinue(this, this.errorHandler),\n onError: error => {\n this.errorHandler.genericError();\n }\n };\n }\n\n}\n\n/* harmony default export */ const ActionHandler_CartActionHandler = (CartActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/MiniCartBootstap.js\n\n\n\nclass MiniCartBootstap {\n constructor(gateway, renderer) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.actionHandler = null;\n }\n\n init() {\n this.actionHandler = new ActionHandler_CartActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.render();\n jQuery(document.body).on('wc_fragments_loaded wc_fragments_refreshed', () => {\n this.render();\n });\n }\n\n shouldRender() {\n return document.querySelector(this.gateway.button.mini_cart_wrapper) !== null || document.querySelector(this.gateway.hosted_fields.mini_cart_wrapper) !== null;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n this.renderer.render(this.gateway.button.mini_cart_wrapper, this.gateway.hosted_fields.mini_cart_wrapper, this.actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_MiniCartBootstap = (MiniCartBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/UpdateCart.js\n\n\nclass UpdateCart {\n constructor(endpoint, nonce) {\n this.endpoint = endpoint;\n this.nonce = nonce;\n }\n /**\n *\n * @param onResolve\n * @param {Product[]} products\n * @returns {Promise<unknown>}\n */\n\n\n update(onResolve, products) {\n return new Promise((resolve, reject) => {\n fetch(this.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.nonce,\n products\n })\n }).then(result => {\n return result.json();\n }).then(result => {\n if (!result.success) {\n reject(result.data);\n return;\n }\n\n const resolved = onResolve(result.data);\n resolve(resolved);\n });\n });\n }\n\n}\n\n/* harmony default export */ const Helper_UpdateCart = (UpdateCart);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/ButtonsToggleListener.js\n/**\n * When you can't add something to the cart, the PayPal buttons should not show.\n * Therefore we listen for changes on the add to cart button and show/hide the buttons accordingly.\n */\nclass ButtonsToggleListener {\n constructor(element, showCallback, hideCallback) {\n this.element = element;\n this.showCallback = showCallback;\n this.hideCallback = hideCallback;\n this.observer = null;\n }\n\n init() {\n const config = {\n attributes: true\n };\n\n const callback = () => {\n if (this.element.classList.contains('disabled')) {\n this.hideCallback();\n return;\n }\n\n this.showCallback();\n };\n\n this.observer = new MutationObserver(callback);\n this.observer.observe(this.element, config);\n callback();\n }\n\n disconnect() {\n this.observer.disconnect();\n }\n\n}\n\n/* harmony default export */ const Helper_ButtonsToggleListener = (ButtonsToggleListener);\n;// CONCATENATED MODULE: ./resources/js/modules/Entity/Product.js\nclass Product {\n constructor(id, quantity, variations) {\n this.id = id;\n this.quantity = quantity;\n this.variations = variations;\n }\n\n data() {\n return {\n id: this.id,\n quantity: this.quantity,\n variations: this.variations\n };\n }\n\n}\n\n/* harmony default export */ const Entity_Product = (Product);\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/SingleProductActionHandler.js\n\n\n\n\n\n\nclass SingleProductActionHandler {\n constructor(config, updateCart, showButtonCallback, hideButtonCallback, formElement, errorHandler) {\n this.config = config;\n this.updateCart = updateCart;\n this.showButtonCallback = showButtonCallback;\n this.hideButtonCallback = hideButtonCallback;\n this.formElement = formElement;\n this.errorHandler = errorHandler;\n }\n\n configuration() {\n if (this.hasVariations()) {\n const observer = new Helper_ButtonsToggleListener(this.formElement.querySelector('.single_add_to_cart_button'), this.showButtonCallback, this.hideButtonCallback);\n observer.init();\n }\n\n return {\n createOrder: this.createOrder(),\n onApprove: onApproveForContinue(this, this.errorHandler),\n onError: error => {\n this.errorHandler.genericError();\n }\n };\n }\n\n createOrder() {\n var getProducts = null;\n\n if (!this.isGroupedProduct()) {\n getProducts = () => {\n const id = document.querySelector('[name=\"add-to-cart\"]').value;\n const qty = document.querySelector('[name=\"quantity\"]').value;\n const variations = this.variations();\n return [new Entity_Product(id, qty, variations)];\n };\n } else {\n getProducts = () => {\n const products = [];\n this.formElement.querySelectorAll('input[type=\"number\"]').forEach(element => {\n if (!element.value) {\n return;\n }\n\n const elementName = element.getAttribute('name').match(/quantity\\[([\\d]*)\\]/);\n\n if (elementName.length !== 2) {\n return;\n }\n\n const id = parseInt(elementName[1]);\n const quantity = parseInt(element.value);\n products.push(new Entity_Product(id, quantity, null));\n });\n return products;\n };\n }\n\n const createOrder = (data, actions) => {\n this.errorHandler.clear();\n\n const onResolve = purchase_units => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n purchase_units,\n payer,\n bn_code: bnCode,\n payment_method: PaymentMethods.PAYPAL,\n funding_source: window.ppcpFundingSource,\n context: this.config.context\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n console.error(data);\n throw Error(data.data.message);\n }\n\n return data.data.id;\n });\n };\n\n const promise = this.updateCart.update(onResolve, getProducts());\n return promise;\n };\n\n return createOrder;\n }\n\n variations() {\n if (!this.hasVariations()) {\n return null;\n }\n\n const attributes = [...this.formElement.querySelectorAll(\"[name^='attribute_']\")].map(element => {\n return {\n value: element.value,\n name: element.name\n };\n });\n return attributes;\n }\n\n hasVariations() {\n return this.formElement.classList.contains('variations_form');\n }\n\n isGroupedProduct() {\n return this.formElement.classList.contains('grouped_form');\n }\n\n}\n\n/* harmony default export */ const ActionHandler_SingleProductActionHandler = (SingleProductActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/SingleProductBootstap.js\n\n\n\n\nclass SingleProductBootstap {\n constructor(gateway, renderer, messages) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.messages = messages;\n }\n\n handleChange() {\n if (!this.shouldRender()) {\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n this.renderer.hideButtons(this.gateway.button.wrapper);\n return;\n }\n\n this.render();\n }\n\n init() {\n document.querySelector('form.cart').addEventListener('change', this.handleChange.bind(this));\n\n if (!this.shouldRender()) {\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n return;\n }\n\n this.render();\n }\n\n shouldRender() {\n return document.querySelector('form.cart') !== null && !this.priceAmountIsZero();\n }\n\n priceAmountIsZero() {\n let priceText = \"0\";\n\n if (document.querySelector('form.cart ins .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart ins .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('form.cart .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('.product .woocommerce-Price-amount')) {\n priceText = document.querySelector('.product .woocommerce-Price-amount').innerText;\n }\n\n const amount = parseFloat(priceText.replace(/([^\\d,\\.\\s]*)/g, ''));\n return amount === 0;\n }\n\n render() {\n const actionHandler = new ActionHandler_SingleProductActionHandler(this.gateway, new Helper_UpdateCart(this.gateway.ajax.change_cart.endpoint, this.gateway.ajax.change_cart.nonce), () => {\n this.renderer.showButtons(this.gateway.button.wrapper);\n this.renderer.showButtons(this.gateway.hosted_fields.wrapper);\n let priceText = \"0\";\n\n if (document.querySelector('form.cart ins .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart ins .woocommerce-Price-amount').innerText;\n } else if (document.querySelector('form.cart .woocommerce-Price-amount')) {\n priceText = document.querySelector('form.cart .woocommerce-Price-amount').innerText;\n }\n\n const amount = parseInt(priceText.replace(/([^\\d,\\.\\s]*)/g, ''));\n this.messages.renderWithAmount(amount);\n }, () => {\n this.renderer.hideButtons(this.gateway.button.wrapper);\n this.renderer.hideButtons(this.gateway.hosted_fields.wrapper);\n }, document.querySelector('form.cart'), new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_SingleProductBootstap = (SingleProductBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/CartBootstap.js\n\n\n\nclass CartBootstrap {\n constructor(gateway, renderer) {\n this.gateway = gateway;\n this.renderer = renderer;\n }\n\n init() {\n if (!this.shouldRender()) {\n return;\n }\n\n this.render();\n jQuery(document.body).on('updated_cart_totals updated_checkout', () => {\n this.render();\n });\n }\n\n shouldRender() {\n return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;\n }\n\n render() {\n const actionHandler = new ActionHandler_CartActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic));\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n }\n\n}\n\n/* harmony default export */ const CartBootstap = (CartBootstrap);\n;// CONCATENATED MODULE: ./resources/js/modules/OnApproveHandler/onApproveForPayNow.js\nconst onApproveForPayNow_onApprove = (context, errorHandler, spinner) => {\n return (data, actions) => {\n spinner.block();\n errorHandler.clear();\n return fetch(context.config.ajax.approve_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: context.config.ajax.approve_order.nonce,\n order_id: data.orderID,\n funding_source: window.ppcpFundingSource\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n spinner.unblock();\n\n if (!data.success) {\n if (data.data.code === 100) {\n errorHandler.message(data.data.message);\n } else {\n errorHandler.genericError();\n }\n\n if (typeof actions !== 'undefined' && typeof actions.restart !== 'undefined') {\n return actions.restart();\n }\n\n throw new Error(data.data.message);\n }\n\n document.querySelector('#place_order').click();\n });\n };\n};\n\n/* harmony default export */ const onApproveForPayNow = (onApproveForPayNow_onApprove);\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/CheckoutActionHandler.js\n\n\n\n\nclass CheckoutActionHandler {\n constructor(config, errorHandler, spinner) {\n this.config = config;\n this.errorHandler = errorHandler;\n this.spinner = spinner;\n }\n\n configuration() {\n const spinner = this.spinner;\n\n const createOrder = (data, actions) => {\n const payer = payerData();\n const bnCode = typeof this.config.bn_codes[this.config.context] !== 'undefined' ? this.config.bn_codes[this.config.context] : '';\n const errorHandler = this.errorHandler;\n const formSelector = this.config.context === 'checkout' ? 'form.checkout' : 'form#order_review';\n const formValues = jQuery(formSelector).serialize();\n const createaccount = jQuery('#createaccount').is(\":checked\") ? true : false;\n return fetch(this.config.ajax.create_order.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.create_order.nonce,\n payer,\n bn_code: bnCode,\n context: this.config.context,\n order_id: this.config.order_id,\n payment_method: getCurrentPaymentMethod(),\n funding_source: window.ppcpFundingSource,\n form: formValues,\n createaccount: createaccount\n })\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n if (!data.success) {\n spinner.unblock(); //handle both messages sent from Woocommerce (data.messages) and this plugin (data.data.message)\n\n if (typeof data.messages !== 'undefined') {\n const domParser = new DOMParser();\n errorHandler.appendPreparedErrorMessageElement(domParser.parseFromString(data.messages, 'text/html').querySelector('ul'));\n } else {\n errorHandler.clear();\n\n if (data.data.details.length > 0) {\n errorHandler.message(data.data.details.map(d => `${d.issue} ${d.description}`).join('<br/>'), true);\n } else {\n errorHandler.message(data.data.message, true);\n }\n }\n\n return;\n }\n\n const input = document.createElement('input');\n input.setAttribute('type', 'hidden');\n input.setAttribute('name', 'ppcp-resume-order');\n input.setAttribute('value', data.data.purchase_units[0].custom_id);\n document.querySelector(formSelector).append(input);\n return data.data.id;\n });\n };\n\n return {\n createOrder,\n onApprove: onApproveForPayNow(this, this.errorHandler, this.spinner),\n onCancel: () => {\n spinner.unblock();\n },\n onError: () => {\n this.errorHandler.genericError();\n spinner.unblock();\n }\n };\n }\n\n}\n\n/* harmony default export */ const ActionHandler_CheckoutActionHandler = (CheckoutActionHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Hiding.js\nconst getElement = selectorOrElement => {\n if (typeof selectorOrElement === 'string') {\n return document.querySelector(selectorOrElement);\n }\n\n return selectorOrElement;\n};\n\nconst isVisible = element => {\n return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);\n};\nconst setVisible = (selectorOrElement, show, important = false) => {\n const element = getElement(selectorOrElement);\n\n if (!element) {\n return;\n }\n\n const currentValue = element.style.getPropertyValue('display');\n\n if (!show) {\n if (currentValue === 'none') {\n return;\n }\n\n element.style.setProperty('display', 'none', important ? 'important' : '');\n } else {\n if (currentValue === 'none') {\n element.style.removeProperty('display');\n } // still not visible (if something else added display: none in CSS)\n\n\n if (!isVisible(element)) {\n element.style.setProperty('display', 'block');\n }\n }\n};\nconst hide = (selectorOrElement, important = false) => {\n setVisible(selectorOrElement, false, important);\n};\nconst show = selectorOrElement => {\n setVisible(selectorOrElement, true);\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/CheckoutBootstap.js\n\n\n\n\n\nclass CheckoutBootstap {\n constructor(gateway, renderer, messages, spinner) {\n this.gateway = gateway;\n this.renderer = renderer;\n this.messages = messages;\n this.spinner = spinner;\n this.standardOrderButtonSelector = ORDER_BUTTON_SELECTOR;\n this.buttonChangeObserver = new MutationObserver(el => {\n this.updateUi();\n });\n }\n\n init() {\n this.render(); // Unselect saved card.\n // WC saves form values, so with our current UI it would be a bit weird\n // if the user paid with saved, then after some time tries to pay again,\n // but wants to enter a new card, and to do that they have to choose “Select payment” in the list.\n\n jQuery('#saved-credit-card').val(jQuery('#saved-credit-card option:first').val());\n jQuery(document.body).on('updated_checkout', () => {\n this.render();\n });\n jQuery(document.body).on('updated_checkout payment_method_selected', () => {\n this.updateUi();\n });\n jQuery(document).on('hosted_fields_loaded', () => {\n jQuery('#saved-credit-card').on('change', () => {\n this.updateUi();\n });\n });\n this.updateUi();\n }\n\n shouldRender() {\n if (document.querySelector(this.gateway.button.cancel_wrapper)) {\n return false;\n }\n\n return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) {\n document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', '');\n }\n\n const actionHandler = new ActionHandler_CheckoutActionHandler(PayPalCommerceGateway, new modules_ErrorHandler(this.gateway.labels.error.generic), this.spinner);\n this.renderer.render(this.gateway.button.wrapper, this.gateway.hosted_fields.wrapper, actionHandler.configuration());\n this.buttonChangeObserver.observe(document.querySelector(this.standardOrderButtonSelector), {\n attributes: true\n });\n }\n\n updateUi() {\n const currentPaymentMethod = getCurrentPaymentMethod();\n const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;\n const isCard = currentPaymentMethod === PaymentMethods.CARDS;\n const isSavedCard = isCard && isSavedCardSelected();\n const isNotOurGateway = !isPaypal && !isCard;\n const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;\n const hasVaultedPaypal = PayPalCommerceGateway.vaulted_paypal_email !== '';\n setVisible(this.standardOrderButtonSelector, isPaypal && isFreeTrial && hasVaultedPaypal || isNotOurGateway || isSavedCard, true);\n setVisible('.ppcp-vaulted-paypal-details', isPaypal);\n setVisible(this.gateway.button.wrapper, isPaypal && !(isFreeTrial && hasVaultedPaypal));\n setVisible(this.gateway.messages.wrapper, isPaypal && !isFreeTrial);\n setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);\n\n if (isPaypal && !isFreeTrial) {\n this.messages.render();\n }\n\n if (isCard) {\n if (isSavedCard) {\n this.disableCreditCardFields();\n } else {\n this.enableCreditCardFields();\n }\n }\n }\n\n disableCreditCardFields() {\n jQuery('label[for=\"ppcp-credit-card-gateway-card-number\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-number').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-expiry\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-expiry').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-cvc\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-cvc').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"vault\"]').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').addClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').attr(\"disabled\", true);\n this.renderer.disableCreditCardFields();\n }\n\n enableCreditCardFields() {\n jQuery('label[for=\"ppcp-credit-card-gateway-card-number\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-number').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-expiry\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-expiry').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"ppcp-credit-card-gateway-card-cvc\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-gateway-card-cvc').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('label[for=\"vault\"]').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').removeClass('ppcp-credit-card-gateway-form-field-disabled');\n jQuery('#ppcp-credit-card-vault').attr(\"disabled\", false);\n this.renderer.enableCreditCardFields();\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_CheckoutBootstap = (CheckoutBootstap);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Subscriptions.js\nconst isChangePaymentPage = () => {\n const urlParams = new URLSearchParams(window.location.search);\n return urlParams.has('change_payment_method');\n};\n;// CONCATENATED MODULE: ./resources/js/modules/ContextBootstrap/PayNowBootstrap.js\n\n\n\nclass PayNowBootstrap extends ContextBootstrap_CheckoutBootstap {\n constructor(gateway, renderer, messages, spinner) {\n super(gateway, renderer, messages, spinner);\n }\n\n updateUi() {\n if (isChangePaymentPage()) {\n return;\n }\n\n super.updateUi();\n }\n\n}\n\n/* harmony default export */ const ContextBootstrap_PayNowBootstrap = (PayNowBootstrap);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/Renderer.js\nclass Renderer {\n constructor(creditCardRenderer, defaultConfig, onSmartButtonClick, onSmartButtonsInit) {\n this.defaultConfig = defaultConfig;\n this.creditCardRenderer = creditCardRenderer;\n this.onSmartButtonClick = onSmartButtonClick;\n this.onSmartButtonsInit = onSmartButtonsInit;\n }\n\n render(wrapper, hostedFieldsWrapper, contextConfig) {\n this.renderButtons(wrapper, contextConfig);\n this.creditCardRenderer.render(hostedFieldsWrapper, contextConfig);\n }\n\n renderButtons(wrapper, contextConfig) {\n if (!document.querySelector(wrapper) || this.isAlreadyRendered(wrapper) || 'undefined' === typeof paypal.Buttons) {\n return;\n }\n\n const style = wrapper === this.defaultConfig.button.wrapper ? this.defaultConfig.button.style : this.defaultConfig.button.mini_cart_style;\n paypal.Buttons({\n style,\n ...contextConfig,\n onClick: this.onSmartButtonClick,\n onInit: this.onSmartButtonsInit\n }).render(wrapper);\n }\n\n isAlreadyRendered(wrapper) {\n return document.querySelector(wrapper).hasChildNodes();\n }\n\n hideButtons(element) {\n const domElement = document.querySelector(element);\n\n if (!domElement) {\n return false;\n }\n\n domElement.style.display = 'none';\n return true;\n }\n\n showButtons(element) {\n const domElement = document.querySelector(element);\n\n if (!domElement) {\n return false;\n }\n\n domElement.style.display = 'block';\n return true;\n }\n\n disableCreditCardFields() {\n this.creditCardRenderer.disableFields();\n }\n\n enableCreditCardFields() {\n this.creditCardRenderer.enableFields();\n }\n\n}\n\n/* harmony default export */ const Renderer_Renderer = (Renderer);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/DccInputFactory.js\nconst dccInputFactory = original => {\n const styles = window.getComputedStyle(original);\n const newElement = document.createElement('span');\n newElement.setAttribute('id', original.id);\n Object.values(styles).forEach(prop => {\n if (!styles[prop] || !isNaN(prop)) {\n return;\n }\n\n newElement.style.setProperty(prop, '' + styles[prop]);\n });\n return newElement;\n};\n\n/* harmony default export */ const DccInputFactory = (dccInputFactory);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/CreditCardRenderer.js\n\n\n\nclass CreditCardRenderer {\n constructor(defaultConfig, errorHandler, spinner) {\n this.defaultConfig = defaultConfig;\n this.errorHandler = errorHandler;\n this.spinner = spinner;\n this.cardValid = false;\n this.formValid = false;\n this.currentHostedFieldsInstance = null;\n }\n\n render(wrapper, contextConfig) {\n if (this.defaultConfig.context !== 'checkout' && this.defaultConfig.context !== 'pay-now' || wrapper === null || document.querySelector(wrapper) === null) {\n return;\n }\n\n if (typeof paypal.HostedFields === 'undefined' || !paypal.HostedFields.isEligible()) {\n const wrapperElement = document.querySelector(wrapper);\n wrapperElement.parentNode.removeChild(wrapperElement);\n return;\n }\n\n const buttonSelector = wrapper + ' button';\n\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.teardown().catch(err => console.error(`Hosted fields teardown error: ${err}`));\n this.currentHostedFieldsInstance = null;\n }\n\n const gateWayBox = document.querySelector('.payment_box.payment_method_ppcp-credit-card-gateway');\n const oldDisplayStyle = gateWayBox.style.display;\n gateWayBox.style.display = 'block';\n const hideDccGateway = document.querySelector('#ppcp-hide-dcc');\n\n if (hideDccGateway) {\n hideDccGateway.parentNode.removeChild(hideDccGateway);\n }\n\n const cardNumberField = document.querySelector('#ppcp-credit-card-gateway-card-number');\n const stylesRaw = window.getComputedStyle(cardNumberField);\n let styles = {};\n Object.values(stylesRaw).forEach(prop => {\n if (!stylesRaw[prop]) {\n return;\n }\n\n styles[prop] = '' + stylesRaw[prop];\n });\n const cardNumber = DccInputFactory(cardNumberField);\n cardNumberField.parentNode.replaceChild(cardNumber, cardNumberField);\n const cardExpiryField = document.querySelector('#ppcp-credit-card-gateway-card-expiry');\n const cardExpiry = DccInputFactory(cardExpiryField);\n cardExpiryField.parentNode.replaceChild(cardExpiry, cardExpiryField);\n const cardCodeField = document.querySelector('#ppcp-credit-card-gateway-card-cvc');\n const cardCode = DccInputFactory(cardCodeField);\n cardCodeField.parentNode.replaceChild(cardCode, cardCodeField);\n gateWayBox.style.display = oldDisplayStyle;\n const formWrapper = '.payment_box payment_method_ppcp-credit-card-gateway';\n\n if (this.defaultConfig.enforce_vault && document.querySelector(formWrapper + ' .ppcp-credit-card-vault')) {\n document.querySelector(formWrapper + ' .ppcp-credit-card-vault').checked = true;\n document.querySelector(formWrapper + ' .ppcp-credit-card-vault').setAttribute('disabled', true);\n }\n\n paypal.HostedFields.render({\n createOrder: contextConfig.createOrder,\n styles: {\n 'input': styles\n },\n fields: {\n number: {\n selector: '#ppcp-credit-card-gateway-card-number',\n placeholder: this.defaultConfig.hosted_fields.labels.credit_card_number\n },\n cvv: {\n selector: '#ppcp-credit-card-gateway-card-cvc',\n placeholder: this.defaultConfig.hosted_fields.labels.cvv\n },\n expirationDate: {\n selector: '#ppcp-credit-card-gateway-card-expiry',\n placeholder: this.defaultConfig.hosted_fields.labels.mm_yy\n }\n }\n }).then(hostedFields => {\n document.dispatchEvent(new CustomEvent(\"hosted_fields_loaded\"));\n this.currentHostedFieldsInstance = hostedFields;\n hostedFields.on('inputSubmitRequest', () => {\n this._submit(contextConfig);\n });\n hostedFields.on('cardTypeChange', event => {\n if (!event.cards.length) {\n this.cardValid = false;\n return;\n }\n\n const validCards = this.defaultConfig.hosted_fields.valid_cards;\n this.cardValid = validCards.indexOf(event.cards[0].type) !== -1;\n });\n hostedFields.on('validityChange', event => {\n const formValid = Object.keys(event.fields).every(function (key) {\n return event.fields[key].isValid;\n });\n this.formValid = formValid;\n });\n show(buttonSelector);\n\n if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) {\n document.querySelector(buttonSelector).addEventListener('click', event => {\n event.preventDefault();\n\n this._submit(contextConfig);\n });\n document.querySelector(wrapper).setAttribute('data-ppcp-subscribed', true);\n }\n });\n document.querySelector('#payment_method_ppcp-credit-card-gateway').addEventListener('click', () => {\n document.querySelector('label[for=ppcp-credit-card-gateway-card-number]').click();\n });\n }\n\n disableFields() {\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.setAttribute({\n field: 'number',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.setAttribute({\n field: 'cvv',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.setAttribute({\n field: 'expirationDate',\n attribute: 'disabled'\n });\n }\n }\n\n enableFields() {\n if (this.currentHostedFieldsInstance) {\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'number',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'cvv',\n attribute: 'disabled'\n });\n this.currentHostedFieldsInstance.removeAttribute({\n field: 'expirationDate',\n attribute: 'disabled'\n });\n }\n }\n\n _submit(contextConfig) {\n this.spinner.block();\n this.errorHandler.clear();\n\n if (this.formValid && this.cardValid) {\n const save_card = this.defaultConfig.can_save_vault_token ? true : false;\n let vault = document.getElementById('ppcp-credit-card-vault') ? document.getElementById('ppcp-credit-card-vault').checked : save_card;\n\n if (this.defaultConfig.enforce_vault) {\n vault = true;\n }\n\n const contingency = this.defaultConfig.hosted_fields.contingency;\n const hostedFieldsData = {\n vault: vault\n };\n\n if (contingency !== 'NO_3D_SECURE') {\n hostedFieldsData.contingencies = [contingency];\n }\n\n if (this.defaultConfig.payer) {\n hostedFieldsData.cardholderName = this.defaultConfig.payer.name.given_name + ' ' + this.defaultConfig.payer.name.surname;\n }\n\n if (!hostedFieldsData.cardholderName) {\n const firstName = document.getElementById('billing_first_name') ? document.getElementById('billing_first_name').value : '';\n const lastName = document.getElementById('billing_last_name') ? document.getElementById('billing_last_name').value : '';\n\n if (!firstName || !lastName) {\n this.spinner.unblock();\n this.errorHandler.message(this.defaultConfig.hosted_fields.labels.cardholder_name_required);\n return;\n }\n\n hostedFieldsData.cardholderName = firstName + ' ' + lastName;\n }\n\n this.currentHostedFieldsInstance.submit(hostedFieldsData).then(payload => {\n payload.orderID = payload.orderId;\n this.spinner.unblock();\n return contextConfig.onApprove(payload);\n }).catch(err => {\n this.spinner.unblock();\n this.errorHandler.clear();\n\n if (err.details) {\n this.errorHandler.message(err.details.map(d => `${d.issue} ${d.description}`).join('<br/>'), true);\n }\n });\n } else {\n this.spinner.unblock();\n const message = !this.cardValid ? this.defaultConfig.hosted_fields.labels.card_not_supported : this.defaultConfig.hosted_fields.labels.fields_not_valid;\n this.errorHandler.message(message);\n }\n }\n\n}\n\n/* harmony default export */ const Renderer_CreditCardRenderer = (CreditCardRenderer);\n;// CONCATENATED MODULE: ./resources/js/modules/DataClientIdAttributeHandler.js\nconst storageKey = 'ppcp-data-client-id';\n\nconst validateToken = (token, user) => {\n if (!token) {\n return false;\n }\n\n if (token.user !== user) {\n return false;\n }\n\n const currentTime = new Date().getTime();\n const isExpired = currentTime >= token.expiration * 1000;\n return !isExpired;\n};\n\nconst storedTokenForUser = user => {\n const token = JSON.parse(sessionStorage.getItem(storageKey));\n\n if (validateToken(token, user)) {\n return token.token;\n }\n\n return null;\n};\n\nconst storeToken = token => {\n sessionStorage.setItem(storageKey, JSON.stringify(token));\n};\n\nconst dataClientIdAttributeHandler = (script, config) => {\n fetch(config.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: config.nonce\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n const isValid = validateToken(data, config.user);\n\n if (!isValid) {\n return;\n }\n\n storeToken(data);\n script.setAttribute('data-client-token', data.token);\n document.body.append(script);\n });\n};\n\n/* harmony default export */ const DataClientIdAttributeHandler = (dataClientIdAttributeHandler);\n;// CONCATENATED MODULE: ./resources/js/modules/Renderer/MessageRenderer.js\nclass MessageRenderer {\n constructor(config) {\n this.config = config;\n }\n\n render() {\n if (!this.shouldRender()) {\n return;\n }\n\n paypal.Messages({\n amount: this.config.amount,\n placement: this.config.placement,\n style: this.config.style\n }).render(this.config.wrapper);\n }\n\n renderWithAmount(amount) {\n if (!this.shouldRender()) {\n return;\n }\n\n const newWrapper = document.createElement('div');\n newWrapper.setAttribute('id', this.config.wrapper.replace('#', ''));\n const sibling = document.querySelector(this.config.wrapper).nextSibling;\n document.querySelector(this.config.wrapper).parentElement.removeChild(document.querySelector(this.config.wrapper));\n sibling.parentElement.insertBefore(newWrapper, sibling);\n paypal.Messages({\n amount,\n placement: this.config.placement,\n style: this.config.style\n }).render(this.config.wrapper);\n }\n\n shouldRender() {\n if (typeof paypal.Messages === 'undefined' || typeof this.config.wrapper === 'undefined') {\n return false;\n }\n\n if (!document.querySelector(this.config.wrapper)) {\n return false;\n }\n\n return true;\n }\n\n}\n\n/* harmony default export */ const Renderer_MessageRenderer = (MessageRenderer);\n;// CONCATENATED MODULE: ./resources/js/modules/Helper/Spinner.js\nclass Spinner {\n constructor(target = 'form.woocommerce-checkout') {\n this.target = target;\n }\n\n setTarget(target) {\n this.target = target;\n }\n\n block() {\n jQuery(this.target).block({\n message: null,\n overlayCSS: {\n background: '#fff',\n opacity: 0.6\n }\n });\n }\n\n unblock() {\n jQuery(this.target).unblock();\n }\n\n}\n\n/* harmony default export */ const Helper_Spinner = (Spinner);\n;// CONCATENATED MODULE: ./resources/js/modules/ActionHandler/FreeTrialHandler.js\n\n\n\nclass FreeTrialHandler {\n constructor(config, spinner, errorHandler) {\n this.config = config;\n this.spinner = spinner;\n this.errorHandler = errorHandler;\n }\n\n handle() {\n this.spinner.block();\n fetch(this.config.ajax.vault_paypal.endpoint, {\n method: 'POST',\n body: JSON.stringify({\n nonce: this.config.ajax.vault_paypal.nonce,\n return_url: location.href\n })\n }).then(res => {\n return res.json();\n }).then(data => {\n if (!data.success) {\n this.spinner.unblock();\n console.error(data);\n this.errorHandler.message(data.data.message);\n throw Error(data.data.message);\n }\n\n location.href = data.data.approve_link;\n }).catch(error => {\n this.spinner.unblock();\n console.error(error);\n this.errorHandler.genericError();\n });\n }\n\n}\n\n/* harmony default export */ const ActionHandler_FreeTrialHandler = (FreeTrialHandler);\n;// CONCATENATED MODULE: ./resources/js/button.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst buttonsSpinner = new Helper_Spinner('.ppc-button-wrapper');\nconst cardsSpinner = new Helper_Spinner('#ppcp-hosted-fields');\n\nconst bootstrap = () => {\n const errorHandler = new modules_ErrorHandler(PayPalCommerceGateway.labels.error.generic);\n const spinner = new Helper_Spinner();\n const creditCardRenderer = new Renderer_CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);\n const freeTrialHandler = new ActionHandler_FreeTrialHandler(PayPalCommerceGateway, spinner, errorHandler);\n\n const onSmartButtonClick = (data, actions) => {\n window.ppcpFundingSource = data.fundingSource;\n const form = document.querySelector('form.woocommerce-checkout');\n\n if (form) {\n jQuery('#ppcp-funding-source-form-input').remove();\n form.insertAdjacentHTML('beforeend', `<input type=\"hidden\" name=\"ppcp-funding-source\" value=\"${data.fundingSource}\" id=\"ppcp-funding-source-form-input\">`);\n }\n\n const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;\n\n if (isFreeTrial && data.fundingSource !== 'card') {\n freeTrialHandler.handle();\n return actions.reject();\n }\n };\n\n const onSmartButtonsInit = () => {\n buttonsSpinner.unblock();\n };\n\n const renderer = new Renderer_Renderer(creditCardRenderer, PayPalCommerceGateway, onSmartButtonClick, onSmartButtonsInit);\n const messageRenderer = new Renderer_MessageRenderer(PayPalCommerceGateway.messages);\n const context = PayPalCommerceGateway.context;\n\n if (context === 'mini-cart' || context === 'product') {\n if (PayPalCommerceGateway.mini_cart_buttons_enabled === '1') {\n const miniCartBootstrap = new ContextBootstrap_MiniCartBootstap(PayPalCommerceGateway, renderer);\n miniCartBootstrap.init();\n }\n }\n\n if (context === 'product' && PayPalCommerceGateway.single_product_buttons_enabled === '1') {\n const singleProductBootstrap = new ContextBootstrap_SingleProductBootstap(PayPalCommerceGateway, renderer, messageRenderer);\n singleProductBootstrap.init();\n }\n\n if (context === 'cart') {\n const cartBootstrap = new CartBootstap(PayPalCommerceGateway, renderer);\n cartBootstrap.init();\n }\n\n if (context === 'checkout') {\n const checkoutBootstap = new ContextBootstrap_CheckoutBootstap(PayPalCommerceGateway, renderer, messageRenderer, spinner);\n checkoutBootstap.init();\n }\n\n if (context === 'pay-now') {\n const payNowBootstrap = new ContextBootstrap_PayNowBootstrap(PayPalCommerceGateway, renderer, messageRenderer, spinner);\n payNowBootstrap.init();\n }\n\n if (context !== 'checkout') {\n messageRenderer.render();\n }\n};\n\ndocument.addEventListener('DOMContentLoaded', () => {\n if (!typeof PayPalCommerceGateway) {\n console.error('PayPal button could not be configured.');\n return;\n }\n\n if (PayPalCommerceGateway.context !== 'checkout' && PayPalCommerceGateway.data_client_id.user === 0 && PayPalCommerceGateway.data_client_id.has_subscriptions) {\n return;\n } // Sometimes PayPal script takes long time to load,\n // so we additionally hide the standard order button here to avoid failed orders.\n // Normally it is hidden later after the script load.\n\n\n const hideOrderButtonIfPpcpGateway = () => {\n // only in checkout and pay now page, otherwise it may break things (e.g. payment via product page),\n // and also the loading spinner may look weird on other pages\n if (!['checkout', 'pay-now'].includes(PayPalCommerceGateway.context) || isChangePaymentPage() || PayPalCommerceGateway.is_free_trial_cart && PayPalCommerceGateway.vaulted_paypal_email !== '') {\n return;\n }\n\n const currentPaymentMethod = getCurrentPaymentMethod();\n const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;\n const isCards = currentPaymentMethod === PaymentMethods.CARDS;\n setVisible(ORDER_BUTTON_SELECTOR, !isPaypal && !isCards, true);\n\n if (isPaypal) {\n // stopped after the first rendering of the buttons, in onInit\n buttonsSpinner.block();\n } else {\n buttonsSpinner.unblock();\n }\n\n if (isCards) {\n cardsSpinner.block();\n } else {\n cardsSpinner.unblock();\n }\n };\n\n jQuery(document).on('hosted_fields_loaded', () => {\n cardsSpinner.unblock();\n });\n let bootstrapped = false;\n hideOrderButtonIfPpcpGateway();\n jQuery(document.body).on('updated_checkout payment_method_selected', () => {\n if (bootstrapped) {\n return;\n }\n\n hideOrderButtonIfPpcpGateway();\n });\n const script = document.createElement('script');\n script.addEventListener('load', event => {\n bootstrapped = true;\n bootstrap();\n });\n script.setAttribute('src', PayPalCommerceGateway.button.url);\n Object.entries(PayPalCommerceGateway.script_attributes).forEach(keyValue => {\n script.setAttribute(keyValue[0], keyValue[1]);\n });\n\n if (PayPalCommerceGateway.data_client_id.set_attribute) {\n DataClientIdAttributeHandler(script, PayPalCommerceGateway.data_client_id);\n return;\n }\n\n document.body.append(script);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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L0IsQ0FBNUI7QUFDQTtBQUNIOztBQUVEM1gsRUFBQUEsUUFBUSxDQUFDMkMsSUFBVCxDQUFjb0osTUFBZCxDQUFxQjBKLE1BQXJCO0FBQ0gsQ0FyRkwiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvRXJyb3JIYW5kbGVyLmpzP2U2NWEiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL09uQXBwcm92ZUhhbmRsZXIvb25BcHByb3ZlRm9yQ29udGludWUuanM/YzQ1NCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1BheWVyRGF0YS5qcz8yYWYxIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvQ2hlY2tvdXRNZXRob2RTdGF0ZS5qcz84MGEzIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9BY3Rpb25IYW5kbGVyL0NhcnRBY3Rpb25IYW5kbGVyLmpzPzgyY2YiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvTWluaUNhcnRCb290c3RhcC5qcz9kNTUyIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvVXBkYXRlQ2FydC5qcz9lNDIyIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9IZWxwZXIvQnV0dG9uc1RvZ2dsZUxpc3RlbmVyLmpzP2UxOTMiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0VudGl0eS9Qcm9kdWN0LmpzPzlmZmYiLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9tb2R1bGVzL0FjdGlvbkhhbmRsZXIvU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIuanM/ZDliNyIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9TaW5nbGVQcm9kdWN0Qm9vdHN0YXAuanM/N2MxOSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9DYXJ0Qm9vdHN0YXAuanM/NWU5NCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvT25BcHByb3ZlSGFuZGxlci9vbkFwcHJvdmVGb3JQYXlOb3cuanM/OTMwNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQWN0aW9uSGFuZGxlci9DaGVja291dEFjdGlvbkhhbmRsZXIuanM/ODUxNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL0hpZGluZy5qcz8xZDM2Iiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9Db250ZXh0Qm9vdHN0cmFwL0NoZWNrb3V0Qm9vdHN0YXAuanM/Yzg1NSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1N1YnNjcmlwdGlvbnMuanM/Yjg3MCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9QYXlOb3dCb290c3RyYXAuanM/ZDlmNSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvUmVuZGVyZXIvUmVuZGVyZXIuanM/ZmE5MyIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL0RjY0lucHV0RmFjdG9yeS5qcz8yYTJmIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9SZW5kZXJlci9DcmVkaXRDYXJkUmVuZGVyZXIuanM/Mzg3YSIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvRGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlci5qcz9lZTBiIiwid2VicGFjazovL3BwYy1idXR0b24vLi9yZXNvdXJjZXMvanMvbW9kdWxlcy9SZW5kZXJlci9NZXNzYWdlUmVuZGVyZXIuanM/Y2QwMiIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvSGVscGVyL1NwaW5uZXIuanM/MTcwOCIsIndlYnBhY2s6Ly9wcGMtYnV0dG9uLy4vcmVzb3VyY2VzL2pzL21vZHVsZXMvQWN0aW9uSGFuZGxlci9GcmVlVHJpYWxIYW5kbGVyLmpzP2FiNzciLCJ3ZWJwYWNrOi8vcHBjLWJ1dHRvbi8uL3Jlc291cmNlcy9qcy9idXR0b24uanM/MDYwZiJdLCJzb3VyY2VzQ29udGVudCI6WyJjbGFzcyBFcnJvckhhbmRsZXIge1xuXG4gICAgY29uc3RydWN0b3IoZ2VuZXJpY0Vycm9yVGV4dClcbiAgICB7XG4gICAgICAgIHRoaXMuZ2VuZXJpY0Vycm9yVGV4dCA9IGdlbmVyaWNFcnJvclRleHQ7XG4gICAgICAgIHRoaXMud3JhcHBlciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy53b29jb21tZXJjZS1ub3RpY2VzLXdyYXBwZXInKTtcbiAgICAgICAgdGhpcy5tZXNzYWdlc0xpc3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCd1bC53b29jb21tZXJjZS1lcnJvcicpO1xuICAgIH1cblxuICAgIGdlbmVyaWNFcnJvcigpIHtcbiAgICAgICAgaWYgKHRoaXMud3JhcHBlci5jbGFzc0xpc3QuY29udGFpbnMoJ3BwY3AtcGVyc2lzdCcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgICB0aGlzLm1lc3NhZ2UodGhpcy5nZW5lcmljRXJyb3JUZXh0KVxuICAgIH1cblxuICAgIGFwcGVuZFByZXBhcmVkRXJyb3JNZXNzYWdlRWxlbWVudChlcnJvck1lc3NhZ2VFbGVtZW50KVxuICAgIHtcbiAgICAgICAgaWYodGhpcy5tZXNzYWdlc0xpc3QgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMucHJlcGFyZU1lc3NhZ2VzTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tZXNzYWdlc0xpc3QucmVwbGFjZVdpdGgoZXJyb3JNZXNzYWdlRWxlbWVudCk7XG4gICAgfVxuXG4gICAgbWVzc2FnZSh0ZXh0LCBwZXJzaXN0ID0gZmFsc2UpXG4gICAge1xuICAgICAgICBpZighIHR5cGVvZiBTdHJpbmcgfHwgdGV4dC5sZW5ndGggPT09IDApe1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBIG5ldyBtZXNzYWdlIHRleHQgbXVzdCBiZSBhIG5vbi1lbXB0eSBzdHJpbmcuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0aGlzLm1lc3NhZ2VzTGlzdCA9PT0gbnVsbCl7XG4gICAgICAgICAgICB0aGlzLnByZXBhcmVNZXNzYWdlc0xpc3QoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwZXJzaXN0KSB7XG4gICAgICAgICAgICB0aGlzLndyYXBwZXIuY2xhc3NMaXN0LmFkZCgncHBjcC1wZXJzaXN0Jyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLndyYXBwZXIuY2xhc3NMaXN0LnJlbW92ZSgncHBjcC1wZXJzaXN0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbWVzc2FnZU5vZGUgPSB0aGlzLnByZXBhcmVNZXNzYWdlc0xpc3RJdGVtKHRleHQpO1xuICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdC5hcHBlbmRDaGlsZChtZXNzYWdlTm9kZSk7XG5cbiAgICAgICAgalF1ZXJ5LnNjcm9sbF90b19ub3RpY2VzKGpRdWVyeSgnLndvb2NvbW1lcmNlLW5vdGljZXMtd3JhcHBlcicpKVxuICAgIH1cblxuICAgIHByZXBhcmVNZXNzYWdlc0xpc3QoKVxuICAgIHtcbiAgICAgICAgaWYodGhpcy5tZXNzYWdlc0xpc3QgPT09IG51bGwpe1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlc0xpc3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd1bCcpO1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlc0xpc3Quc2V0QXR0cmlidXRlKCdjbGFzcycsICd3b29jb21tZXJjZS1lcnJvcicpO1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlc0xpc3Quc2V0QXR0cmlidXRlKCdyb2xlJywgJ2FsZXJ0Jyk7XG4gICAgICAgICAgICB0aGlzLndyYXBwZXIuYXBwZW5kQ2hpbGQodGhpcy5tZXNzYWdlc0xpc3QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJlcGFyZU1lc3NhZ2VzTGlzdEl0ZW0obWVzc2FnZSlcbiAgICB7XG4gICAgICAgIGNvbnN0IGxpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGknKTtcbiAgICAgICAgbGkuaW5uZXJIVE1MID0gbWVzc2FnZTtcblxuICAgICAgICByZXR1cm4gbGk7XG4gICAgfVxuXG4gICAgc2FuaXRpemUodGV4dClcbiAgICB7XG4gICAgICAgIGNvbnN0IHRleHRhcmVhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGV4dGFyZWEnKTtcbiAgICAgICAgdGV4dGFyZWEuaW5uZXJIVE1MID0gdGV4dDtcbiAgICAgICAgcmV0dXJuIHRleHRhcmVhLnZhbHVlLnJlcGxhY2UoJ0Vycm9yOiAnLCAnJyk7XG4gICAgfVxuXG4gICAgY2xlYXIoKVxuICAgIHtcbiAgICAgICAgaWYgKHRoaXMubWVzc2FnZXNMaXN0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1lc3NhZ2VzTGlzdC5pbm5lckhUTUwgPSAnJztcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEVycm9ySGFuZGxlcjtcbiIsImNvbnN0IG9uQXBwcm92ZSA9IChjb250ZXh0LCBlcnJvckhhbmRsZXIpID0+IHtcbiAgICByZXR1cm4gKGRhdGEsIGFjdGlvbnMpID0+IHtcbiAgICAgICAgcmV0dXJuIGZldGNoKGNvbnRleHQuY29uZmlnLmFqYXguYXBwcm92ZV9vcmRlci5lbmRwb2ludCwge1xuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgbm9uY2U6IGNvbnRleHQuY29uZmlnLmFqYXguYXBwcm92ZV9vcmRlci5ub25jZSxcbiAgICAgICAgICAgICAgICBvcmRlcl9pZDpkYXRhLm9yZGVySUQsXG4gICAgICAgICAgICAgICAgZnVuZGluZ19zb3VyY2U6IHdpbmRvdy5wcGNwRnVuZGluZ1NvdXJjZSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0pLnRoZW4oKHJlcyk9PntcbiAgICAgICAgICAgIHJldHVybiByZXMuanNvbigpO1xuICAgICAgICB9KS50aGVuKChkYXRhKT0+e1xuICAgICAgICAgICAgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBlcnJvckhhbmRsZXIuZ2VuZXJpY0Vycm9yKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjdGlvbnMucmVzdGFydCgpLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlci5nZW5lcmljRXJyb3IoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvY2F0aW9uLmhyZWYgPSBjb250ZXh0LmNvbmZpZy5yZWRpcmVjdDtcbiAgICAgICAgfSk7XG5cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG9uQXBwcm92ZTtcbiIsImV4cG9ydCBjb25zdCBwYXllckRhdGEgPSAoKSA9PiB7XG4gICAgY29uc3QgcGF5ZXIgPSBQYXlQYWxDb21tZXJjZUdhdGV3YXkucGF5ZXI7XG4gICAgaWYgKCEgcGF5ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgcGhvbmUgPSAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfcGhvbmUnKSB8fCB0eXBlb2YgcGF5ZXIucGhvbmUgIT09ICd1bmRlZmluZWQnKSA/XG4gICAge1xuICAgICAgICBwaG9uZV90eXBlOlwiSE9NRVwiLFxuICAgICAgICAgICAgcGhvbmVfbnVtYmVyOntcbiAgICAgICAgICAgIG5hdGlvbmFsX251bWJlciA6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19waG9uZScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3Bob25lJykudmFsdWUgOiBwYXllci5waG9uZS5waG9uZV9udW1iZXIubmF0aW9uYWxfbnVtYmVyXG4gICAgICAgIH1cbiAgICB9IDogbnVsbDtcbiAgICBjb25zdCBwYXllckRhdGEgPSB7XG4gICAgICAgIGVtYWlsX2FkZHJlc3M6KGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2VtYWlsJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfZW1haWwnKS52YWx1ZSA6IHBheWVyLmVtYWlsX2FkZHJlc3MsXG4gICAgICAgIG5hbWUgOiB7XG4gICAgICAgICAgICBzdXJuYW1lOiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfbGFzdF9uYW1lJykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfbGFzdF9uYW1lJykudmFsdWUgOiBwYXllci5uYW1lLnN1cm5hbWUsXG4gICAgICAgICAgICBnaXZlbl9uYW1lOiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfZmlyc3RfbmFtZScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2ZpcnN0X25hbWUnKS52YWx1ZSA6IHBheWVyLm5hbWUuZ2l2ZW5fbmFtZVxuICAgICAgICB9LFxuICAgICAgICBhZGRyZXNzIDoge1xuICAgICAgICAgICAgY291bnRyeV9jb2RlIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2NvdW50cnknKSkgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19jb3VudHJ5JykudmFsdWUgOiBwYXllci5hZGRyZXNzLmNvdW50cnlfY29kZSxcbiAgICAgICAgICAgIGFkZHJlc3NfbGluZV8xIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2FkZHJlc3NfMScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2FkZHJlc3NfMScpLnZhbHVlIDogcGF5ZXIuYWRkcmVzcy5hZGRyZXNzX2xpbmVfMSxcbiAgICAgICAgICAgIGFkZHJlc3NfbGluZV8yIDogKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2FkZHJlc3NfMicpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX2FkZHJlc3NfMicpLnZhbHVlIDogcGF5ZXIuYWRkcmVzcy5hZGRyZXNzX2xpbmVfMixcbiAgICAgICAgICAgIGFkbWluX2FyZWFfMSA6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19zdGF0ZScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3N0YXRlJykudmFsdWUgOiBwYXllci5hZGRyZXNzLmFkbWluX2FyZWFfMSxcbiAgICAgICAgICAgIGFkbWluX2FyZWFfMiA6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19jaXR5JykpID8gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI2JpbGxpbmdfY2l0eScpLnZhbHVlIDogcGF5ZXIuYWRkcmVzcy5hZG1pbl9hcmVhXzIsXG4gICAgICAgICAgICBwb3N0YWxfY29kZSA6IChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYmlsbGluZ19wb3N0Y29kZScpKSA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNiaWxsaW5nX3Bvc3Rjb2RlJykudmFsdWUgOiBwYXllci5hZGRyZXNzLnBvc3RhbF9jb2RlXG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKHBob25lKSB7XG4gICAgICAgIHBheWVyRGF0YS5waG9uZSA9IHBob25lO1xuICAgIH1cbiAgICByZXR1cm4gcGF5ZXJEYXRhO1xufVxuIiwiZXhwb3J0IGNvbnN0IFBheW1lbnRNZXRob2RzID0ge1xuICAgIFBBWVBBTDogJ3BwY3AtZ2F0ZXdheScsXG4gICAgQ0FSRFM6ICdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXknLFxufTtcblxuZXhwb3J0IGNvbnN0IE9SREVSX0JVVFRPTl9TRUxFQ1RPUiA9ICcjcGxhY2Vfb3JkZXInO1xuXG5leHBvcnQgY29uc3QgZ2V0Q3VycmVudFBheW1lbnRNZXRob2QgPSAoKSA9PiB7XG4gICAgY29uc3QgZWwgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdpbnB1dFtuYW1lPVwicGF5bWVudF9tZXRob2RcIl06Y2hlY2tlZCcpO1xuICAgIGlmICghZWwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsLnZhbHVlO1xufTtcblxuZXhwb3J0IGNvbnN0IGlzU2F2ZWRDYXJkU2VsZWN0ZWQgPSAoKSA9PiB7XG4gICAgY29uc3Qgc2F2ZWRDYXJkTGlzdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNzYXZlZC1jcmVkaXQtY2FyZCcpO1xuICAgIHJldHVybiBzYXZlZENhcmRMaXN0ICYmIHNhdmVkQ2FyZExpc3QudmFsdWUgIT09ICcnO1xufTtcbiIsImltcG9ydCBvbkFwcHJvdmUgZnJvbSAnLi4vT25BcHByb3ZlSGFuZGxlci9vbkFwcHJvdmVGb3JDb250aW51ZS5qcyc7XG5pbXBvcnQge3BheWVyRGF0YX0gZnJvbSBcIi4uL0hlbHBlci9QYXllckRhdGFcIjtcbmltcG9ydCB7UGF5bWVudE1ldGhvZHN9IGZyb20gXCIuLi9IZWxwZXIvQ2hlY2tvdXRNZXRob2RTdGF0ZVwiO1xuXG5jbGFzcyBDYXJ0QWN0aW9uSGFuZGxlciB7XG5cbiAgICBjb25zdHJ1Y3Rvcihjb25maWcsIGVycm9ySGFuZGxlcikge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIgPSBlcnJvckhhbmRsZXI7XG4gICAgfVxuXG4gICAgY29uZmlndXJhdGlvbigpIHtcbiAgICAgICAgY29uc3QgY3JlYXRlT3JkZXIgPSAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICAgICAgY29uc3QgcGF5ZXIgPSBwYXllckRhdGEoKTtcbiAgICAgICAgICAgIGNvbnN0IGJuQ29kZSA9IHR5cGVvZiB0aGlzLmNvbmZpZy5ibl9jb2Rlc1t0aGlzLmNvbmZpZy5jb250ZXh0XSAhPT0gJ3VuZGVmaW5lZCcgP1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdIDogJyc7XG4gICAgICAgICAgICByZXR1cm4gZmV0Y2godGhpcy5jb25maWcuYWpheC5jcmVhdGVfb3JkZXIuZW5kcG9pbnQsIHtcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgIG5vbmNlOiB0aGlzLmNvbmZpZy5hamF4LmNyZWF0ZV9vcmRlci5ub25jZSxcbiAgICAgICAgICAgICAgICAgICAgcHVyY2hhc2VfdW5pdHM6IFtdLFxuICAgICAgICAgICAgICAgICAgICBwYXltZW50X21ldGhvZDogUGF5bWVudE1ldGhvZHMuUEFZUEFMLFxuICAgICAgICAgICAgICAgICAgICBmdW5kaW5nX3NvdXJjZTogd2luZG93LnBwY3BGdW5kaW5nU291cmNlLFxuICAgICAgICAgICAgICAgICAgICBibl9jb2RlOmJuQ29kZSxcbiAgICAgICAgICAgICAgICAgICAgcGF5ZXIsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6dGhpcy5jb25maWcuY29udGV4dFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbihyZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24oZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGRhdGEuZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEuZGF0YS5pZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjcmVhdGVPcmRlcixcbiAgICAgICAgICAgIG9uQXBwcm92ZTogb25BcHByb3ZlKHRoaXMsIHRoaXMuZXJyb3JIYW5kbGVyKSxcbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgQ2FydEFjdGlvbkhhbmRsZXI7XG4iLCJpbXBvcnQgRXJyb3JIYW5kbGVyIGZyb20gJy4uL0Vycm9ySGFuZGxlcic7XG5pbXBvcnQgQ2FydEFjdGlvbkhhbmRsZXIgZnJvbSAnLi4vQWN0aW9uSGFuZGxlci9DYXJ0QWN0aW9uSGFuZGxlcic7XG5cbmNsYXNzIE1pbmlDYXJ0Qm9vdHN0YXAge1xuICAgIGNvbnN0cnVjdG9yKGdhdGV3YXksIHJlbmRlcmVyKSB7XG4gICAgICAgIHRoaXMuZ2F0ZXdheSA9IGdhdGV3YXk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcbiAgICAgICAgdGhpcy5hY3Rpb25IYW5kbGVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBpbml0KCkge1xuXG4gICAgICAgIHRoaXMuYWN0aW9uSGFuZGxlciA9IG5ldyBDYXJ0QWN0aW9uSGFuZGxlcihcbiAgICAgICAgICAgIFBheVBhbENvbW1lcmNlR2F0ZXdheSxcbiAgICAgICAgICAgIG5ldyBFcnJvckhhbmRsZXIodGhpcy5nYXRld2F5LmxhYmVscy5lcnJvci5nZW5lcmljKSxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQuYm9keSkub24oJ3djX2ZyYWdtZW50c19sb2FkZWQgd2NfZnJhZ21lbnRzX3JlZnJlc2hlZCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHNob3VsZFJlbmRlcigpIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5LmJ1dHRvbi5taW5pX2NhcnRfd3JhcHBlcikgIT09IG51bGxcbiAgICAgICAgICAgIHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMubWluaV9jYXJ0X3dyYXBwZXIpICE9PSBudWxsO1xuICAgIH1cblxuICAgIHJlbmRlcigpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcihcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5idXR0b24ubWluaV9jYXJ0X3dyYXBwZXIsXG4gICAgICAgICAgICB0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy5taW5pX2NhcnRfd3JhcHBlcixcbiAgICAgICAgICAgIHRoaXMuYWN0aW9uSGFuZGxlci5jb25maWd1cmF0aW9uKClcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1pbmlDYXJ0Qm9vdHN0YXA7XG4iLCJpbXBvcnQgUHJvZHVjdCBmcm9tIFwiLi4vRW50aXR5L1Byb2R1Y3RcIjtcbmNsYXNzIFVwZGF0ZUNhcnQge1xuXG4gICAgY29uc3RydWN0b3IoZW5kcG9pbnQsIG5vbmNlKVxuICAgIHtcbiAgICAgICAgdGhpcy5lbmRwb2ludCA9IGVuZHBvaW50O1xuICAgICAgICB0aGlzLm5vbmNlID0gbm9uY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gb25SZXNvbHZlXG4gICAgICogQHBhcmFtIHtQcm9kdWN0W119IHByb2R1Y3RzXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dW5rbm93bj59XG4gICAgICovXG4gICAgdXBkYXRlKG9uUmVzb2x2ZSwgcHJvZHVjdHMpXG4gICAge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgZmV0Y2goXG4gICAgICAgICAgICAgICAgdGhpcy5lbmRwb2ludCxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBub25jZTogdGhpcy5ub25jZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb2R1Y3RzLFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICkudGhlbihcbiAgICAgICAgICAgICAgICAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5qc29uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoISByZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QocmVzdWx0LmRhdGEpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkID0gb25SZXNvbHZlKHJlc3VsdC5kYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShyZXNvbHZlZCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfSk7XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBVcGRhdGVDYXJ0OyIsIi8qKlxuICogV2hlbiB5b3UgY2FuJ3QgYWRkIHNvbWV0aGluZyB0byB0aGUgY2FydCwgdGhlIFBheVBhbCBidXR0b25zIHNob3VsZCBub3Qgc2hvdy5cbiAqIFRoZXJlZm9yZSB3ZSBsaXN0ZW4gZm9yIGNoYW5nZXMgb24gdGhlIGFkZCB0byBjYXJ0IGJ1dHRvbiBhbmQgc2hvdy9oaWRlIHRoZSBidXR0b25zIGFjY29yZGluZ2x5LlxuICovXG5cbmNsYXNzIEJ1dHRvbnNUb2dnbGVMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZWxlbWVudCwgc2hvd0NhbGxiYWNrLCBoaWRlQ2FsbGJhY2spXG4gICAge1xuICAgICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgICB0aGlzLnNob3dDYWxsYmFjayA9IHNob3dDYWxsYmFjaztcbiAgICAgICAgdGhpcy5oaWRlQ2FsbGJhY2sgPSBoaWRlQ2FsbGJhY2s7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIgPSBudWxsO1xuICAgIH1cblxuICAgIGluaXQoKVxuICAgIHtcbiAgICAgICAgY29uc3QgY29uZmlnID0geyBhdHRyaWJ1dGVzIDogdHJ1ZSB9O1xuICAgICAgICBjb25zdCBjYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdkaXNhYmxlZCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNob3dDYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcihjYWxsYmFjayk7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLmVsZW1lbnQsIGNvbmZpZyk7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgZGlzY29ubmVjdCgpXG4gICAge1xuICAgICAgICB0aGlzLm9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJ1dHRvbnNUb2dnbGVMaXN0ZW5lcjsiLCJjbGFzcyBQcm9kdWN0IHtcblxuICAgIGNvbnN0cnVjdG9yKGlkLCBxdWFudGl0eSwgdmFyaWF0aW9ucykge1xuICAgICAgICB0aGlzLmlkID0gaWQ7XG4gICAgICAgIHRoaXMucXVhbnRpdHkgPSBxdWFudGl0eTtcbiAgICAgICAgdGhpcy52YXJpYXRpb25zID0gdmFyaWF0aW9ucztcbiAgICB9XG5cbiAgICBkYXRhKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQ6dGhpcy5pZCxcbiAgICAgICAgICAgIHF1YW50aXR5OnRoaXMucXVhbnRpdHksXG4gICAgICAgICAgICB2YXJpYXRpb25zOnRoaXMudmFyaWF0aW9uc1xuICAgICAgICB9XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBQcm9kdWN0OyIsImltcG9ydCBCdXR0b25zVG9nZ2xlTGlzdGVuZXIgZnJvbSAnLi4vSGVscGVyL0J1dHRvbnNUb2dnbGVMaXN0ZW5lcic7XG5pbXBvcnQgUHJvZHVjdCBmcm9tICcuLi9FbnRpdHkvUHJvZHVjdCc7XG5pbXBvcnQgb25BcHByb3ZlIGZyb20gJy4uL09uQXBwcm92ZUhhbmRsZXIvb25BcHByb3ZlRm9yQ29udGludWUnO1xuaW1wb3J0IHtwYXllckRhdGF9IGZyb20gXCIuLi9IZWxwZXIvUGF5ZXJEYXRhXCI7XG5pbXBvcnQge1BheW1lbnRNZXRob2RzfSBmcm9tIFwiLi4vSGVscGVyL0NoZWNrb3V0TWV0aG9kU3RhdGVcIjtcblxuY2xhc3MgU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIge1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdXBkYXRlQ2FydCxcbiAgICAgICAgc2hvd0J1dHRvbkNhbGxiYWNrLFxuICAgICAgICBoaWRlQnV0dG9uQ2FsbGJhY2ssXG4gICAgICAgIGZvcm1FbGVtZW50LFxuICAgICAgICBlcnJvckhhbmRsZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMudXBkYXRlQ2FydCA9IHVwZGF0ZUNhcnQ7XG4gICAgICAgIHRoaXMuc2hvd0J1dHRvbkNhbGxiYWNrID0gc2hvd0J1dHRvbkNhbGxiYWNrO1xuICAgICAgICB0aGlzLmhpZGVCdXR0b25DYWxsYmFjayA9IGhpZGVCdXR0b25DYWxsYmFjaztcbiAgICAgICAgdGhpcy5mb3JtRWxlbWVudCA9IGZvcm1FbGVtZW50O1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcbiAgICB9XG5cbiAgICBjb25maWd1cmF0aW9uKClcbiAgICB7XG5cbiAgICAgICAgaWYgKCB0aGlzLmhhc1ZhcmlhdGlvbnMoKSApIHtcbiAgICAgICAgICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IEJ1dHRvbnNUb2dnbGVMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5zaW5nbGVfYWRkX3RvX2NhcnRfYnV0dG9uJyksXG4gICAgICAgICAgICAgICAgdGhpcy5zaG93QnV0dG9uQ2FsbGJhY2ssXG4gICAgICAgICAgICAgICAgdGhpcy5oaWRlQnV0dG9uQ2FsbGJhY2tcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBvYnNlcnZlci5pbml0KCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY3JlYXRlT3JkZXI6IHRoaXMuY3JlYXRlT3JkZXIoKSxcbiAgICAgICAgICAgIG9uQXBwcm92ZTogb25BcHByb3ZlKHRoaXMsIHRoaXMuZXJyb3JIYW5kbGVyKSxcbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY3JlYXRlT3JkZXIoKVxuICAgIHtcbiAgICAgICAgdmFyIGdldFByb2R1Y3RzID0gbnVsbDtcbiAgICAgICAgaWYgKCEgdGhpcy5pc0dyb3VwZWRQcm9kdWN0KCkgKSB7XG4gICAgICAgICAgICBnZXRQcm9kdWN0cyA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tuYW1lPVwiYWRkLXRvLWNhcnRcIl0nKS52YWx1ZTtcbiAgICAgICAgICAgICAgICBjb25zdCBxdHkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbbmFtZT1cInF1YW50aXR5XCJdJykudmFsdWU7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFyaWF0aW9ucyA9IHRoaXMudmFyaWF0aW9ucygpO1xuICAgICAgICAgICAgICAgIHJldHVybiBbbmV3IFByb2R1Y3QoaWQsIHF0eSwgdmFyaWF0aW9ucyldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UHJvZHVjdHMgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcHJvZHVjdHMgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1FbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0W3R5cGU9XCJudW1iZXJcIl0nKS5mb3JFYWNoKChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghIGVsZW1lbnQudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50TmFtZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCduYW1lJykubWF0Y2goL3F1YW50aXR5XFxbKFtcXGRdKilcXF0vKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnROYW1lLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gcGFyc2VJbnQoZWxlbWVudE5hbWVbMV0pO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWFudGl0eSA9IHBhcnNlSW50KGVsZW1lbnQudmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBwcm9kdWN0cy5wdXNoKG5ldyBQcm9kdWN0KGlkLCBxdWFudGl0eSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb2R1Y3RzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNyZWF0ZU9yZGVyID0gKGRhdGEsIGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmNsZWFyKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IG9uUmVzb2x2ZSA9IChwdXJjaGFzZV91bml0cykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBheWVyID0gcGF5ZXJEYXRhKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgYm5Db2RlID0gdHlwZW9mIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdICE9PSAndW5kZWZpbmVkJyA/XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdIDogJyc7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoKHRoaXMuY29uZmlnLmFqYXguY3JlYXRlX29yZGVyLmVuZHBvaW50LCB7XG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBub25jZTogdGhpcy5jb25maWcuYWpheC5jcmVhdGVfb3JkZXIubm9uY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBwdXJjaGFzZV91bml0cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheWVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgYm5fY29kZTpibkNvZGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50X21ldGhvZDogUGF5bWVudE1ldGhvZHMuUEFZUEFMLFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuZGluZ19zb3VyY2U6IHdpbmRvdy5wcGNwRnVuZGluZ1NvdXJjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6dGhpcy5jb25maWcuY29udGV4dFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoZGF0YS5kYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhLmRhdGEuaWQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy51cGRhdGVDYXJ0LnVwZGF0ZShvblJlc29sdmUsIGdldFByb2R1Y3RzKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBjcmVhdGVPcmRlcjtcbiAgICB9XG5cbiAgICB2YXJpYXRpb25zKClcbiAgICB7XG5cbiAgICAgICAgaWYgKCEgdGhpcy5oYXNWYXJpYXRpb25zKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBbLi4udGhpcy5mb3JtRWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKFwiW25hbWVePSdhdHRyaWJ1dGVfJ11cIildLm1hcChcbiAgICAgICAgICAgIChlbGVtZW50KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZTplbGVtZW50LnZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBuYW1lOmVsZW1lbnQubmFtZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIGF0dHJpYnV0ZXM7XG4gICAgfVxuXG4gICAgaGFzVmFyaWF0aW9ucygpXG4gICAge1xuICAgICAgICByZXR1cm4gdGhpcy5mb3JtRWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3ZhcmlhdGlvbnNfZm9ybScpO1xuICAgIH1cblxuICAgIGlzR3JvdXBlZFByb2R1Y3QoKVxuICAgIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybUVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdncm91cGVkX2Zvcm0nKTtcbiAgICB9XG59XG5leHBvcnQgZGVmYXVsdCBTaW5nbGVQcm9kdWN0QWN0aW9uSGFuZGxlcjtcbiIsImltcG9ydCBFcnJvckhhbmRsZXIgZnJvbSAnLi4vRXJyb3JIYW5kbGVyJztcbmltcG9ydCBVcGRhdGVDYXJ0IGZyb20gXCIuLi9IZWxwZXIvVXBkYXRlQ2FydFwiO1xuaW1wb3J0IFNpbmdsZVByb2R1Y3RBY3Rpb25IYW5kbGVyIGZyb20gXCIuLi9BY3Rpb25IYW5kbGVyL1NpbmdsZVByb2R1Y3RBY3Rpb25IYW5kbGVyXCI7XG5cbmNsYXNzIFNpbmdsZVByb2R1Y3RCb290c3RhcCB7XG4gICAgY29uc3RydWN0b3IoZ2F0ZXdheSwgcmVuZGVyZXIsIG1lc3NhZ2VzKSB7XG4gICAgICAgIHRoaXMuZ2F0ZXdheSA9IGdhdGV3YXk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcbiAgICAgICAgdGhpcy5tZXNzYWdlcyA9IG1lc3NhZ2VzO1xuICAgIH1cblxuXG4gICAgaGFuZGxlQ2hhbmdlKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuaGlkZUJ1dHRvbnModGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlcik7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmhpZGVCdXR0b25zKHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH1cblxuICAgIGluaXQoKSB7XG5cbiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0JykuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5oYW5kbGVDaGFuZ2UuYmluZCh0aGlzKSlcblxuICAgICAgICBpZiAoIXRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuaGlkZUJ1dHRvbnModGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlcik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlcigpO1xuXG4gICAgfVxuXG4gICAgc2hvdWxkUmVuZGVyKCkge1xuXG4gICAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQnKSAhPT0gbnVsbCAmJiAhdGhpcy5wcmljZUFtb3VudElzWmVybygpO1xuXG4gICAgfVxuXG4gICAgcHJpY2VBbW91bnRJc1plcm8oKSB7XG5cbiAgICAgICAgbGV0IHByaWNlVGV4dCA9IFwiMFwiO1xuICAgICAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IGlucyAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykpIHtcbiAgICAgICAgICAgIHByaWNlVGV4dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCBpbnMgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpLmlubmVyVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpKSB7XG4gICAgICAgICAgICBwcmljZVRleHQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpLmlubmVyVGV4dDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcucHJvZHVjdCAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykpIHtcbiAgICAgICAgICAgIHByaWNlVGV4dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5wcm9kdWN0IC53b29jb21tZXJjZS1QcmljZS1hbW91bnQnKS5pbm5lclRleHQ7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYW1vdW50ID0gcGFyc2VGbG9hdChwcmljZVRleHQucmVwbGFjZSgvKFteXFxkLFxcLlxcc10qKS9nLCAnJykpO1xuICAgICAgICByZXR1cm4gYW1vdW50ID09PSAwO1xuXG4gICAgfVxuXG4gICAgcmVuZGVyKCkge1xuICAgICAgICBjb25zdCBhY3Rpb25IYW5kbGVyID0gbmV3IFNpbmdsZVByb2R1Y3RBY3Rpb25IYW5kbGVyKFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5LFxuICAgICAgICAgICAgbmV3IFVwZGF0ZUNhcnQoXG4gICAgICAgICAgICAgICAgdGhpcy5nYXRld2F5LmFqYXguY2hhbmdlX2NhcnQuZW5kcG9pbnQsXG4gICAgICAgICAgICAgICAgdGhpcy5nYXRld2F5LmFqYXguY2hhbmdlX2NhcnQubm9uY2UsXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2hvd0J1dHRvbnModGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNob3dCdXR0b25zKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpO1xuICAgICAgICAgICAgICAgIGxldCBwcmljZVRleHQgPSBcIjBcIjtcbiAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IGlucyAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJpY2VUZXh0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignZm9ybS5jYXJ0IGlucyAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykuaW5uZXJUZXh0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdmb3JtLmNhcnQgLndvb2NvbW1lcmNlLVByaWNlLWFtb3VudCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByaWNlVGV4dCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCAud29vY29tbWVyY2UtUHJpY2UtYW1vdW50JykuaW5uZXJUZXh0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBhbW91bnQgPSBwYXJzZUludChwcmljZVRleHQucmVwbGFjZSgvKFteXFxkLFxcLlxcc10qKS9nLCAnJykpO1xuICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZXMucmVuZGVyV2l0aEFtb3VudChhbW91bnQpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuaGlkZUJ1dHRvbnModGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmhpZGVCdXR0b25zKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0uY2FydCcpLFxuICAgICAgICAgICAgbmV3IEVycm9ySGFuZGxlcih0aGlzLmdhdGV3YXkubGFiZWxzLmVycm9yLmdlbmVyaWMpLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMucmVuZGVyZXIucmVuZGVyKFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5LmJ1dHRvbi53cmFwcGVyLFxuICAgICAgICAgICAgdGhpcy5nYXRld2F5Lmhvc3RlZF9maWVsZHMud3JhcHBlcixcbiAgICAgICAgICAgIGFjdGlvbkhhbmRsZXIuY29uZmlndXJhdGlvbigpLFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgU2luZ2xlUHJvZHVjdEJvb3RzdGFwO1xuIiwiaW1wb3J0IENhcnRBY3Rpb25IYW5kbGVyIGZyb20gJy4uL0FjdGlvbkhhbmRsZXIvQ2FydEFjdGlvbkhhbmRsZXInO1xuaW1wb3J0IEVycm9ySGFuZGxlciBmcm9tICcuLi9FcnJvckhhbmRsZXInO1xuXG5jbGFzcyBDYXJ0Qm9vdHN0cmFwIHtcbiAgICBjb25zdHJ1Y3RvcihnYXRld2F5LCByZW5kZXJlcikge1xuICAgICAgICB0aGlzLmdhdGV3YXkgPSBnYXRld2F5O1xuICAgICAgICB0aGlzLnJlbmRlcmVyID0gcmVuZGVyZXI7XG4gICAgfVxuXG4gICAgaW5pdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFJlbmRlcigpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlbmRlcigpO1xuXG4gICAgICAgIGpRdWVyeShkb2N1bWVudC5ib2R5KS5vbigndXBkYXRlZF9jYXJ0X3RvdGFscyB1cGRhdGVkX2NoZWNrb3V0JywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgc2hvdWxkUmVuZGVyKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuYnV0dG9uLndyYXBwZXIpICE9PVxuICAgICAgICAgICAgbnVsbCB8fCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIpICE9PVxuICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGNvbnN0IGFjdGlvbkhhbmRsZXIgPSBuZXcgQ2FydEFjdGlvbkhhbmRsZXIoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICBuZXcgRXJyb3JIYW5kbGVyKHRoaXMuZ2F0ZXdheS5sYWJlbHMuZXJyb3IuZ2VuZXJpYyksXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5yZW5kZXJlci5yZW5kZXIoXG4gICAgICAgICAgICB0aGlzLmdhdGV3YXkuYnV0dG9uLndyYXBwZXIsXG4gICAgICAgICAgICB0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy53cmFwcGVyLFxuICAgICAgICAgICAgYWN0aW9uSGFuZGxlci5jb25maWd1cmF0aW9uKCksXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDYXJ0Qm9vdHN0cmFwO1xuIiwiY29uc3Qgb25BcHByb3ZlID0gKGNvbnRleHQsIGVycm9ySGFuZGxlciwgc3Bpbm5lcikgPT4ge1xuICAgIHJldHVybiAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICBzcGlubmVyLmJsb2NrKCk7XG4gICAgICAgIGVycm9ySGFuZGxlci5jbGVhcigpO1xuXG4gICAgICAgIHJldHVybiBmZXRjaChjb250ZXh0LmNvbmZpZy5hamF4LmFwcHJvdmVfb3JkZXIuZW5kcG9pbnQsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIG5vbmNlOiBjb250ZXh0LmNvbmZpZy5hamF4LmFwcHJvdmVfb3JkZXIubm9uY2UsXG4gICAgICAgICAgICAgICAgb3JkZXJfaWQ6ZGF0YS5vcmRlcklELFxuICAgICAgICAgICAgICAgIGZ1bmRpbmdfc291cmNlOiB3aW5kb3cucHBjcEZ1bmRpbmdTb3VyY2UsXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KS50aGVuKChyZXMpPT57XG4gICAgICAgICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICAgICAgfSkudGhlbigoZGF0YSk9PntcbiAgICAgICAgICAgIHNwaW5uZXIudW5ibG9jaygpO1xuICAgICAgICAgICAgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5kYXRhLmNvZGUgPT09IDEwMCkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsZXIubWVzc2FnZShkYXRhLmRhdGEubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFjdGlvbnMgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBhY3Rpb25zLnJlc3RhcnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3Rpb25zLnJlc3RhcnQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGRhdGEuZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwbGFjZV9vcmRlcicpLmNsaWNrKClcbiAgICAgICAgfSk7XG5cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG9uQXBwcm92ZTtcbiIsImltcG9ydCBvbkFwcHJvdmUgZnJvbSAnLi4vT25BcHByb3ZlSGFuZGxlci9vbkFwcHJvdmVGb3JQYXlOb3cuanMnO1xuaW1wb3J0IHtwYXllckRhdGF9IGZyb20gXCIuLi9IZWxwZXIvUGF5ZXJEYXRhXCI7XG5pbXBvcnQge2dldEN1cnJlbnRQYXltZW50TWV0aG9kfSBmcm9tIFwiLi4vSGVscGVyL0NoZWNrb3V0TWV0aG9kU3RhdGVcIjtcblxuY2xhc3MgQ2hlY2tvdXRBY3Rpb25IYW5kbGVyIHtcblxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZywgZXJyb3JIYW5kbGVyLCBzcGlubmVyKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcbiAgICAgICAgdGhpcy5zcGlubmVyID0gc3Bpbm5lcjtcbiAgICB9XG5cbiAgICBjb25maWd1cmF0aW9uKCkge1xuICAgICAgICBjb25zdCBzcGlubmVyID0gdGhpcy5zcGlubmVyO1xuICAgICAgICBjb25zdCBjcmVhdGVPcmRlciA9IChkYXRhLCBhY3Rpb25zKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwYXllciA9IHBheWVyRGF0YSgpO1xuICAgICAgICAgICAgY29uc3QgYm5Db2RlID0gdHlwZW9mIHRoaXMuY29uZmlnLmJuX2NvZGVzW3RoaXMuY29uZmlnLmNvbnRleHRdICE9PSAndW5kZWZpbmVkJyA/XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcuYm5fY29kZXNbdGhpcy5jb25maWcuY29udGV4dF0gOiAnJztcblxuICAgICAgICAgICAgY29uc3QgZXJyb3JIYW5kbGVyID0gdGhpcy5lcnJvckhhbmRsZXI7XG5cbiAgICAgICAgICAgIGNvbnN0IGZvcm1TZWxlY3RvciA9IHRoaXMuY29uZmlnLmNvbnRleHQgPT09ICdjaGVja291dCcgPyAnZm9ybS5jaGVja291dCcgOiAnZm9ybSNvcmRlcl9yZXZpZXcnO1xuICAgICAgICAgICAgY29uc3QgZm9ybVZhbHVlcyA9IGpRdWVyeShmb3JtU2VsZWN0b3IpLnNlcmlhbGl6ZSgpO1xuXG4gICAgICAgICAgICBjb25zdCBjcmVhdGVhY2NvdW50ID0galF1ZXJ5KCcjY3JlYXRlYWNjb3VudCcpLmlzKFwiOmNoZWNrZWRcIikgPyB0cnVlIDogZmFsc2U7XG5cbiAgICAgICAgICAgIHJldHVybiBmZXRjaCh0aGlzLmNvbmZpZy5hamF4LmNyZWF0ZV9vcmRlci5lbmRwb2ludCwge1xuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgICAgbm9uY2U6IHRoaXMuY29uZmlnLmFqYXguY3JlYXRlX29yZGVyLm5vbmNlLFxuICAgICAgICAgICAgICAgICAgICBwYXllcixcbiAgICAgICAgICAgICAgICAgICAgYm5fY29kZTpibkNvZGUsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6dGhpcy5jb25maWcuY29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgb3JkZXJfaWQ6dGhpcy5jb25maWcub3JkZXJfaWQsXG4gICAgICAgICAgICAgICAgICAgIHBheW1lbnRfbWV0aG9kOiBnZXRDdXJyZW50UGF5bWVudE1ldGhvZCgpLFxuICAgICAgICAgICAgICAgICAgICBmdW5kaW5nX3NvdXJjZTogd2luZG93LnBwY3BGdW5kaW5nU291cmNlLFxuICAgICAgICAgICAgICAgICAgICBmb3JtOmZvcm1WYWx1ZXMsXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZWFjY291bnQ6IGNyZWF0ZWFjY291bnRcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICAgICAgICAgIC8vaGFuZGxlIGJvdGggbWVzc2FnZXMgc2VudCBmcm9tIFdvb2NvbW1lcmNlIChkYXRhLm1lc3NhZ2VzKSBhbmQgdGhpcyBwbHVnaW4gKGRhdGEuZGF0YS5tZXNzYWdlKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mKGRhdGEubWVzc2FnZXMpICE9PSAndW5kZWZpbmVkJyApXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRvbVBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9ySGFuZGxlci5hcHBlbmRQcmVwYXJlZEVycm9yTWVzc2FnZUVsZW1lbnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tUGFyc2VyLnBhcnNlRnJvbVN0cmluZyhkYXRhLm1lc3NhZ2VzLCAndGV4dC9odG1sJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnF1ZXJ5U2VsZWN0b3IoJ3VsJylcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsZXIuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmRhdGEuZGV0YWlscy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JIYW5kbGVyLm1lc3NhZ2UoZGF0YS5kYXRhLmRldGFpbHMubWFwKGQgPT4gYCR7ZC5pc3N1ZX0gJHtkLmRlc2NyaXB0aW9ufWApLmpvaW4oJzxici8+JyksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvckhhbmRsZXIubWVzc2FnZShkYXRhLmRhdGEubWVzc2FnZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcbiAgICAgICAgICAgICAgICBpbnB1dC5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAnaGlkZGVuJyk7XG4gICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCduYW1lJywgJ3BwY3AtcmVzdW1lLW9yZGVyJyk7XG4gICAgICAgICAgICAgICAgaW5wdXQuc2V0QXR0cmlidXRlKCd2YWx1ZScsIGRhdGEuZGF0YS5wdXJjaGFzZV91bml0c1swXS5jdXN0b21faWQpO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZm9ybVNlbGVjdG9yKS5hcHBlbmQoaW5wdXQpO1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXRhLmRhdGEuaWQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY3JlYXRlT3JkZXIsXG4gICAgICAgICAgICBvbkFwcHJvdmU6b25BcHByb3ZlKHRoaXMsIHRoaXMuZXJyb3JIYW5kbGVyLCB0aGlzLnNwaW5uZXIpLFxuICAgICAgICAgICAgb25DYW5jZWw6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBzcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkVycm9yOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIuZ2VuZXJpY0Vycm9yKCk7XG4gICAgICAgICAgICAgICAgc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IENoZWNrb3V0QWN0aW9uSGFuZGxlcjtcbiIsImNvbnN0IGdldEVsZW1lbnQgPSAoc2VsZWN0b3JPckVsZW1lbnQpID0+IHtcbiAgICBpZiAodHlwZW9mIHNlbGVjdG9yT3JFbGVtZW50ID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvck9yRWxlbWVudCk7XG4gICAgfVxuICAgIHJldHVybiBzZWxlY3Rvck9yRWxlbWVudDtcbn1cblxuZXhwb3J0IGNvbnN0IGlzVmlzaWJsZSA9IChlbGVtZW50KSA9PiB7XG4gICAgcmV0dXJuICEhKGVsZW1lbnQub2Zmc2V0V2lkdGggfHwgZWxlbWVudC5vZmZzZXRIZWlnaHQgfHwgZWxlbWVudC5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCk7XG59XG5cbmV4cG9ydCBjb25zdCBzZXRWaXNpYmxlID0gKHNlbGVjdG9yT3JFbGVtZW50LCBzaG93LCBpbXBvcnRhbnQgPSBmYWxzZSkgPT4ge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBnZXRFbGVtZW50KHNlbGVjdG9yT3JFbGVtZW50KTtcbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IGVsZW1lbnQuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgnZGlzcGxheScpO1xuXG4gICAgaWYgKCFzaG93KSB7XG4gICAgICAgIGlmIChjdXJyZW50VmFsdWUgPT09ICdub25lJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudC5zdHlsZS5zZXRQcm9wZXJ0eSgnZGlzcGxheScsICdub25lJywgaW1wb3J0YW50ID8gJ2ltcG9ydGFudCcgOiAnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlLnJlbW92ZVByb3BlcnR5KCdkaXNwbGF5Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBzdGlsbCBub3QgdmlzaWJsZSAoaWYgc29tZXRoaW5nIGVsc2UgYWRkZWQgZGlzcGxheTogbm9uZSBpbiBDU1MpXG4gICAgICAgIGlmICghaXNWaXNpYmxlKGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5leHBvcnQgY29uc3QgaGlkZSA9IChzZWxlY3Rvck9yRWxlbWVudCwgaW1wb3J0YW50ID0gZmFsc2UpID0+IHtcbiAgICBzZXRWaXNpYmxlKHNlbGVjdG9yT3JFbGVtZW50LCBmYWxzZSwgaW1wb3J0YW50KTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaG93ID0gKHNlbGVjdG9yT3JFbGVtZW50KSA9PiB7XG4gICAgc2V0VmlzaWJsZShzZWxlY3Rvck9yRWxlbWVudCwgdHJ1ZSk7XG59O1xuIiwiaW1wb3J0IEVycm9ySGFuZGxlciBmcm9tICcuLi9FcnJvckhhbmRsZXInO1xuaW1wb3J0IENoZWNrb3V0QWN0aW9uSGFuZGxlciBmcm9tICcuLi9BY3Rpb25IYW5kbGVyL0NoZWNrb3V0QWN0aW9uSGFuZGxlcic7XG5pbXBvcnQgeyBzZXRWaXNpYmxlIH0gZnJvbSAnLi4vSGVscGVyL0hpZGluZyc7XG5pbXBvcnQge1xuICAgIGdldEN1cnJlbnRQYXltZW50TWV0aG9kLFxuICAgIGlzU2F2ZWRDYXJkU2VsZWN0ZWQsIE9SREVSX0JVVFRPTl9TRUxFQ1RPUixcbiAgICBQYXltZW50TWV0aG9kc1xufSBmcm9tIFwiLi4vSGVscGVyL0NoZWNrb3V0TWV0aG9kU3RhdGVcIjtcblxuY2xhc3MgQ2hlY2tvdXRCb290c3RhcCB7XG4gICAgY29uc3RydWN0b3IoZ2F0ZXdheSwgcmVuZGVyZXIsIG1lc3NhZ2VzLCBzcGlubmVyKSB7XG4gICAgICAgIHRoaXMuZ2F0ZXdheSA9IGdhdGV3YXk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcbiAgICAgICAgdGhpcy5tZXNzYWdlcyA9IG1lc3NhZ2VzO1xuICAgICAgICB0aGlzLnNwaW5uZXIgPSBzcGlubmVyO1xuXG4gICAgICAgIHRoaXMuc3RhbmRhcmRPcmRlckJ1dHRvblNlbGVjdG9yID0gT1JERVJfQlVUVE9OX1NFTEVDVE9SO1xuXG4gICAgICAgIHRoaXMuYnV0dG9uQ2hhbmdlT2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigoZWwpID0+IHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVWkoKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaW5pdCgpIHtcbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcblxuICAgICAgICAvLyBVbnNlbGVjdCBzYXZlZCBjYXJkLlxuICAgICAgICAvLyBXQyBzYXZlcyBmb3JtIHZhbHVlcywgc28gd2l0aCBvdXIgY3VycmVudCBVSSBpdCB3b3VsZCBiZSBhIGJpdCB3ZWlyZFxuICAgICAgICAvLyBpZiB0aGUgdXNlciBwYWlkIHdpdGggc2F2ZWQsIHRoZW4gYWZ0ZXIgc29tZSB0aW1lIHRyaWVzIHRvIHBheSBhZ2FpbixcbiAgICAgICAgLy8gYnV0IHdhbnRzIHRvIGVudGVyIGEgbmV3IGNhcmQsIGFuZCB0byBkbyB0aGF0IHRoZXkgaGF2ZSB0byBjaG9vc2Ug4oCcU2VsZWN0IHBheW1lbnTigJ0gaW4gdGhlIGxpc3QuXG4gICAgICAgIGpRdWVyeSgnI3NhdmVkLWNyZWRpdC1jYXJkJykudmFsKGpRdWVyeSgnI3NhdmVkLWNyZWRpdC1jYXJkIG9wdGlvbjpmaXJzdCcpLnZhbCgpKTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQuYm9keSkub24oJ3VwZGF0ZWRfY2hlY2tvdXQnLCAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcigpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGpRdWVyeShkb2N1bWVudC5ib2R5KS5vbigndXBkYXRlZF9jaGVja291dCBwYXltZW50X21ldGhvZF9zZWxlY3RlZCcsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlVWkoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgalF1ZXJ5KGRvY3VtZW50KS5vbignaG9zdGVkX2ZpZWxkc19sb2FkZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBqUXVlcnkoJyNzYXZlZC1jcmVkaXQtY2FyZCcpLm9uKCdjaGFuZ2UnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVVaSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy51cGRhdGVVaSgpO1xuICAgIH1cblxuICAgIHNob3VsZFJlbmRlcigpIHtcbiAgICAgICAgaWYgKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5nYXRld2F5LmJ1dHRvbi5jYW5jZWxfd3JhcHBlcikpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcikgIT09IG51bGwgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmdhdGV3YXkuaG9zdGVkX2ZpZWxkcy53cmFwcGVyKSAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGlmICghdGhpcy5zaG91bGRSZW5kZXIoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIgKyAnPmRpdicpKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIgKyAnPmRpdicpLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYWN0aW9uSGFuZGxlciA9IG5ldyBDaGVja291dEFjdGlvbkhhbmRsZXIoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICBuZXcgRXJyb3JIYW5kbGVyKHRoaXMuZ2F0ZXdheS5sYWJlbHMuZXJyb3IuZ2VuZXJpYyksXG4gICAgICAgICAgICB0aGlzLnNwaW5uZXJcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcihcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5idXR0b24ud3JhcHBlcixcbiAgICAgICAgICAgIHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIsXG4gICAgICAgICAgICBhY3Rpb25IYW5kbGVyLmNvbmZpZ3VyYXRpb24oKSxcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmJ1dHRvbkNoYW5nZU9ic2VydmVyLm9ic2VydmUoXG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHRoaXMuc3RhbmRhcmRPcmRlckJ1dHRvblNlbGVjdG9yKSxcbiAgICAgICAgICAgIHthdHRyaWJ1dGVzOiB0cnVlfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHVwZGF0ZVVpKCkge1xuICAgICAgICBjb25zdCBjdXJyZW50UGF5bWVudE1ldGhvZCA9IGdldEN1cnJlbnRQYXltZW50TWV0aG9kKCk7XG4gICAgICAgIGNvbnN0IGlzUGF5cGFsID0gY3VycmVudFBheW1lbnRNZXRob2QgPT09IFBheW1lbnRNZXRob2RzLlBBWVBBTDtcbiAgICAgICAgY29uc3QgaXNDYXJkID0gY3VycmVudFBheW1lbnRNZXRob2QgPT09IFBheW1lbnRNZXRob2RzLkNBUkRTO1xuICAgICAgICBjb25zdCBpc1NhdmVkQ2FyZCA9IGlzQ2FyZCAmJiBpc1NhdmVkQ2FyZFNlbGVjdGVkKCk7XG4gICAgICAgIGNvbnN0IGlzTm90T3VyR2F0ZXdheSA9ICFpc1BheXBhbCAmJiAhaXNDYXJkO1xuICAgICAgICBjb25zdCBpc0ZyZWVUcmlhbCA9IFBheVBhbENvbW1lcmNlR2F0ZXdheS5pc19mcmVlX3RyaWFsX2NhcnQ7XG4gICAgICAgIGNvbnN0IGhhc1ZhdWx0ZWRQYXlwYWwgPSBQYXlQYWxDb21tZXJjZUdhdGV3YXkudmF1bHRlZF9wYXlwYWxfZW1haWwgIT09ICcnO1xuXG4gICAgICAgIHNldFZpc2libGUodGhpcy5zdGFuZGFyZE9yZGVyQnV0dG9uU2VsZWN0b3IsICAoaXNQYXlwYWwgJiYgaXNGcmVlVHJpYWwgJiYgaGFzVmF1bHRlZFBheXBhbCkgfHwgaXNOb3RPdXJHYXRld2F5IHx8IGlzU2F2ZWRDYXJkLCB0cnVlKTtcbiAgICAgICAgc2V0VmlzaWJsZSgnLnBwY3AtdmF1bHRlZC1wYXlwYWwtZGV0YWlscycsIGlzUGF5cGFsKTtcbiAgICAgICAgc2V0VmlzaWJsZSh0aGlzLmdhdGV3YXkuYnV0dG9uLndyYXBwZXIsIGlzUGF5cGFsICYmICEoaXNGcmVlVHJpYWwgJiYgaGFzVmF1bHRlZFBheXBhbCkpO1xuICAgICAgICBzZXRWaXNpYmxlKHRoaXMuZ2F0ZXdheS5tZXNzYWdlcy53cmFwcGVyLCBpc1BheXBhbCAmJiAhaXNGcmVlVHJpYWwpO1xuICAgICAgICBzZXRWaXNpYmxlKHRoaXMuZ2F0ZXdheS5ob3N0ZWRfZmllbGRzLndyYXBwZXIsIGlzQ2FyZCAmJiAhaXNTYXZlZENhcmQpO1xuXG4gICAgICAgIGlmIChpc1BheXBhbCAmJiAhaXNGcmVlVHJpYWwpIHtcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZXMucmVuZGVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNDYXJkKSB7XG4gICAgICAgICAgICBpZiAoaXNTYXZlZENhcmQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRpc2FibGVDcmVkaXRDYXJkRmllbGRzKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlQ3JlZGl0Q2FyZEZpZWxkcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGlzYWJsZUNyZWRpdENhcmRGaWVsZHMoKSB7XG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwicHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyXCJdJykuYWRkQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyJykuYWRkQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCdsYWJlbFtmb3I9XCJwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1leHBpcnlcIl0nKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1leHBpcnknKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJ2xhYmVsW2Zvcj1cInBwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWN2Y1wiXScpLmFkZENsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLWN2YycpLmFkZENsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwidmF1bHRcIl0nKS5hZGRDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLXZhdWx0JykuYWRkQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC12YXVsdCcpLmF0dHIoXCJkaXNhYmxlZFwiLCB0cnVlKVxuICAgICAgICB0aGlzLnJlbmRlcmVyLmRpc2FibGVDcmVkaXRDYXJkRmllbGRzKClcbiAgICB9XG5cbiAgICBlbmFibGVDcmVkaXRDYXJkRmllbGRzKCkge1xuICAgICAgICBqUXVlcnkoJ2xhYmVsW2Zvcj1cInBwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLW51bWJlclwiXScpLnJlbW92ZUNsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLW51bWJlcicpLnJlbW92ZUNsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnbGFiZWxbZm9yPVwicHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtZXhwaXJ5XCJdJykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtZXhwaXJ5JykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCdsYWJlbFtmb3I9XCJwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1jdmNcIl0nKS5yZW1vdmVDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1jdmMnKS5yZW1vdmVDbGFzcygncHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWZvcm0tZmllbGQtZGlzYWJsZWQnKVxuICAgICAgICBqUXVlcnkoJ2xhYmVsW2Zvcj1cInZhdWx0XCJdJykucmVtb3ZlQ2xhc3MoJ3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1mb3JtLWZpZWxkLWRpc2FibGVkJylcbiAgICAgICAgalF1ZXJ5KCcjcHBjcC1jcmVkaXQtY2FyZC12YXVsdCcpLnJlbW92ZUNsYXNzKCdwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktZm9ybS1maWVsZC1kaXNhYmxlZCcpXG4gICAgICAgIGpRdWVyeSgnI3BwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKS5hdHRyKFwiZGlzYWJsZWRcIiwgZmFsc2UpXG4gICAgICAgIHRoaXMucmVuZGVyZXIuZW5hYmxlQ3JlZGl0Q2FyZEZpZWxkcygpXG4gICAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDaGVja291dEJvb3RzdGFwXG4iLCJleHBvcnQgY29uc3QgaXNDaGFuZ2VQYXltZW50UGFnZSA9ICgpID0+IHtcbiAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpXG4gICAgcmV0dXJuIHVybFBhcmFtcy5oYXMoJ2NoYW5nZV9wYXltZW50X21ldGhvZCcpO1xufVxuIiwiaW1wb3J0IENoZWNrb3V0Qm9vdHN0YXAgZnJvbSAnLi9DaGVja291dEJvb3RzdGFwJ1xuaW1wb3J0IHtpc0NoYW5nZVBheW1lbnRQYWdlfSBmcm9tIFwiLi4vSGVscGVyL1N1YnNjcmlwdGlvbnNcIjtcblxuY2xhc3MgUGF5Tm93Qm9vdHN0cmFwIGV4dGVuZHMgQ2hlY2tvdXRCb290c3RhcCB7XG4gICAgY29uc3RydWN0b3IoZ2F0ZXdheSwgcmVuZGVyZXIsIG1lc3NhZ2VzLCBzcGlubmVyKSB7XG4gICAgICAgIHN1cGVyKGdhdGV3YXksIHJlbmRlcmVyLCBtZXNzYWdlcywgc3Bpbm5lcilcbiAgICB9XG5cbiAgICB1cGRhdGVVaSgpIHtcbiAgICAgICAgaWYgKGlzQ2hhbmdlUGF5bWVudFBhZ2UoKSkge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cblxuICAgICAgICBzdXBlci51cGRhdGVVaSgpO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUGF5Tm93Qm9vdHN0cmFwO1xuIiwiY2xhc3MgUmVuZGVyZXIge1xuICAgIGNvbnN0cnVjdG9yKGNyZWRpdENhcmRSZW5kZXJlciwgZGVmYXVsdENvbmZpZywgb25TbWFydEJ1dHRvbkNsaWNrLCBvblNtYXJ0QnV0dG9uc0luaXQpIHtcbiAgICAgICAgdGhpcy5kZWZhdWx0Q29uZmlnID0gZGVmYXVsdENvbmZpZztcbiAgICAgICAgdGhpcy5jcmVkaXRDYXJkUmVuZGVyZXIgPSBjcmVkaXRDYXJkUmVuZGVyZXI7XG4gICAgICAgIHRoaXMub25TbWFydEJ1dHRvbkNsaWNrID0gb25TbWFydEJ1dHRvbkNsaWNrO1xuICAgICAgICB0aGlzLm9uU21hcnRCdXR0b25zSW5pdCA9IG9uU21hcnRCdXR0b25zSW5pdDtcbiAgICB9XG5cbiAgICByZW5kZXIod3JhcHBlciwgaG9zdGVkRmllbGRzV3JhcHBlciwgY29udGV4dENvbmZpZykge1xuXG4gICAgICAgIHRoaXMucmVuZGVyQnV0dG9ucyh3cmFwcGVyLCBjb250ZXh0Q29uZmlnKTtcbiAgICAgICAgdGhpcy5jcmVkaXRDYXJkUmVuZGVyZXIucmVuZGVyKGhvc3RlZEZpZWxkc1dyYXBwZXIsIGNvbnRleHRDb25maWcpO1xuICAgIH1cblxuICAgIHJlbmRlckJ1dHRvbnMod3JhcHBlciwgY29udGV4dENvbmZpZykge1xuICAgICAgICBpZiAoISBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHdyYXBwZXIpIHx8IHRoaXMuaXNBbHJlYWR5UmVuZGVyZWQod3JhcHBlcikgfHwgJ3VuZGVmaW5lZCcgPT09IHR5cGVvZiBwYXlwYWwuQnV0dG9ucyApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0eWxlID0gd3JhcHBlciA9PT0gdGhpcy5kZWZhdWx0Q29uZmlnLmJ1dHRvbi53cmFwcGVyID8gdGhpcy5kZWZhdWx0Q29uZmlnLmJ1dHRvbi5zdHlsZSA6IHRoaXMuZGVmYXVsdENvbmZpZy5idXR0b24ubWluaV9jYXJ0X3N0eWxlO1xuICAgICAgICBwYXlwYWwuQnV0dG9ucyh7XG4gICAgICAgICAgICBzdHlsZSxcbiAgICAgICAgICAgIC4uLmNvbnRleHRDb25maWcsXG4gICAgICAgICAgICBvbkNsaWNrOiB0aGlzLm9uU21hcnRCdXR0b25DbGljayxcbiAgICAgICAgICAgIG9uSW5pdDogdGhpcy5vblNtYXJ0QnV0dG9uc0luaXQsXG4gICAgICAgIH0pLnJlbmRlcih3cmFwcGVyKTtcbiAgICB9XG5cbiAgICBpc0FscmVhZHlSZW5kZXJlZCh3cmFwcGVyKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHdyYXBwZXIpLmhhc0NoaWxkTm9kZXMoKTtcbiAgICB9XG5cbiAgICBoaWRlQnV0dG9ucyhlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGVsZW1lbnQpO1xuICAgICAgICBpZiAoISBkb21FbGVtZW50ICkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGRvbUVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgc2hvd0J1dHRvbnMoZWxlbWVudCkge1xuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihlbGVtZW50KTtcbiAgICAgICAgaWYgKCEgZG9tRWxlbWVudCApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBkb21FbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBkaXNhYmxlQ3JlZGl0Q2FyZEZpZWxkcygpIHtcbiAgICAgICAgdGhpcy5jcmVkaXRDYXJkUmVuZGVyZXIuZGlzYWJsZUZpZWxkcygpO1xuICAgIH1cblxuICAgIGVuYWJsZUNyZWRpdENhcmRGaWVsZHMoKSB7XG4gICAgICAgIHRoaXMuY3JlZGl0Q2FyZFJlbmRlcmVyLmVuYWJsZUZpZWxkcygpO1xuICAgIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUmVuZGVyZXI7XG4iLCJjb25zdCBkY2NJbnB1dEZhY3RvcnkgPSAob3JpZ2luYWwpID0+IHtcbiAgICBjb25zdCBzdHlsZXMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShvcmlnaW5hbCk7XG4gICAgY29uc3QgbmV3RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICBuZXdFbGVtZW50LnNldEF0dHJpYnV0ZSgnaWQnLCBvcmlnaW5hbC5pZCk7XG4gICAgT2JqZWN0LnZhbHVlcyhzdHlsZXMpLmZvckVhY2goIChwcm9wKSA9PiB7XG4gICAgICAgIGlmICghIHN0eWxlc1twcm9wXSB8fCAhIGlzTmFOKHByb3ApICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIG5ld0VsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkocHJvcCwnJyArIHN0eWxlc1twcm9wXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG5ld0VsZW1lbnQ7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGRjY0lucHV0RmFjdG9yeTsiLCJpbXBvcnQgZGNjSW5wdXRGYWN0b3J5IGZyb20gXCIuLi9IZWxwZXIvRGNjSW5wdXRGYWN0b3J5XCI7XG5pbXBvcnQge3Nob3d9IGZyb20gXCIuLi9IZWxwZXIvSGlkaW5nXCI7XG5cbmNsYXNzIENyZWRpdENhcmRSZW5kZXJlciB7XG5cbiAgICBjb25zdHJ1Y3RvcihkZWZhdWx0Q29uZmlnLCBlcnJvckhhbmRsZXIsIHNwaW5uZXIpIHtcbiAgICAgICAgdGhpcy5kZWZhdWx0Q29uZmlnID0gZGVmYXVsdENvbmZpZztcbiAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIgPSBlcnJvckhhbmRsZXI7XG4gICAgICAgIHRoaXMuc3Bpbm5lciA9IHNwaW5uZXI7XG4gICAgICAgIHRoaXMuY2FyZFZhbGlkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZm9ybVZhbGlkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlID0gbnVsbDtcbiAgICB9XG5cbiAgICByZW5kZXIod3JhcHBlciwgY29udGV4dENvbmZpZykge1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRDb25maWcuY29udGV4dCAhPT0gJ2NoZWNrb3V0J1xuICAgICAgICAgICAgICAgICYmIHRoaXMuZGVmYXVsdENvbmZpZy5jb250ZXh0ICE9PSAncGF5LW5vdydcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHx8IHdyYXBwZXIgPT09IG51bGxcbiAgICAgICAgICAgIHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iod3JhcHBlcikgPT09IG51bGxcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdHlwZW9mIHBheXBhbC5Ib3N0ZWRGaWVsZHMgPT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgICB8fCAhIHBheXBhbC5Ib3N0ZWRGaWVsZHMuaXNFbGlnaWJsZSgpXG4gICAgICAgICkge1xuICAgICAgICAgICAgY29uc3Qgd3JhcHBlckVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKHdyYXBwZXIpO1xuICAgICAgICAgICAgd3JhcHBlckVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh3cmFwcGVyRWxlbWVudCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBidXR0b25TZWxlY3RvciA9IHdyYXBwZXIgKyAnIGJ1dHRvbic7XG5cbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS50ZWFyZG93bigpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGVyciA9PiBjb25zb2xlLmVycm9yKGBIb3N0ZWQgZmllbGRzIHRlYXJkb3duIGVycm9yOiAke2Vycn1gKSk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZSA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBnYXRlV2F5Qm94ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnBheW1lbnRfYm94LnBheW1lbnRfbWV0aG9kX3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheScpO1xuICAgICAgICBjb25zdCBvbGREaXNwbGF5U3R5bGUgPSBnYXRlV2F5Qm94LnN0eWxlLmRpc3BsYXk7XG4gICAgICAgIGdhdGVXYXlCb3guc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG5cbiAgICAgICAgY29uc3QgaGlkZURjY0dhdGV3YXkgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcHBjcC1oaWRlLWRjYycpO1xuICAgICAgICBpZiAoaGlkZURjY0dhdGV3YXkpIHtcbiAgICAgICAgICAgIGhpZGVEY2NHYXRld2F5LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoaGlkZURjY0dhdGV3YXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2FyZE51bWJlckZpZWxkID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignI3BwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLW51bWJlcicpO1xuXG4gICAgICAgIGNvbnN0IHN0eWxlc1JhdyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGNhcmROdW1iZXJGaWVsZCk7XG4gICAgICAgIGxldCBzdHlsZXMgPSB7fTtcbiAgICAgICAgT2JqZWN0LnZhbHVlcyhzdHlsZXNSYXcpLmZvckVhY2goIChwcm9wKSA9PiB7XG4gICAgICAgICAgICBpZiAoISBzdHlsZXNSYXdbcHJvcF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHlsZXNbcHJvcF0gPSAnJyArIHN0eWxlc1Jhd1twcm9wXTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgY2FyZE51bWJlciA9IGRjY0lucHV0RmFjdG9yeShjYXJkTnVtYmVyRmllbGQpO1xuICAgICAgICBjYXJkTnVtYmVyRmllbGQucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoY2FyZE51bWJlciwgY2FyZE51bWJlckZpZWxkKTtcblxuICAgICAgICBjb25zdCBjYXJkRXhwaXJ5RmllbGQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtZXhwaXJ5Jyk7XG4gICAgICAgIGNvbnN0IGNhcmRFeHBpcnkgPSBkY2NJbnB1dEZhY3RvcnkoY2FyZEV4cGlyeUZpZWxkKTtcbiAgICAgICAgY2FyZEV4cGlyeUZpZWxkLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKGNhcmRFeHBpcnksIGNhcmRFeHBpcnlGaWVsZCk7XG5cbiAgICAgICAgY29uc3QgY2FyZENvZGVGaWVsZCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1jdmMnKTtcbiAgICAgICAgY29uc3QgY2FyZENvZGUgPSBkY2NJbnB1dEZhY3RvcnkoY2FyZENvZGVGaWVsZCk7XG4gICAgICAgIGNhcmRDb2RlRmllbGQucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoY2FyZENvZGUsIGNhcmRDb2RlRmllbGQpO1xuXG4gICAgICAgIGdhdGVXYXlCb3guc3R5bGUuZGlzcGxheSA9IG9sZERpc3BsYXlTdHlsZTtcblxuICAgICAgICBjb25zdCBmb3JtV3JhcHBlciA9ICcucGF5bWVudF9ib3ggcGF5bWVudF9tZXRob2RfcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5JztcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5kZWZhdWx0Q29uZmlnLmVuZm9yY2VfdmF1bHRcbiAgICAgICAgICAgICYmIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZm9ybVdyYXBwZXIgKyAnIC5wcGNwLWNyZWRpdC1jYXJkLXZhdWx0JylcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGZvcm1XcmFwcGVyICsgJyAucHBjcC1jcmVkaXQtY2FyZC12YXVsdCcpLmNoZWNrZWQgPSB0cnVlO1xuICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihmb3JtV3JhcHBlciArICcgLnBwY3AtY3JlZGl0LWNhcmQtdmF1bHQnKS5zZXRBdHRyaWJ1dGUoJ2Rpc2FibGVkJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcGF5cGFsLkhvc3RlZEZpZWxkcy5yZW5kZXIoe1xuICAgICAgICAgICAgY3JlYXRlT3JkZXI6IGNvbnRleHRDb25maWcuY3JlYXRlT3JkZXIsXG4gICAgICAgICAgICBzdHlsZXM6IHtcbiAgICAgICAgICAgICAgICAnaW5wdXQnOiBzdHlsZXNcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmaWVsZHM6IHtcbiAgICAgICAgICAgICAgICBudW1iZXI6IHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtbnVtYmVyJyxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5jcmVkaXRfY2FyZF9udW1iZXIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBjdnY6IHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0b3I6ICcjcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5LWNhcmQtY3ZjJyxcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI6IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5jdnYsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBleHBpcmF0aW9uRGF0ZToge1xuICAgICAgICAgICAgICAgICAgICBzZWxlY3RvcjogJyNwcGNwLWNyZWRpdC1jYXJkLWdhdGV3YXktY2FyZC1leHBpcnknLFxuICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcjogdGhpcy5kZWZhdWx0Q29uZmlnLmhvc3RlZF9maWVsZHMubGFiZWxzLm1tX3l5LFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkudGhlbihob3N0ZWRGaWVsZHMgPT4ge1xuICAgICAgICAgICAgZG9jdW1lbnQuZGlzcGF0Y2hFdmVudChuZXcgQ3VzdG9tRXZlbnQoXCJob3N0ZWRfZmllbGRzX2xvYWRlZFwiKSk7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZSA9IGhvc3RlZEZpZWxkcztcblxuICAgICAgICAgICAgaG9zdGVkRmllbGRzLm9uKCdpbnB1dFN1Ym1pdFJlcXVlc3QnLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc3VibWl0KGNvbnRleHRDb25maWcpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBob3N0ZWRGaWVsZHMub24oJ2NhcmRUeXBlQ2hhbmdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCAhIGV2ZW50LmNhcmRzLmxlbmd0aCApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJkVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCB2YWxpZENhcmRzID0gdGhpcy5kZWZhdWx0Q29uZmlnLmhvc3RlZF9maWVsZHMudmFsaWRfY2FyZHM7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXJkVmFsaWQgPSB2YWxpZENhcmRzLmluZGV4T2YoZXZlbnQuY2FyZHNbMF0udHlwZSkgIT09IC0xO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIGhvc3RlZEZpZWxkcy5vbigndmFsaWRpdHlDaGFuZ2UnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmb3JtVmFsaWQgPSBPYmplY3Qua2V5cyhldmVudC5maWVsZHMpLmV2ZXJ5KGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV2ZW50LmZpZWxkc1trZXldLmlzVmFsaWQ7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICB0aGlzLmZvcm1WYWxpZCA9IGZvcm1WYWxpZDtcblxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHNob3coYnV0dG9uU2VsZWN0b3IpO1xuXG4gICAgICAgICAgICBpZiAoZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih3cmFwcGVyKS5nZXRBdHRyaWJ1dGUoJ2RhdGEtcHBjcC1zdWJzY3JpYmVkJykgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGJ1dHRvblNlbGVjdG9yKS5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgICAgICAgICAnY2xpY2snLFxuICAgICAgICAgICAgICAgICAgICBldmVudCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3VibWl0KGNvbnRleHRDb25maWcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iod3JhcHBlcikuc2V0QXR0cmlidXRlKCdkYXRhLXBwY3Atc3Vic2NyaWJlZCcsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjcGF5bWVudF9tZXRob2RfcHBjcC1jcmVkaXQtY2FyZC1nYXRld2F5JykuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICdjbGljaycsXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignbGFiZWxbZm9yPXBwY3AtY3JlZGl0LWNhcmQtZ2F0ZXdheS1jYXJkLW51bWJlcl0nKS5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICApXG4gICAgfVxuXG4gICAgZGlzYWJsZUZpZWxkcygpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5zZXRBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6ICdkaXNhYmxlZCdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5zZXRBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnY3Z2JyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6ICdkaXNhYmxlZCdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5zZXRBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnZXhwaXJhdGlvbkRhdGUnLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGVuYWJsZUZpZWxkcygpIHtcbiAgICAgICAgaWYgKHRoaXMuY3VycmVudEhvc3RlZEZpZWxkc0luc3RhbmNlKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5yZW1vdmVBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6ICdkaXNhYmxlZCdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5yZW1vdmVBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnY3Z2JyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6ICdkaXNhYmxlZCdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRIb3N0ZWRGaWVsZHNJbnN0YW5jZS5yZW1vdmVBdHRyaWJ1dGUoe1xuICAgICAgICAgICAgICAgIGZpZWxkOiAnZXhwaXJhdGlvbkRhdGUnLFxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZTogJ2Rpc2FibGVkJ1xuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIF9zdWJtaXQoY29udGV4dENvbmZpZykge1xuICAgICAgICB0aGlzLnNwaW5uZXIuYmxvY2soKTtcbiAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIuY2xlYXIoKTtcblxuICAgICAgICBpZiAodGhpcy5mb3JtVmFsaWQgJiYgdGhpcy5jYXJkVmFsaWQpIHtcbiAgICAgICAgICAgIGNvbnN0IHNhdmVfY2FyZCA9IHRoaXMuZGVmYXVsdENvbmZpZy5jYW5fc2F2ZV92YXVsdF90b2tlbiA/IHRydWUgOiBmYWxzZTtcbiAgICAgICAgICAgIGxldCB2YXVsdCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwcGNwLWNyZWRpdC1jYXJkLXZhdWx0JykgP1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdwcGNwLWNyZWRpdC1jYXJkLXZhdWx0JykuY2hlY2tlZCA6IHNhdmVfY2FyZDtcbiAgICAgICAgICAgIGlmICh0aGlzLmRlZmF1bHRDb25maWcuZW5mb3JjZV92YXVsdCkge1xuICAgICAgICAgICAgICAgIHZhdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGNvbnRpbmdlbmN5ID0gdGhpcy5kZWZhdWx0Q29uZmlnLmhvc3RlZF9maWVsZHMuY29udGluZ2VuY3k7XG4gICAgICAgICAgICBjb25zdCBob3N0ZWRGaWVsZHNEYXRhID0ge1xuICAgICAgICAgICAgICAgIHZhdWx0OiB2YXVsdFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChjb250aW5nZW5jeSAhPT0gJ05PXzNEX1NFQ1VSRScpIHtcbiAgICAgICAgICAgICAgICBob3N0ZWRGaWVsZHNEYXRhLmNvbnRpbmdlbmNpZXMgPSBbY29udGluZ2VuY3ldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5kZWZhdWx0Q29uZmlnLnBheWVyKSB7XG4gICAgICAgICAgICAgICAgaG9zdGVkRmllbGRzRGF0YS5jYXJkaG9sZGVyTmFtZSA9IHRoaXMuZGVmYXVsdENvbmZpZy5wYXllci5uYW1lLmdpdmVuX25hbWUgKyAnICcgKyB0aGlzLmRlZmF1bHRDb25maWcucGF5ZXIubmFtZS5zdXJuYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFob3N0ZWRGaWVsZHNEYXRhLmNhcmRob2xkZXJOYW1lKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmlyc3ROYW1lID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbGxpbmdfZmlyc3RfbmFtZScpID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2JpbGxpbmdfZmlyc3RfbmFtZScpLnZhbHVlIDogJyc7XG4gICAgICAgICAgICAgICAgY29uc3QgbGFzdE5hbWUgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnYmlsbGluZ19sYXN0X25hbWUnKSA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdiaWxsaW5nX2xhc3RfbmFtZScpLnZhbHVlIDogJyc7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWZpcnN0TmFtZSB8fCAhbGFzdE5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIubWVzc2FnZSh0aGlzLmRlZmF1bHRDb25maWcuaG9zdGVkX2ZpZWxkcy5sYWJlbHMuY2FyZGhvbGRlcl9uYW1lX3JlcXVpcmVkKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGhvc3RlZEZpZWxkc0RhdGEuY2FyZGhvbGRlck5hbWUgPSBmaXJzdE5hbWUgKyAnICcgKyBsYXN0TmFtZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2Uuc3VibWl0KGhvc3RlZEZpZWxkc0RhdGEpLnRoZW4oKHBheWxvYWQpID0+IHtcbiAgICAgICAgICAgICAgICBwYXlsb2FkLm9yZGVySUQgPSBwYXlsb2FkLm9yZGVySWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29udGV4dENvbmZpZy5vbkFwcHJvdmUocGF5bG9hZCk7XG4gICAgICAgICAgICB9KS5jYXRjaChlcnIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIuY2xlYXIoKTtcblxuICAgICAgICAgICAgICAgIGlmIChlcnIuZGV0YWlscykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5tZXNzYWdlKGVyci5kZXRhaWxzLm1hcChkID0+IGAke2QuaXNzdWV9ICR7ZC5kZXNjcmlwdGlvbn1gKS5qb2luKCc8YnIvPicpLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gISB0aGlzLmNhcmRWYWxpZCA/IHRoaXMuZGVmYXVsdENvbmZpZy5ob3N0ZWRfZmllbGRzLmxhYmVscy5jYXJkX25vdF9zdXBwb3J0ZWQgOiB0aGlzLmRlZmF1bHRDb25maWcuaG9zdGVkX2ZpZWxkcy5sYWJlbHMuZmllbGRzX25vdF92YWxpZDtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLm1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5leHBvcnQgZGVmYXVsdCBDcmVkaXRDYXJkUmVuZGVyZXI7XG4iLCJjb25zdCBzdG9yYWdlS2V5ID0gJ3BwY3AtZGF0YS1jbGllbnQtaWQnO1xuXG5jb25zdCB2YWxpZGF0ZVRva2VuID0gKHRva2VuLCB1c2VyKSA9PiB7XG4gICAgaWYgKCEgdG9rZW4pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAodG9rZW4udXNlciAhPT0gdXNlcikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGN1cnJlbnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgY29uc3QgaXNFeHBpcmVkID0gY3VycmVudFRpbWUgPj0gdG9rZW4uZXhwaXJhdGlvbiAqIDEwMDA7XG4gICAgcmV0dXJuICEgaXNFeHBpcmVkO1xufVxuXG5jb25zdCBzdG9yZWRUb2tlbkZvclVzZXIgPSAodXNlcikgPT4ge1xuICAgIGNvbnN0IHRva2VuID0gSlNPTi5wYXJzZShzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKHN0b3JhZ2VLZXkpKTtcbiAgICBpZiAodmFsaWRhdGVUb2tlbih0b2tlbiwgdXNlcikpIHtcbiAgICAgICAgcmV0dXJuIHRva2VuLnRva2VuO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuY29uc3Qgc3RvcmVUb2tlbiA9ICh0b2tlbikgPT4ge1xuICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oc3RvcmFnZUtleSwgSlNPTi5zdHJpbmdpZnkodG9rZW4pKTtcbn1cblxuY29uc3QgZGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlciA9IChzY3JpcHQsIGNvbmZpZykgPT4ge1xuICAgIGZldGNoKGNvbmZpZy5lbmRwb2ludCwge1xuICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgbm9uY2U6IGNvbmZpZy5ub25jZVxuICAgICAgICB9KVxuICAgIH0pLnRoZW4oKHJlcyk9PntcbiAgICAgICAgcmV0dXJuIHJlcy5qc29uKCk7XG4gICAgfSkudGhlbigoZGF0YSk9PntcbiAgICAgICAgY29uc3QgaXNWYWxpZCA9IHZhbGlkYXRlVG9rZW4oZGF0YSwgY29uZmlnLnVzZXIpO1xuICAgICAgICBpZiAoIWlzVmFsaWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdG9yZVRva2VuKGRhdGEpO1xuICAgICAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCdkYXRhLWNsaWVudC10b2tlbicsIGRhdGEudG9rZW4pO1xuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZChzY3JpcHQpO1xuICAgIH0pO1xufVxuXG5leHBvcnQgZGVmYXVsdCBkYXRhQ2xpZW50SWRBdHRyaWJ1dGVIYW5kbGVyO1xuIiwiY2xhc3MgTWVzc2FnZVJlbmRlcmVyIHtcblxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZykge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICB9XG5cbiAgICByZW5kZXIoKSB7XG4gICAgICAgIGlmICghIHRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHBheXBhbC5NZXNzYWdlcyh7XG4gICAgICAgICAgICBhbW91bnQ6IHRoaXMuY29uZmlnLmFtb3VudCxcbiAgICAgICAgICAgIHBsYWNlbWVudDogdGhpcy5jb25maWcucGxhY2VtZW50LFxuICAgICAgICAgICAgc3R5bGU6IHRoaXMuY29uZmlnLnN0eWxlXG4gICAgICAgIH0pLnJlbmRlcih0aGlzLmNvbmZpZy53cmFwcGVyKTtcbiAgICB9XG5cbiAgICByZW5kZXJXaXRoQW1vdW50KGFtb3VudCkge1xuXG4gICAgICAgIGlmICghIHRoaXMuc2hvdWxkUmVuZGVyKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5ld1dyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgbmV3V3JhcHBlci5zZXRBdHRyaWJ1dGUoJ2lkJywgdGhpcy5jb25maWcud3JhcHBlci5yZXBsYWNlKCcjJywgJycpKTtcblxuICAgICAgICBjb25zdCBzaWJsaW5nID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmNvbmZpZy53cmFwcGVyKS5uZXh0U2libGluZztcbiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcih0aGlzLmNvbmZpZy53cmFwcGVyKS5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5jb25maWcud3JhcHBlcikpO1xuICAgICAgICBzaWJsaW5nLnBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG5ld1dyYXBwZXIsIHNpYmxpbmcpO1xuICAgICAgICBwYXlwYWwuTWVzc2FnZXMoe1xuICAgICAgICAgICAgYW1vdW50LFxuICAgICAgICAgICAgcGxhY2VtZW50OiB0aGlzLmNvbmZpZy5wbGFjZW1lbnQsXG4gICAgICAgICAgICBzdHlsZTogdGhpcy5jb25maWcuc3R5bGVcbiAgICAgICAgfSkucmVuZGVyKHRoaXMuY29uZmlnLndyYXBwZXIpO1xuICAgIH1cblxuICAgIHNob3VsZFJlbmRlcigpIHtcblxuICAgICAgICBpZiAodHlwZW9mIHBheXBhbC5NZXNzYWdlcyA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIHRoaXMuY29uZmlnLndyYXBwZXIgPT09ICd1bmRlZmluZWQnICkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodGhpcy5jb25maWcud3JhcHBlcikpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5leHBvcnQgZGVmYXVsdCBNZXNzYWdlUmVuZGVyZXI7IiwiY2xhc3MgU3Bpbm5lciB7XG5cbiAgICBjb25zdHJ1Y3Rvcih0YXJnZXQgPSAnZm9ybS53b29jb21tZXJjZS1jaGVja291dCcpIHtcbiAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgfVxuXG4gICAgc2V0VGFyZ2V0KHRhcmdldCkge1xuICAgICAgICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgICB9XG5cbiAgICBibG9jaygpIHtcblxuICAgICAgICBqUXVlcnkoIHRoaXMudGFyZ2V0ICkuYmxvY2soe1xuICAgICAgICAgICAgbWVzc2FnZTogbnVsbCxcbiAgICAgICAgICAgIG92ZXJsYXlDU1M6IHtcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAnI2ZmZicsXG4gICAgICAgICAgICAgICAgb3BhY2l0eTogMC42XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHVuYmxvY2soKSB7XG5cbiAgICAgICAgalF1ZXJ5KCB0aGlzLnRhcmdldCApLnVuYmxvY2soKTtcbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNwaW5uZXI7XG4iLCJpbXBvcnQge1BheW1lbnRNZXRob2RzfSBmcm9tIFwiLi4vSGVscGVyL0NoZWNrb3V0TWV0aG9kU3RhdGVcIjtcbmltcG9ydCBlcnJvckhhbmRsZXIgZnJvbSBcIi4uL0Vycm9ySGFuZGxlclwiO1xuXG5jbGFzcyBGcmVlVHJpYWxIYW5kbGVyIHtcbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBzcGlubmVyLFxuICAgICAgICBlcnJvckhhbmRsZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMuc3Bpbm5lciA9IHNwaW5uZXI7XG4gICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyID0gZXJyb3JIYW5kbGVyO1xuICAgIH1cblxuICAgIGhhbmRsZSgpXG4gICAge1xuICAgICAgICB0aGlzLnNwaW5uZXIuYmxvY2soKTtcblxuICAgICAgICBmZXRjaCh0aGlzLmNvbmZpZy5hamF4LnZhdWx0X3BheXBhbC5lbmRwb2ludCwge1xuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgbm9uY2U6IHRoaXMuY29uZmlnLmFqYXgudmF1bHRfcGF5cGFsLm5vbmNlLFxuICAgICAgICAgICAgICAgIHJldHVybl91cmw6IGxvY2F0aW9uLmhyZWZcbiAgICAgICAgICAgIH0pLFxuICAgICAgICB9KS50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcmVzLmpzb24oKTtcbiAgICAgICAgfSkudGhlbihkYXRhID0+IHtcbiAgICAgICAgICAgIGlmICghZGF0YS5zdWNjZXNzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGRhdGEpO1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLm1lc3NhZ2UoZGF0YS5kYXRhLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGRhdGEuZGF0YS5tZXNzYWdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IGRhdGEuZGF0YS5hcHByb3ZlX2xpbms7XG4gICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgIHRoaXMuc3Bpbm5lci51bmJsb2NrKCk7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmdlbmVyaWNFcnJvcigpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5leHBvcnQgZGVmYXVsdCBGcmVlVHJpYWxIYW5kbGVyO1xuIiwiaW1wb3J0IE1pbmlDYXJ0Qm9vdHN0YXAgZnJvbSAnLi9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvTWluaUNhcnRCb290c3RhcCc7XG5pbXBvcnQgU2luZ2xlUHJvZHVjdEJvb3RzdGFwIGZyb20gJy4vbW9kdWxlcy9Db250ZXh0Qm9vdHN0cmFwL1NpbmdsZVByb2R1Y3RCb290c3RhcCc7XG5pbXBvcnQgQ2FydEJvb3RzdHJhcCBmcm9tICcuL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9DYXJ0Qm9vdHN0YXAnO1xuaW1wb3J0IENoZWNrb3V0Qm9vdHN0YXAgZnJvbSAnLi9tb2R1bGVzL0NvbnRleHRCb290c3RyYXAvQ2hlY2tvdXRCb290c3RhcCc7XG5pbXBvcnQgUGF5Tm93Qm9vdHN0cmFwIGZyb20gXCIuL21vZHVsZXMvQ29udGV4dEJvb3RzdHJhcC9QYXlOb3dCb290c3RyYXBcIjtcbmltcG9ydCBSZW5kZXJlciBmcm9tICcuL21vZHVsZXMvUmVuZGVyZXIvUmVuZGVyZXInO1xuaW1wb3J0IEVycm9ySGFuZGxlciBmcm9tICcuL21vZHVsZXMvRXJyb3JIYW5kbGVyJztcbmltcG9ydCBDcmVkaXRDYXJkUmVuZGVyZXIgZnJvbSBcIi4vbW9kdWxlcy9SZW5kZXJlci9DcmVkaXRDYXJkUmVuZGVyZXJcIjtcbmltcG9ydCBkYXRhQ2xpZW50SWRBdHRyaWJ1dGVIYW5kbGVyIGZyb20gXCIuL21vZHVsZXMvRGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlclwiO1xuaW1wb3J0IE1lc3NhZ2VSZW5kZXJlciBmcm9tIFwiLi9tb2R1bGVzL1JlbmRlcmVyL01lc3NhZ2VSZW5kZXJlclwiO1xuaW1wb3J0IFNwaW5uZXIgZnJvbSBcIi4vbW9kdWxlcy9IZWxwZXIvU3Bpbm5lclwiO1xuaW1wb3J0IHtcbiAgICBnZXRDdXJyZW50UGF5bWVudE1ldGhvZCxcbiAgICBPUkRFUl9CVVRUT05fU0VMRUNUT1IsXG4gICAgUGF5bWVudE1ldGhvZHNcbn0gZnJvbSBcIi4vbW9kdWxlcy9IZWxwZXIvQ2hlY2tvdXRNZXRob2RTdGF0ZVwiO1xuaW1wb3J0IHtoaWRlLCBzZXRWaXNpYmxlfSBmcm9tIFwiLi9tb2R1bGVzL0hlbHBlci9IaWRpbmdcIjtcbmltcG9ydCB7aXNDaGFuZ2VQYXltZW50UGFnZX0gZnJvbSBcIi4vbW9kdWxlcy9IZWxwZXIvU3Vic2NyaXB0aW9uc1wiO1xuaW1wb3J0IEZyZWVUcmlhbEhhbmRsZXIgZnJvbSBcIi4vbW9kdWxlcy9BY3Rpb25IYW5kbGVyL0ZyZWVUcmlhbEhhbmRsZXJcIjtcblxuY29uc3QgYnV0dG9uc1NwaW5uZXIgPSBuZXcgU3Bpbm5lcignLnBwYy1idXR0b24td3JhcHBlcicpO1xuY29uc3QgY2FyZHNTcGlubmVyID0gbmV3IFNwaW5uZXIoJyNwcGNwLWhvc3RlZC1maWVsZHMnKTtcblxuY29uc3QgYm9vdHN0cmFwID0gKCkgPT4ge1xuICAgIGNvbnN0IGVycm9ySGFuZGxlciA9IG5ldyBFcnJvckhhbmRsZXIoUGF5UGFsQ29tbWVyY2VHYXRld2F5LmxhYmVscy5lcnJvci5nZW5lcmljKTtcbiAgICBjb25zdCBzcGlubmVyID0gbmV3IFNwaW5uZXIoKTtcbiAgICBjb25zdCBjcmVkaXRDYXJkUmVuZGVyZXIgPSBuZXcgQ3JlZGl0Q2FyZFJlbmRlcmVyKFBheVBhbENvbW1lcmNlR2F0ZXdheSwgZXJyb3JIYW5kbGVyLCBzcGlubmVyKTtcblxuICAgIGNvbnN0IGZyZWVUcmlhbEhhbmRsZXIgPSBuZXcgRnJlZVRyaWFsSGFuZGxlcihQYXlQYWxDb21tZXJjZUdhdGV3YXksIHNwaW5uZXIsIGVycm9ySGFuZGxlcik7XG5cbiAgICBjb25zdCBvblNtYXJ0QnV0dG9uQ2xpY2sgPSAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICB3aW5kb3cucHBjcEZ1bmRpbmdTb3VyY2UgPSBkYXRhLmZ1bmRpbmdTb3VyY2U7XG5cbiAgICAgICAgY29uc3QgZm9ybSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0ud29vY29tbWVyY2UtY2hlY2tvdXQnKTtcbiAgICAgICAgaWYgKGZvcm0pIHtcbiAgICAgICAgICAgIGpRdWVyeSgnI3BwY3AtZnVuZGluZy1zb3VyY2UtZm9ybS1pbnB1dCcpLnJlbW92ZSgpO1xuICAgICAgICAgICAgZm9ybS5pbnNlcnRBZGphY2VudEhUTUwoXG4gICAgICAgICAgICAgICAgJ2JlZm9yZWVuZCcsXG4gICAgICAgICAgICAgICAgYDxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cInBwY3AtZnVuZGluZy1zb3VyY2VcIiB2YWx1ZT1cIiR7ZGF0YS5mdW5kaW5nU291cmNlfVwiIGlkPVwicHBjcC1mdW5kaW5nLXNvdXJjZS1mb3JtLWlucHV0XCI+YFxuICAgICAgICAgICAgKVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNGcmVlVHJpYWwgPSBQYXlQYWxDb21tZXJjZUdhdGV3YXkuaXNfZnJlZV90cmlhbF9jYXJ0O1xuICAgICAgICBpZiAoaXNGcmVlVHJpYWwgJiYgZGF0YS5mdW5kaW5nU291cmNlICE9PSAnY2FyZCcpIHtcbiAgICAgICAgICAgIGZyZWVUcmlhbEhhbmRsZXIuaGFuZGxlKCk7XG4gICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5yZWplY3QoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgb25TbWFydEJ1dHRvbnNJbml0ID0gKCkgPT4ge1xuICAgICAgICBidXR0b25zU3Bpbm5lci51bmJsb2NrKCk7XG4gICAgfTtcbiAgICBjb25zdCByZW5kZXJlciA9IG5ldyBSZW5kZXJlcihjcmVkaXRDYXJkUmVuZGVyZXIsIFBheVBhbENvbW1lcmNlR2F0ZXdheSwgb25TbWFydEJ1dHRvbkNsaWNrLCBvblNtYXJ0QnV0dG9uc0luaXQpO1xuICAgIGNvbnN0IG1lc3NhZ2VSZW5kZXJlciA9IG5ldyBNZXNzYWdlUmVuZGVyZXIoUGF5UGFsQ29tbWVyY2VHYXRld2F5Lm1lc3NhZ2VzKTtcbiAgICBjb25zdCBjb250ZXh0ID0gUGF5UGFsQ29tbWVyY2VHYXRld2F5LmNvbnRleHQ7XG4gICAgaWYgKGNvbnRleHQgPT09ICdtaW5pLWNhcnQnIHx8IGNvbnRleHQgPT09ICdwcm9kdWN0Jykge1xuICAgICAgICBpZiAoUGF5UGFsQ29tbWVyY2VHYXRld2F5Lm1pbmlfY2FydF9idXR0b25zX2VuYWJsZWQgPT09ICcxJykge1xuICAgICAgICAgICAgY29uc3QgbWluaUNhcnRCb290c3RyYXAgPSBuZXcgTWluaUNhcnRCb290c3RhcChcbiAgICAgICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICAgICAgcmVuZGVyZXJcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIG1pbmlDYXJ0Qm9vdHN0cmFwLmluaXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb250ZXh0ID09PSAncHJvZHVjdCcgJiYgUGF5UGFsQ29tbWVyY2VHYXRld2F5LnNpbmdsZV9wcm9kdWN0X2J1dHRvbnNfZW5hYmxlZCA9PT0gJzEnKSB7XG4gICAgICAgIGNvbnN0IHNpbmdsZVByb2R1Y3RCb290c3RyYXAgPSBuZXcgU2luZ2xlUHJvZHVjdEJvb3RzdGFwKFxuICAgICAgICAgICAgUGF5UGFsQ29tbWVyY2VHYXRld2F5LFxuICAgICAgICAgICAgcmVuZGVyZXIsXG4gICAgICAgICAgICBtZXNzYWdlUmVuZGVyZXIsXG4gICAgICAgICk7XG5cbiAgICAgICAgc2luZ2xlUHJvZHVjdEJvb3RzdHJhcC5pbml0KCk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgPT09ICdjYXJ0Jykge1xuICAgICAgICBjb25zdCBjYXJ0Qm9vdHN0cmFwID0gbmV3IENhcnRCb290c3RyYXAoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICByZW5kZXJlcixcbiAgICAgICAgKTtcblxuICAgICAgICBjYXJ0Qm9vdHN0cmFwLmluaXQoKTtcbiAgICB9XG5cbiAgICBpZiAoY29udGV4dCA9PT0gJ2NoZWNrb3V0Jykge1xuICAgICAgICBjb25zdCBjaGVja291dEJvb3RzdGFwID0gbmV3IENoZWNrb3V0Qm9vdHN0YXAoXG4gICAgICAgICAgICBQYXlQYWxDb21tZXJjZUdhdGV3YXksXG4gICAgICAgICAgICByZW5kZXJlcixcbiAgICAgICAgICAgIG1lc3NhZ2VSZW5kZXJlcixcbiAgICAgICAgICAgIHNwaW5uZXJcbiAgICAgICAgKTtcblxuICAgICAgICBjaGVja291dEJvb3RzdGFwLmluaXQoKTtcbiAgICB9XG5cbiAgICBpZiAoY29udGV4dCA9PT0gJ3BheS1ub3cnICkge1xuICAgICAgICBjb25zdCBwYXlOb3dCb290c3RyYXAgPSBuZXcgUGF5Tm93Qm9vdHN0cmFwKFxuICAgICAgICAgICAgUGF5UGFsQ29tbWVyY2VHYXRld2F5LFxuICAgICAgICAgICAgcmVuZGVyZXIsXG4gICAgICAgICAgICBtZXNzYWdlUmVuZGVyZXIsXG4gICAgICAgICAgICBzcGlubmVyXG4gICAgICAgICk7XG4gICAgICAgIHBheU5vd0Jvb3RzdHJhcC5pbml0KCk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgIT09ICdjaGVja291dCcpIHtcbiAgICAgICAgbWVzc2FnZVJlbmRlcmVyLnJlbmRlcigpO1xuICAgIH1cbn07XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFxuICAgICdET01Db250ZW50TG9hZGVkJyxcbiAgICAoKSA9PiB7XG4gICAgICAgIGlmICghdHlwZW9mIChQYXlQYWxDb21tZXJjZUdhdGV3YXkpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdQYXlQYWwgYnV0dG9uIGNvdWxkIG5vdCBiZSBjb25maWd1cmVkLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgUGF5UGFsQ29tbWVyY2VHYXRld2F5LmNvbnRleHQgIT09ICdjaGVja291dCdcbiAgICAgICAgICAgICYmIFBheVBhbENvbW1lcmNlR2F0ZXdheS5kYXRhX2NsaWVudF9pZC51c2VyID09PSAwXG4gICAgICAgICAgICAmJiBQYXlQYWxDb21tZXJjZUdhdGV3YXkuZGF0YV9jbGllbnRfaWQuaGFzX3N1YnNjcmlwdGlvbnNcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTb21ldGltZXMgUGF5UGFsIHNjcmlwdCB0YWtlcyBsb25nIHRpbWUgdG8gbG9hZCxcbiAgICAgICAgLy8gc28gd2UgYWRkaXRpb25hbGx5IGhpZGUgdGhlIHN0YW5kYXJkIG9yZGVyIGJ1dHRvbiBoZXJlIHRvIGF2b2lkIGZhaWxlZCBvcmRlcnMuXG4gICAgICAgIC8vIE5vcm1hbGx5IGl0IGlzIGhpZGRlbiBsYXRlciBhZnRlciB0aGUgc2NyaXB0IGxvYWQuXG4gICAgICAgIGNvbnN0IGhpZGVPcmRlckJ1dHRvbklmUHBjcEdhdGV3YXkgPSAoKSA9PiB7XG4gICAgICAgICAgICAvLyBvbmx5IGluIGNoZWNrb3V0IGFuZCBwYXkgbm93IHBhZ2UsIG90aGVyd2lzZSBpdCBtYXkgYnJlYWsgdGhpbmdzIChlLmcuIHBheW1lbnQgdmlhIHByb2R1Y3QgcGFnZSksXG4gICAgICAgICAgICAvLyBhbmQgYWxzbyB0aGUgbG9hZGluZyBzcGlubmVyIG1heSBsb29rIHdlaXJkIG9uIG90aGVyIHBhZ2VzXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIVsnY2hlY2tvdXQnLCAncGF5LW5vdyddLmluY2x1ZGVzKFBheVBhbENvbW1lcmNlR2F0ZXdheS5jb250ZXh0KVxuICAgICAgICAgICAgICAgIHx8IGlzQ2hhbmdlUGF5bWVudFBhZ2UoKVxuICAgICAgICAgICAgICAgIHx8IChQYXlQYWxDb21tZXJjZUdhdGV3YXkuaXNfZnJlZV90cmlhbF9jYXJ0ICYmIFBheVBhbENvbW1lcmNlR2F0ZXdheS52YXVsdGVkX3BheXBhbF9lbWFpbCAhPT0gJycpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRQYXltZW50TWV0aG9kID0gZ2V0Q3VycmVudFBheW1lbnRNZXRob2QoKTtcbiAgICAgICAgICAgIGNvbnN0IGlzUGF5cGFsID0gY3VycmVudFBheW1lbnRNZXRob2QgPT09IFBheW1lbnRNZXRob2RzLlBBWVBBTDtcbiAgICAgICAgICAgIGNvbnN0IGlzQ2FyZHMgPSBjdXJyZW50UGF5bWVudE1ldGhvZCA9PT0gUGF5bWVudE1ldGhvZHMuQ0FSRFM7XG5cbiAgICAgICAgICAgIHNldFZpc2libGUoT1JERVJfQlVUVE9OX1NFTEVDVE9SLCAhaXNQYXlwYWwgJiYgIWlzQ2FyZHMsIHRydWUpO1xuXG4gICAgICAgICAgICBpZiAoaXNQYXlwYWwpIHtcbiAgICAgICAgICAgICAgICAvLyBzdG9wcGVkIGFmdGVyIHRoZSBmaXJzdCByZW5kZXJpbmcgb2YgdGhlIGJ1dHRvbnMsIGluIG9uSW5pdFxuICAgICAgICAgICAgICAgIGJ1dHRvbnNTcGlubmVyLmJsb2NrKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1dHRvbnNTcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzQ2FyZHMpIHtcbiAgICAgICAgICAgICAgICBjYXJkc1NwaW5uZXIuYmxvY2soKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FyZHNTcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGpRdWVyeShkb2N1bWVudCkub24oJ2hvc3RlZF9maWVsZHNfbG9hZGVkJywgKCkgPT4ge1xuICAgICAgICAgICAgY2FyZHNTcGlubmVyLnVuYmxvY2soKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGJvb3RzdHJhcHBlZCA9IGZhbHNlO1xuXG4gICAgICAgIGhpZGVPcmRlckJ1dHRvbklmUHBjcEdhdGV3YXkoKTtcblxuICAgICAgICBqUXVlcnkoZG9jdW1lbnQuYm9keSkub24oJ3VwZGF0ZWRfY2hlY2tvdXQgcGF5bWVudF9tZXRob2Rfc2VsZWN0ZWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYm9vdHN0cmFwcGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBoaWRlT3JkZXJCdXR0b25JZlBwY3BHYXRld2F5KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICBzY3JpcHQuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgYm9vdHN0cmFwcGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgYm9vdHN0cmFwKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBzY3JpcHQuc2V0QXR0cmlidXRlKCdzcmMnLCBQYXlQYWxDb21tZXJjZUdhdGV3YXkuYnV0dG9uLnVybCk7XG4gICAgICAgIE9iamVjdC5lbnRyaWVzKFBheVBhbENvbW1lcmNlR2F0ZXdheS5zY3JpcHRfYXR0cmlidXRlcykuZm9yRWFjaChcbiAgICAgICAgICAgIChrZXlWYWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIHNjcmlwdC5zZXRBdHRyaWJ1dGUoa2V5VmFsdWVbMF0sIGtleVZhbHVlWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoUGF5UGFsQ29tbWVyY2VHYXRld2F5LmRhdGFfY2xpZW50X2lkLnNldF9hdHRyaWJ1dGUpIHtcbiAgICAgICAgICAgIGRhdGFDbGllbnRJZEF0dHJpYnV0ZUhhbmRsZXIoc2NyaXB0LCBQYXlQYWxDb21tZXJjZUdhdGV3YXkuZGF0YV9jbGllbnRfaWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQoc2NyaXB0KTtcbiAgICB9LFxuKTtcbiJdLCJuYW1lcyI6WyJFcnJvckhhbmRsZXIiLCJjb25zdHJ1Y3RvciIsImdlbmVyaWNFcnJvclRleHQiLCJ3cmFwcGVyIiwiZG9jdW1lbnQiLCJxdWVyeVNlbGVjdG9yIiwibWVzc2FnZXNMaXN0IiwiZ2VuZXJpY0Vycm9yIiwiY2xhc3NMaXN0IiwiY29udGFpbnMiLCJjbGVhciIsIm1lc3NhZ2UiLCJhcHBlbmRQcmVwYXJlZEVycm9yTWVzc2FnZUVsZW1lbnQiLCJlcnJvck1lc3NhZ2VFbGVtZW50IiwicHJlcGFyZU1lc3NhZ2VzTGlzdCIsInJlcGxhY2VXaXRoIiwidGV4dCIsInBlcnNpc3QiLCJTdHJpbmciLCJsZW5ndGgiLCJFcnJvciIsImFkZCIsInJlbW92ZSIsIm1lc3NhZ2VOb2RlIiwicHJlcGFyZU1lc3NhZ2VzTGlzdEl0ZW0iLCJhcHBlbmRDaGlsZCIsImpRdWVyeSIsInNjcm9sbF90b19ub3RpY2VzIiwiY3JlYXRlRWxlbWVudCIsInNldEF0dHJpYnV0ZSIsImxpIiwiaW5uZXJIVE1MIiwic2FuaXRpemUiLCJ0ZXh0YXJlYSIsInZhbHVlIiwicmVwbGFjZSIsIm9uQXBwcm92ZSIsImNvbnRleHQiLCJlcnJvckhhbmRsZXIiLCJkYXRhIiwiYWN0aW9ucyIsImZldGNoIiwiY29uZmlnIiwiYWpheCIsImFwcHJvdmVfb3JkZXIiLCJlbmRwb2ludCIsIm1ldGhvZCIsImJvZHkiLCJKU09OIiwic3RyaW5naWZ5Iiwibm9uY2UiLCJvcmRlcl9pZCIsIm9yZGVySUQiLCJmdW5kaW5nX3NvdXJjZSIsIndpbmRvdyIsInBwY3BGdW5kaW5nU291cmNlIiwidGhlbiIsInJlcyIsImpzb24iLCJzdWNjZXNzIiwicmVzdGFydCIsImNhdGNoIiwiZXJyIiwibG9jYXRpb24iLCJocmVmIiwicmVkaXJlY3QiLCJwYXllckRhdGEiLCJwYXllciIsIlBheVBhbENvbW1lcmNlR2F0ZXdheSIsInBob25lIiwicGhvbmVfdHlwZSIsInBob25lX251bWJlciIsIm5hdGlvbmFsX251bWJlciIsImVtYWlsX2FkZHJlc3MiLCJuYW1lIiwic3VybmFtZSIsImdpdmVuX25hbWUiLCJhZGRyZXNzIiwiY291bnRyeV9jb2RlIiwiYWRkcmVzc19saW5lXzEiLCJhZGRyZXNzX2xpbmVfMiIsImFkbWluX2FyZWFfMSIsImFkbWluX2FyZWFfMiIsInBvc3RhbF9jb2RlIiwiUGF5bWVudE1ldGhvZHMiLCJQQVlQQUwiLCJDQVJEUyIsIk9SREVSX0JVVFRPTl9TRUxFQ1RPUiIsImdldEN1cnJlbnRQYXltZW50TWV0aG9kIiwiZWwiLCJpc1NhdmVkQ2FyZFNlbGVjdGVkIiwic2F2ZWRDYXJkTGlzdCIsIkNhcnRBY3Rpb25IYW5kbGVyIiwiY29uZmlndXJhdGlvbiIsImNyZWF0ZU9yZGVyIiwiYm5Db2RlIiwiYm5fY29kZXMiLCJjcmVhdGVfb3JkZXIiLCJwdXJjaGFzZV91bml0cyIsInBheW1lbnRfbWV0aG9kIiwiYm5fY29kZSIsImNvbnNvbGUiLCJlcnJvciIsImlkIiwib25FcnJvciIsIk1pbmlDYXJ0Qm9vdHN0YXAiLCJnYXRld2F5IiwicmVuZGVyZXIiLCJhY3Rpb25IYW5kbGVyIiwiaW5pdCIsImxhYmVscyIsImdlbmVyaWMiLCJyZW5kZXIiLCJvbiIsInNob3VsZFJlbmRlciIsImJ1dHRvbiIsIm1pbmlfY2FydF93cmFwcGVyIiwiaG9zdGVkX2ZpZWxkcyIsIlByb2R1Y3QiLCJVcGRhdGVDYXJ0IiwidXBkYXRlIiwib25SZXNvbHZlIiwicHJvZHVjdHMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsInJlc3VsdCIsInJlc29sdmVkIiwiQnV0dG9uc1RvZ2dsZUxpc3RlbmVyIiwiZWxlbWVudCIsInNob3dDYWxsYmFjayIsImhpZGVDYWxsYmFjayIsIm9ic2VydmVyIiwiYXR0cmlidXRlcyIsImNhbGxiYWNrIiwiTXV0YXRpb25PYnNlcnZlciIsIm9ic2VydmUiLCJkaXNjb25uZWN0IiwicXVhbnRpdHkiLCJ2YXJpYXRpb25zIiwiU2luZ2xlUHJvZHVjdEFjdGlvbkhhbmRsZXIiLCJ1cGRhdGVDYXJ0Iiwic2hvd0J1dHRvbkNhbGxiYWNrIiwiaGlkZUJ1dHRvbkNhbGxiYWNrIiwiZm9ybUVsZW1lbnQiLCJoYXNWYXJpYXRpb25zIiwiZ2V0UHJvZHVjdHMiLCJpc0dyb3VwZWRQcm9kdWN0IiwicXR5IiwicXVlcnlTZWxlY3RvckFsbCIsImZvckVhY2giLCJlbGVtZW50TmFtZSIsImdldEF0dHJpYnV0ZSIsIm1hdGNoIiwicGFyc2VJbnQiLCJwdXNoIiwicHJvbWlzZSIsIm1hcCIsIlNpbmdsZVByb2R1Y3RCb290c3RhcCIsIm1lc3NhZ2VzIiwiaGFuZGxlQ2hhbmdlIiwiaGlkZUJ1dHRvbnMiLCJhZGRFdmVudExpc3RlbmVyIiwiYmluZCIsInByaWNlQW1vdW50SXNaZXJvIiwicHJpY2VUZXh0IiwiaW5uZXJUZXh0IiwiYW1vdW50IiwicGFyc2VGbG9hdCIsImNoYW5nZV9jYXJ0Iiwic2hvd0J1dHRvbnMiLCJyZW5kZXJXaXRoQW1vdW50IiwiQ2FydEJvb3RzdHJhcCIsInNwaW5uZXIiLCJibG9jayIsInVuYmxvY2siLCJjb2RlIiwiY2xpY2siLCJDaGVja291dEFjdGlvbkhhbmRsZXIiLCJmb3JtU2VsZWN0b3IiLCJmb3JtVmFsdWVzIiwic2VyaWFsaXplIiwiY3JlYXRlYWNjb3VudCIsImlzIiwiZm9ybSIsImRvbVBhcnNlciIsIkRPTVBhcnNlciIsInBhcnNlRnJvbVN0cmluZyIsImRldGFpbHMiLCJkIiwiaXNzdWUiLCJkZXNjcmlwdGlvbiIsImpvaW4iLCJpbnB1dCIsImN1c3RvbV9pZCIsImFwcGVuZCIsIm9uQ2FuY2VsIiwiZ2V0RWxlbWVudCIsInNlbGVjdG9yT3JFbGVtZW50IiwiaXNWaXNpYmxlIiwib2Zmc2V0V2lkdGgiLCJvZmZzZXRIZWlnaHQiLCJnZXRDbGllbnRSZWN0cyIsInNldFZpc2libGUiLCJzaG93IiwiaW1wb3J0YW50IiwiY3VycmVudFZhbHVlIiwic3R5bGUiLCJnZXRQcm9wZXJ0eVZhbHVlIiwic2V0UHJvcGVydHkiLCJyZW1vdmVQcm9wZXJ0eSIsImhpZGUiLCJDaGVja291dEJvb3RzdGFwIiwic3RhbmRhcmRPcmRlckJ1dHRvblNlbGVjdG9yIiwiYnV0dG9uQ2hhbmdlT2JzZXJ2ZXIiLCJ1cGRhdGVVaSIsInZhbCIsImNhbmNlbF93cmFwcGVyIiwiY3VycmVudFBheW1lbnRNZXRob2QiLCJpc1BheXBhbCIsImlzQ2FyZCIsImlzU2F2ZWRDYXJkIiwiaXNOb3RPdXJHYXRld2F5IiwiaXNGcmVlVHJpYWwiLCJpc19mcmVlX3RyaWFsX2NhcnQiLCJoYXNWYXVsdGVkUGF5cGFsIiwidmF1bHRlZF9wYXlwYWxfZW1haWwiLCJkaXNhYmxlQ3JlZGl0Q2FyZEZpZWxkcyIsImVuYWJsZUNyZWRpdENhcmRGaWVsZHMiLCJhZGRDbGFzcyIsImF0dHIiLCJyZW1vdmVDbGFzcyIsImlzQ2hhbmdlUGF5bWVudFBhZ2UiLCJ1cmxQYXJhbXMiLCJVUkxTZWFyY2hQYXJhbXMiLCJzZWFyY2giLCJoYXMiLCJQYXlOb3dCb290c3RyYXAiLCJSZW5kZXJlciIsImNyZWRpdENhcmRSZW5kZXJlciIsImRlZmF1bHRDb25maWciLCJvblNtYXJ0QnV0dG9uQ2xpY2siLCJvblNtYXJ0QnV0dG9uc0luaXQiLCJob3N0ZWRGaWVsZHNXcmFwcGVyIiwiY29udGV4dENvbmZpZyIsInJlbmRlckJ1dHRvbnMiLCJpc0FscmVhZHlSZW5kZXJlZCIsInBheXBhbCIsIkJ1dHRvbnMiLCJtaW5pX2NhcnRfc3R5bGUiLCJvbkNsaWNrIiwib25Jbml0IiwiaGFzQ2hpbGROb2RlcyIsImRvbUVsZW1lbnQiLCJkaXNwbGF5IiwiZGlzYWJsZUZpZWxkcyIsImVuYWJsZUZpZWxkcyIsImRjY0lucHV0RmFjdG9yeSIsIm9yaWdpbmFsIiwic3R5bGVzIiwiZ2V0Q29tcHV0ZWRTdHlsZSIsIm5ld0VsZW1lbnQiLCJPYmplY3QiLCJ2YWx1ZXMiLCJwcm9wIiwiaXNOYU4iLCJDcmVkaXRDYXJkUmVuZGVyZXIiLCJjYXJkVmFsaWQiLCJmb3JtVmFsaWQiLCJjdXJyZW50SG9zdGVkRmllbGRzSW5zdGFuY2UiLCJIb3N0ZWRGaWVsZHMiLCJpc0VsaWdpYmxlIiwid3JhcHBlckVsZW1lbnQiLCJwYXJlbnROb2RlIiwicmVtb3ZlQ2hpbGQiLCJidXR0b25TZWxlY3RvciIsInRlYXJkb3duIiwiZ2F0ZVdheUJveCIsIm9sZERpc3BsYXlTdHlsZSIsImhpZGVEY2NHYXRld2F5IiwiY2FyZE51bWJlckZpZWxkIiwic3R5bGVzUmF3IiwiY2FyZE51bWJlciIsInJlcGxhY2VDaGlsZCIsImNhcmRFeHBpcnlGaWVsZCIsImNhcmRFeHBpcnkiLCJjYXJkQ29kZUZpZWxkIiwiY2FyZENvZGUiLCJmb3JtV3JhcHBlciIsImVuZm9yY2VfdmF1bHQiLCJjaGVja2VkIiwiZmllbGRzIiwibnVtYmVyIiwic2VsZWN0b3IiLCJwbGFjZWhvbGRlciIsImNyZWRpdF9jYXJkX251bWJlciIsImN2diIsImV4cGlyYXRpb25EYXRlIiwibW1feXkiLCJob3N0ZWRGaWVsZHMiLCJkaXNwYXRjaEV2ZW50IiwiQ3VzdG9tRXZlbnQiLCJfc3VibWl0IiwiZXZlbnQiLCJjYXJkcyIsInZhbGlkQ2FyZHMiLCJ2YWxpZF9jYXJkcyIsImluZGV4T2YiLCJ0eXBlIiwia2V5cyIsImV2ZXJ5Iiwia2V5IiwiaXNWYWxpZCIsInByZXZlbnREZWZhdWx0IiwiZmllbGQiLCJhdHRyaWJ1dGUiLCJyZW1vdmVBdHRyaWJ1dGUiLCJzYXZlX2NhcmQiLCJjYW5fc2F2ZV92YXVsdF90b2tlbiIsInZhdWx0IiwiZ2V0RWxlbWVudEJ5SWQiLCJjb250aW5nZW5jeSIsImhvc3RlZEZpZWxkc0RhdGEiLCJjb250aW5nZW5jaWVzIiwiY2FyZGhvbGRlck5hbWUiLCJmaXJzdE5hbWUiLCJsYXN0TmFtZSIsImNhcmRob2xkZXJfbmFtZV9yZXF1aXJlZCIsInN1Ym1pdCIsInBheWxvYWQiLCJvcmRlcklkIiwiY2FyZF9ub3Rfc3VwcG9ydGVkIiwiZmllbGRzX25vdF92YWxpZCIsInN0b3JhZ2VLZXkiLCJ2YWxpZGF0ZVRva2VuIiwidG9rZW4iLCJ1c2VyIiwiY3VycmVudFRpbWUiLCJEYXRlIiwiZ2V0VGltZSIsImlzRXhwaXJlZCIsImV4cGlyYXRpb24iLCJzdG9yZWRUb2tlbkZvclVzZXIiLCJwYXJzZSIsInNlc3Npb25TdG9yYWdlIiwiZ2V0SXRlbSIsInN0b3JlVG9rZW4iLCJzZXRJdGVtIiwiZGF0YUNsaWVudElkQXR0cmlidXRlSGFuZGxlciIsInNjcmlwdCIsIk1lc3NhZ2VSZW5kZXJlciIsIk1lc3NhZ2VzIiwicGxhY2VtZW50IiwibmV3V3JhcHBlciIsInNpYmxpbmciLCJuZXh0U2libGluZyIsInBhcmVudEVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJTcGlubmVyIiwidGFyZ2V0Iiwic2V0VGFyZ2V0Iiwib3ZlcmxheUNTUyIsImJhY2tncm91bmQiLCJvcGFjaXR5IiwiRnJlZVRyaWFsSGFuZGxlciIsImhhbmRsZSIsInZhdWx0X3BheXBhbCIsInJldHVybl91cmwiLCJhcHByb3ZlX2xpbmsiLCJidXR0b25zU3Bpbm5lciIsImNhcmRzU3Bpbm5lciIsImJvb3RzdHJhcCIsImZyZWVUcmlhbEhhbmRsZXIiLCJmdW5kaW5nU291cmNlIiwiaW5zZXJ0QWRqYWNlbnRIVE1MIiwibWVzc2FnZVJlbmRlcmVyIiwibWluaV9jYXJ0X2J1dHRvbnNfZW5hYmxlZCIsIm1pbmlDYXJ0Qm9vdHN0cmFwIiwic2luZ2xlX3Byb2R1Y3RfYnV0dG9uc19lbmFibGVkIiwic2luZ2xlUHJvZHVjdEJvb3RzdHJhcCIsImNhcnRCb290c3RyYXAiLCJjaGVja291dEJvb3RzdGFwIiwicGF5Tm93Qm9vdHN0cmFwIiwiZGF0YV9jbGllbnRfaWQiLCJoYXNfc3Vic2NyaXB0aW9ucyIsImhpZGVPcmRlckJ1dHRvbklmUHBjcEdhdGV3YXkiLCJpbmNsdWRlcyIsImlzQ2FyZHMiLCJib290c3RyYXBwZWQiLCJ1cmwiLCJlbnRyaWVzIiwic2NyaXB0X2F0dHJpYnV0ZXMiLCJrZXlWYWx1ZSIsInNldF9hdHRyaWJ1dGUiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///536\n")}},__webpack_exports__={};__webpack_modules__[536]()})();
|
modules/ppcp-button/resources/js/button.js
CHANGED
@@ -16,15 +16,35 @@ import {
|
|
16 |
} from "./modules/Helper/CheckoutMethodState";
|
17 |
import {hide, setVisible} from "./modules/Helper/Hiding";
|
18 |
import {isChangePaymentPage} from "./modules/Helper/Subscriptions";
|
|
|
19 |
|
20 |
const buttonsSpinner = new Spinner('.ppc-button-wrapper');
|
|
|
21 |
|
22 |
const bootstrap = () => {
|
23 |
const errorHandler = new ErrorHandler(PayPalCommerceGateway.labels.error.generic);
|
24 |
const spinner = new Spinner();
|
25 |
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);
|
26 |
-
|
|
|
|
|
|
|
27 |
window.ppcpFundingSource = data.fundingSource;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
};
|
29 |
const onSmartButtonsInit = () => {
|
30 |
buttonsSpinner.unblock();
|
@@ -112,14 +132,16 @@ document.addEventListener(
|
|
112 |
if (
|
113 |
!['checkout', 'pay-now'].includes(PayPalCommerceGateway.context)
|
114 |
|| isChangePaymentPage()
|
|
|
115 |
) {
|
116 |
return;
|
117 |
}
|
118 |
|
119 |
const currentPaymentMethod = getCurrentPaymentMethod();
|
120 |
const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;
|
|
|
121 |
|
122 |
-
setVisible(ORDER_BUTTON_SELECTOR, !isPaypal, true);
|
123 |
|
124 |
if (isPaypal) {
|
125 |
// stopped after the first rendering of the buttons, in onInit
|
@@ -127,8 +149,18 @@ document.addEventListener(
|
|
127 |
} else {
|
128 |
buttonsSpinner.unblock();
|
129 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
130 |
}
|
131 |
|
|
|
|
|
|
|
|
|
132 |
let bootstrapped = false;
|
133 |
|
134 |
hideOrderButtonIfPpcpGateway();
|
16 |
} from "./modules/Helper/CheckoutMethodState";
|
17 |
import {hide, setVisible} from "./modules/Helper/Hiding";
|
18 |
import {isChangePaymentPage} from "./modules/Helper/Subscriptions";
|
19 |
+
import FreeTrialHandler from "./modules/ActionHandler/FreeTrialHandler";
|
20 |
|
21 |
const buttonsSpinner = new Spinner('.ppc-button-wrapper');
|
22 |
+
const cardsSpinner = new Spinner('#ppcp-hosted-fields');
|
23 |
|
24 |
const bootstrap = () => {
|
25 |
const errorHandler = new ErrorHandler(PayPalCommerceGateway.labels.error.generic);
|
26 |
const spinner = new Spinner();
|
27 |
const creditCardRenderer = new CreditCardRenderer(PayPalCommerceGateway, errorHandler, spinner);
|
28 |
+
|
29 |
+
const freeTrialHandler = new FreeTrialHandler(PayPalCommerceGateway, spinner, errorHandler);
|
30 |
+
|
31 |
+
const onSmartButtonClick = (data, actions) => {
|
32 |
window.ppcpFundingSource = data.fundingSource;
|
33 |
+
|
34 |
+
const form = document.querySelector('form.woocommerce-checkout');
|
35 |
+
if (form) {
|
36 |
+
jQuery('#ppcp-funding-source-form-input').remove();
|
37 |
+
form.insertAdjacentHTML(
|
38 |
+
'beforeend',
|
39 |
+
`<input type="hidden" name="ppcp-funding-source" value="${data.fundingSource}" id="ppcp-funding-source-form-input">`
|
40 |
+
)
|
41 |
+
}
|
42 |
+
|
43 |
+
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
44 |
+
if (isFreeTrial && data.fundingSource !== 'card') {
|
45 |
+
freeTrialHandler.handle();
|
46 |
+
return actions.reject();
|
47 |
+
}
|
48 |
};
|
49 |
const onSmartButtonsInit = () => {
|
50 |
buttonsSpinner.unblock();
|
132 |
if (
|
133 |
!['checkout', 'pay-now'].includes(PayPalCommerceGateway.context)
|
134 |
|| isChangePaymentPage()
|
135 |
+
|| (PayPalCommerceGateway.is_free_trial_cart && PayPalCommerceGateway.vaulted_paypal_email !== '')
|
136 |
) {
|
137 |
return;
|
138 |
}
|
139 |
|
140 |
const currentPaymentMethod = getCurrentPaymentMethod();
|
141 |
const isPaypal = currentPaymentMethod === PaymentMethods.PAYPAL;
|
142 |
+
const isCards = currentPaymentMethod === PaymentMethods.CARDS;
|
143 |
|
144 |
+
setVisible(ORDER_BUTTON_SELECTOR, !isPaypal && !isCards, true);
|
145 |
|
146 |
if (isPaypal) {
|
147 |
// stopped after the first rendering of the buttons, in onInit
|
149 |
} else {
|
150 |
buttonsSpinner.unblock();
|
151 |
}
|
152 |
+
|
153 |
+
if (isCards) {
|
154 |
+
cardsSpinner.block();
|
155 |
+
} else {
|
156 |
+
cardsSpinner.unblock();
|
157 |
+
}
|
158 |
}
|
159 |
|
160 |
+
jQuery(document).on('hosted_fields_loaded', () => {
|
161 |
+
cardsSpinner.unblock();
|
162 |
+
});
|
163 |
+
|
164 |
let bootstrapped = false;
|
165 |
|
166 |
hideOrderButtonIfPpcpGateway();
|
modules/ppcp-button/resources/js/modules/ActionHandler/CartActionHandler.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import onApprove from '../OnApproveHandler/onApproveForContinue.js';
|
2 |
import {payerData} from "../Helper/PayerData";
|
|
|
3 |
|
4 |
class CartActionHandler {
|
5 |
|
@@ -18,6 +19,8 @@ class CartActionHandler {
|
|
18 |
body: JSON.stringify({
|
19 |
nonce: this.config.ajax.create_order.nonce,
|
20 |
purchase_units: [],
|
|
|
|
|
21 |
bn_code:bnCode,
|
22 |
payer,
|
23 |
context:this.config.context
|
1 |
import onApprove from '../OnApproveHandler/onApproveForContinue.js';
|
2 |
import {payerData} from "../Helper/PayerData";
|
3 |
+
import {PaymentMethods} from "../Helper/CheckoutMethodState";
|
4 |
|
5 |
class CartActionHandler {
|
6 |
|
19 |
body: JSON.stringify({
|
20 |
nonce: this.config.ajax.create_order.nonce,
|
21 |
purchase_units: [],
|
22 |
+
payment_method: PaymentMethods.PAYPAL,
|
23 |
+
funding_source: window.ppcpFundingSource,
|
24 |
bn_code:bnCode,
|
25 |
payer,
|
26 |
context:this.config.context
|
modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import onApprove from '../OnApproveHandler/onApproveForPayNow.js';
|
2 |
import {payerData} from "../Helper/PayerData";
|
|
|
3 |
|
4 |
class CheckoutActionHandler {
|
5 |
|
@@ -31,6 +32,8 @@ class CheckoutActionHandler {
|
|
31 |
bn_code:bnCode,
|
32 |
context:this.config.context,
|
33 |
order_id:this.config.order_id,
|
|
|
|
|
34 |
form:formValues,
|
35 |
createaccount: createaccount
|
36 |
})
|
1 |
import onApprove from '../OnApproveHandler/onApproveForPayNow.js';
|
2 |
import {payerData} from "../Helper/PayerData";
|
3 |
+
import {getCurrentPaymentMethod} from "../Helper/CheckoutMethodState";
|
4 |
|
5 |
class CheckoutActionHandler {
|
6 |
|
32 |
bn_code:bnCode,
|
33 |
context:this.config.context,
|
34 |
order_id:this.config.order_id,
|
35 |
+
payment_method: getCurrentPaymentMethod(),
|
36 |
+
funding_source: window.ppcpFundingSource,
|
37 |
form:formValues,
|
38 |
createaccount: createaccount
|
39 |
})
|
modules/ppcp-button/resources/js/modules/ActionHandler/FreeTrialHandler.js
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {PaymentMethods} from "../Helper/CheckoutMethodState";
|
2 |
+
import errorHandler from "../ErrorHandler";
|
3 |
+
|
4 |
+
class FreeTrialHandler {
|
5 |
+
constructor(
|
6 |
+
config,
|
7 |
+
spinner,
|
8 |
+
errorHandler
|
9 |
+
) {
|
10 |
+
this.config = config;
|
11 |
+
this.spinner = spinner;
|
12 |
+
this.errorHandler = errorHandler;
|
13 |
+
}
|
14 |
+
|
15 |
+
handle()
|
16 |
+
{
|
17 |
+
this.spinner.block();
|
18 |
+
|
19 |
+
fetch(this.config.ajax.vault_paypal.endpoint, {
|
20 |
+
method: 'POST',
|
21 |
+
body: JSON.stringify({
|
22 |
+
nonce: this.config.ajax.vault_paypal.nonce,
|
23 |
+
return_url: location.href
|
24 |
+
}),
|
25 |
+
}).then(res => {
|
26 |
+
return res.json();
|
27 |
+
}).then(data => {
|
28 |
+
if (!data.success) {
|
29 |
+
this.spinner.unblock();
|
30 |
+
console.error(data);
|
31 |
+
this.errorHandler.message(data.data.message);
|
32 |
+
throw Error(data.data.message);
|
33 |
+
}
|
34 |
+
|
35 |
+
location.href = data.data.approve_link;
|
36 |
+
}).catch(error => {
|
37 |
+
this.spinner.unblock();
|
38 |
+
console.error(error);
|
39 |
+
this.errorHandler.genericError();
|
40 |
+
});
|
41 |
+
}
|
42 |
+
}
|
43 |
+
export default FreeTrialHandler;
|
modules/ppcp-button/resources/js/modules/ActionHandler/SingleProductActionHandler.js
CHANGED
@@ -2,6 +2,7 @@ import ButtonsToggleListener from '../Helper/ButtonsToggleListener';
|
|
2 |
import Product from '../Entity/Product';
|
3 |
import onApprove from '../OnApproveHandler/onApproveForContinue';
|
4 |
import {payerData} from "../Helper/PayerData";
|
|
|
5 |
|
6 |
class SingleProductActionHandler {
|
7 |
|
@@ -84,6 +85,8 @@ class SingleProductActionHandler {
|
|
84 |
purchase_units,
|
85 |
payer,
|
86 |
bn_code:bnCode,
|
|
|
|
|
87 |
context:this.config.context
|
88 |
})
|
89 |
}).then(function (res) {
|
2 |
import Product from '../Entity/Product';
|
3 |
import onApprove from '../OnApproveHandler/onApproveForContinue';
|
4 |
import {payerData} from "../Helper/PayerData";
|
5 |
+
import {PaymentMethods} from "../Helper/CheckoutMethodState";
|
6 |
|
7 |
class SingleProductActionHandler {
|
8 |
|
85 |
purchase_units,
|
86 |
payer,
|
87 |
bn_code:bnCode,
|
88 |
+
payment_method: PaymentMethods.PAYPAL,
|
89 |
+
funding_source: window.ppcpFundingSource,
|
90 |
context:this.config.context
|
91 |
})
|
92 |
}).then(function (res) {
|
modules/ppcp-button/resources/js/modules/ContextBootstrap/CheckoutBootstap.js
CHANGED
@@ -86,13 +86,16 @@ class CheckoutBootstap {
|
|
86 |
const isCard = currentPaymentMethod === PaymentMethods.CARDS;
|
87 |
const isSavedCard = isCard && isSavedCardSelected();
|
88 |
const isNotOurGateway = !isPaypal && !isCard;
|
|
|
|
|
89 |
|
90 |
-
setVisible(this.standardOrderButtonSelector, isNotOurGateway || isSavedCard, true);
|
91 |
-
setVisible(
|
92 |
-
setVisible(this.gateway.
|
|
|
93 |
setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);
|
94 |
|
95 |
-
if (isPaypal) {
|
96 |
this.messages.render();
|
97 |
}
|
98 |
|
86 |
const isCard = currentPaymentMethod === PaymentMethods.CARDS;
|
87 |
const isSavedCard = isCard && isSavedCardSelected();
|
88 |
const isNotOurGateway = !isPaypal && !isCard;
|
89 |
+
const isFreeTrial = PayPalCommerceGateway.is_free_trial_cart;
|
90 |
+
const hasVaultedPaypal = PayPalCommerceGateway.vaulted_paypal_email !== '';
|
91 |
|
92 |
+
setVisible(this.standardOrderButtonSelector, (isPaypal && isFreeTrial && hasVaultedPaypal) || isNotOurGateway || isSavedCard, true);
|
93 |
+
setVisible('.ppcp-vaulted-paypal-details', isPaypal);
|
94 |
+
setVisible(this.gateway.button.wrapper, isPaypal && !(isFreeTrial && hasVaultedPaypal));
|
95 |
+
setVisible(this.gateway.messages.wrapper, isPaypal && !isFreeTrial);
|
96 |
setVisible(this.gateway.hosted_fields.wrapper, isCard && !isSavedCard);
|
97 |
|
98 |
+
if (isPaypal && !isFreeTrial) {
|
99 |
this.messages.render();
|
100 |
}
|
101 |
|
modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import dccInputFactory from "../Helper/DccInputFactory";
|
|
|
2 |
|
3 |
class CreditCardRenderer {
|
4 |
|
@@ -32,6 +33,8 @@ class CreditCardRenderer {
|
|
32 |
return;
|
33 |
}
|
34 |
|
|
|
|
|
35 |
if (this.currentHostedFieldsInstance) {
|
36 |
this.currentHostedFieldsInstance.teardown()
|
37 |
.catch(err => console.error(`Hosted fields teardown error: ${err}`));
|
@@ -121,8 +124,10 @@ class CreditCardRenderer {
|
|
121 |
|
122 |
});
|
123 |
|
|
|
|
|
124 |
if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) {
|
125 |
-
document.querySelector(
|
126 |
'click',
|
127 |
event => {
|
128 |
event.preventDefault();
|
1 |
import dccInputFactory from "../Helper/DccInputFactory";
|
2 |
+
import {show} from "../Helper/Hiding";
|
3 |
|
4 |
class CreditCardRenderer {
|
5 |
|
33 |
return;
|
34 |
}
|
35 |
|
36 |
+
const buttonSelector = wrapper + ' button';
|
37 |
+
|
38 |
if (this.currentHostedFieldsInstance) {
|
39 |
this.currentHostedFieldsInstance.teardown()
|
40 |
.catch(err => console.error(`Hosted fields teardown error: ${err}`));
|
124 |
|
125 |
});
|
126 |
|
127 |
+
show(buttonSelector);
|
128 |
+
|
129 |
if (document.querySelector(wrapper).getAttribute('data-ppcp-subscribed') !== true) {
|
130 |
+
document.querySelector(buttonSelector).addEventListener(
|
131 |
'click',
|
132 |
event => {
|
133 |
event.preventDefault();
|
modules/ppcp-button/services.php
CHANGED
@@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
|
18 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
19 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
20 |
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
|
|
21 |
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
22 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
23 |
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
@@ -85,7 +86,9 @@ return array(
|
|
85 |
$environment,
|
86 |
$payment_token_repository,
|
87 |
$settings_status,
|
88 |
-
$currency
|
|
|
|
|
89 |
);
|
90 |
},
|
91 |
'button.url' => static function ( ContainerInterface $container ): string {
|
@@ -169,6 +172,13 @@ return array(
|
|
169 |
$logger
|
170 |
);
|
171 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
'button.helper.three-d-secure' => static function ( ContainerInterface $container ): ThreeDSecure {
|
173 |
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
174 |
return new ThreeDSecure( $logger );
|
18 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
19 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
20 |
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
21 |
+
use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint;
|
22 |
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
23 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
24 |
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
86 |
$environment,
|
87 |
$payment_token_repository,
|
88 |
$settings_status,
|
89 |
+
$currency,
|
90 |
+
$container->get( 'wcgateway.all-funding-sources' ),
|
91 |
+
$container->get( 'woocommerce.logger.woocommerce' )
|
92 |
);
|
93 |
},
|
94 |
'button.url' => static function ( ContainerInterface $container ): string {
|
172 |
$logger
|
173 |
);
|
174 |
},
|
175 |
+
'button.endpoint.vault-paypal' => static function( ContainerInterface $container ) : StartPayPalVaultingEndpoint {
|
176 |
+
return new StartPayPalVaultingEndpoint(
|
177 |
+
$container->get( 'button.request-data' ),
|
178 |
+
$container->get( 'api.endpoint.payment-token' ),
|
179 |
+
$container->get( 'woocommerce.logger.woocommerce' )
|
180 |
+
);
|
181 |
+
},
|
182 |
'button.helper.three-d-secure' => static function ( ContainerInterface $container ): ThreeDSecure {
|
183 |
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
184 |
return new ThreeDSecure( $logger );
|
modules/ppcp-button/src/Assets/SmartButton.php
CHANGED
@@ -9,6 +9,9 @@ declare(strict_types=1);
|
|
9 |
|
10 |
namespace WooCommerce\PayPalCommerce\Button\Assets;
|
11 |
|
|
|
|
|
|
|
12 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
13 |
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
14 |
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
@@ -16,9 +19,11 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
|
16 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
17 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
18 |
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
|
|
19 |
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
20 |
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
21 |
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
|
|
22 |
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
23 |
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
24 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
@@ -30,6 +35,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|
30 |
*/
|
31 |
class SmartButton implements SmartButtonInterface {
|
32 |
|
|
|
|
|
33 |
/**
|
34 |
* The Settings status helper.
|
35 |
*
|
@@ -128,6 +135,27 @@ class SmartButton implements SmartButtonInterface {
|
|
128 |
*/
|
129 |
private $currency;
|
130 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
/**
|
132 |
* SmartButton constructor.
|
133 |
*
|
@@ -145,6 +173,8 @@ class SmartButton implements SmartButtonInterface {
|
|
145 |
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
146 |
* @param SettingsStatus $settings_status The Settings status helper.
|
147 |
* @param string $currency 3-letter currency code of the shop.
|
|
|
|
|
148 |
*/
|
149 |
public function __construct(
|
150 |
string $module_url,
|
@@ -160,7 +190,9 @@ class SmartButton implements SmartButtonInterface {
|
|
160 |
Environment $environment,
|
161 |
PaymentTokenRepository $payment_token_repository,
|
162 |
SettingsStatus $settings_status,
|
163 |
-
string $currency
|
|
|
|
|
164 |
) {
|
165 |
|
166 |
$this->module_url = $module_url;
|
@@ -177,6 +209,8 @@ class SmartButton implements SmartButtonInterface {
|
|
177 |
$this->payment_token_repository = $payment_token_repository;
|
178 |
$this->settings_status = $settings_status;
|
179 |
$this->currency = $currency;
|
|
|
|
|
180 |
}
|
181 |
|
182 |
/**
|
@@ -262,6 +296,38 @@ class SmartButton implements SmartButtonInterface {
|
|
262 |
2
|
263 |
);
|
264 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
265 |
return true;
|
266 |
}
|
267 |
|
@@ -341,6 +407,9 @@ class SmartButton implements SmartButtonInterface {
|
|
341 |
if (
|
342 |
( is_product() || wc_post_content_has_shortcode( 'product_page' ) )
|
343 |
&& ! $not_enabled_on_product_page
|
|
|
|
|
|
|
344 |
) {
|
345 |
add_action(
|
346 |
$this->single_product_renderer_hook(),
|
@@ -358,11 +427,12 @@ class SmartButton implements SmartButtonInterface {
|
|
358 |
! $this->settings->get( 'button_mini_cart_enabled' );
|
359 |
if (
|
360 |
! $not_enabled_on_minicart
|
|
|
361 |
) {
|
362 |
add_action(
|
363 |
$this->mini_cart_button_renderer_hook(),
|
364 |
function () {
|
365 |
-
if ( $this->is_cart_price_total_zero() ) {
|
366 |
return;
|
367 |
}
|
368 |
|
@@ -375,7 +445,7 @@ class SmartButton implements SmartButtonInterface {
|
|
375 |
);
|
376 |
}
|
377 |
|
378 |
-
if ( $this->is_cart_price_total_zero() ) {
|
379 |
return false;
|
380 |
}
|
381 |
|
@@ -384,6 +454,7 @@ class SmartButton implements SmartButtonInterface {
|
|
384 |
if (
|
385 |
is_cart()
|
386 |
&& ! $not_enabled_on_cart
|
|
|
387 |
) {
|
388 |
add_action(
|
389 |
$this->proceed_to_checkout_button_renderer_hook(),
|
@@ -601,8 +672,10 @@ class SmartButton implements SmartButtonInterface {
|
|
601 |
|
602 |
printf(
|
603 |
'<div id="%1$s" style="display:none;">
|
604 |
-
|
605 |
-
|
|
|
|
|
606 |
esc_attr( $id ),
|
607 |
esc_html( $label )
|
608 |
);
|
@@ -671,6 +744,8 @@ class SmartButton implements SmartButtonInterface {
|
|
671 |
private function localize_script(): array {
|
672 |
global $wp;
|
673 |
|
|
|
|
|
674 |
$this->request_data->enqueue_nonce_fix();
|
675 |
$localize = array(
|
676 |
'script_attributes' => $this->attributes(),
|
@@ -696,9 +771,15 @@ class SmartButton implements SmartButtonInterface {
|
|
696 |
'endpoint' => \WC_AJAX::get_endpoint( ApproveOrderEndpoint::ENDPOINT ),
|
697 |
'nonce' => wp_create_nonce( ApproveOrderEndpoint::nonce() ),
|
698 |
),
|
|
|
|
|
|
|
|
|
699 |
),
|
700 |
'enforce_vault' => $this->has_subscriptions(),
|
701 |
'can_save_vault_token' => $this->can_save_vault_token(),
|
|
|
|
|
702 |
'bn_codes' => $this->bn_codes(),
|
703 |
'payer' => $this->payerData(),
|
704 |
'button' => array(
|
@@ -817,13 +898,24 @@ class SmartButton implements SmartButtonInterface {
|
|
817 |
if ( ! is_checkout() ) {
|
818 |
$disable_funding[] = 'card';
|
819 |
}
|
820 |
-
|
|
|
|
|
|
|
821 |
$key = array_search( 'card', $disable_funding, true );
|
822 |
if ( false !== $key ) {
|
823 |
unset( $disable_funding[ $key ] );
|
824 |
}
|
825 |
}
|
826 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
827 |
if ( count( $disable_funding ) > 0 ) {
|
828 |
$params['disable-funding'] = implode( ',', array_unique( $disable_funding ) );
|
829 |
}
|
@@ -832,6 +924,11 @@ class SmartButton implements SmartButtonInterface {
|
|
832 |
if ( $this->settings_status->pay_later_messaging_is_enabled() || ! in_array( 'credit', $disable_funding, true ) ) {
|
833 |
$enable_funding[] = 'paylater';
|
834 |
}
|
|
|
|
|
|
|
|
|
|
|
835 |
if ( count( $enable_funding ) > 0 ) {
|
836 |
$params['enable-funding'] = implode( ',', array_unique( $enable_funding ) );
|
837 |
}
|
@@ -890,7 +987,10 @@ class SmartButton implements SmartButtonInterface {
|
|
890 |
if ( $this->load_button_component() ) {
|
891 |
$components[] = 'buttons';
|
892 |
}
|
893 |
-
if (
|
|
|
|
|
|
|
894 |
$components[] = 'messages';
|
895 |
}
|
896 |
if ( $this->dcc_is_enabled() ) {
|
@@ -1126,4 +1226,37 @@ class SmartButton implements SmartButtonInterface {
|
|
1126 |
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
1127 |
return WC()->cart->get_cart_contents_total() == 0;
|
1128 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1129 |
}
|
9 |
|
10 |
namespace WooCommerce\PayPalCommerce\Button\Assets;
|
11 |
|
12 |
+
use Exception;
|
13 |
+
use Psr\Log\LoggerInterface;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
17 |
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
19 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
20 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
21 |
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
22 |
+
use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint;
|
23 |
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
24 |
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
25 |
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
26 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
27 |
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
28 |
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
|
29 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
35 |
*/
|
36 |
class SmartButton implements SmartButtonInterface {
|
37 |
|
38 |
+
use FreeTrialHandlerTrait;
|
39 |
+
|
40 |
/**
|
41 |
* The Settings status helper.
|
42 |
*
|
135 |
*/
|
136 |
private $currency;
|
137 |
|
138 |
+
/**
|
139 |
+
* All existing funding sources.
|
140 |
+
*
|
141 |
+
* @var array
|
142 |
+
*/
|
143 |
+
private $all_funding_sources;
|
144 |
+
|
145 |
+
/**
|
146 |
+
* The logger.
|
147 |
+
*
|
148 |
+
* @var LoggerInterface
|
149 |
+
*/
|
150 |
+
private $logger;
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Cached payment tokens.
|
154 |
+
*
|
155 |
+
* @var PaymentToken[]|null
|
156 |
+
*/
|
157 |
+
private $payment_tokens = null;
|
158 |
+
|
159 |
/**
|
160 |
* SmartButton constructor.
|
161 |
*
|
173 |
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
174 |
* @param SettingsStatus $settings_status The Settings status helper.
|
175 |
* @param string $currency 3-letter currency code of the shop.
|
176 |
+
* @param array $all_funding_sources All existing funding sources.
|
177 |
+
* @param LoggerInterface $logger The logger.
|
178 |
*/
|
179 |
public function __construct(
|
180 |
string $module_url,
|
190 |
Environment $environment,
|
191 |
PaymentTokenRepository $payment_token_repository,
|
192 |
SettingsStatus $settings_status,
|
193 |
+
string $currency,
|
194 |
+
array $all_funding_sources,
|
195 |
+
LoggerInterface $logger
|
196 |
) {
|
197 |
|
198 |
$this->module_url = $module_url;
|
209 |
$this->payment_token_repository = $payment_token_repository;
|
210 |
$this->settings_status = $settings_status;
|
211 |
$this->currency = $currency;
|
212 |
+
$this->all_funding_sources = $all_funding_sources;
|
213 |
+
$this->logger = $logger;
|
214 |
}
|
215 |
|
216 |
/**
|
296 |
2
|
297 |
);
|
298 |
}
|
299 |
+
|
300 |
+
if ( $this->is_free_trial_cart() ) {
|
301 |
+
add_action(
|
302 |
+
'woocommerce_review_order_after_submit',
|
303 |
+
function () {
|
304 |
+
$vaulted_email = $this->get_vaulted_paypal_email();
|
305 |
+
if ( ! $vaulted_email ) {
|
306 |
+
return;
|
307 |
+
}
|
308 |
+
|
309 |
+
?>
|
310 |
+
<div class="ppcp-vaulted-paypal-details">
|
311 |
+
<?php
|
312 |
+
echo wp_kses_post(
|
313 |
+
sprintf(
|
314 |
+
// translators: %1$s - email, %2$s, %3$s - HTML tags for a link.
|
315 |
+
esc_html__(
|
316 |
+
'Using %2$s%1$s%3$s PayPal.',
|
317 |
+
'woocommerce-paypal-payments'
|
318 |
+
),
|
319 |
+
$vaulted_email,
|
320 |
+
'<b>',
|
321 |
+
'</b>'
|
322 |
+
)
|
323 |
+
);
|
324 |
+
?>
|
325 |
+
</div>
|
326 |
+
<?php
|
327 |
+
}
|
328 |
+
);
|
329 |
+
}
|
330 |
+
|
331 |
return true;
|
332 |
}
|
333 |
|
407 |
if (
|
408 |
( is_product() || wc_post_content_has_shortcode( 'product_page' ) )
|
409 |
&& ! $not_enabled_on_product_page
|
410 |
+
// TODO: it seems like there is no easy way to properly handle vaulted PayPal free trial,
|
411 |
+
// so disable the buttons for now everywhere except checkout for free trial.
|
412 |
+
&& ! $this->is_free_trial_product()
|
413 |
) {
|
414 |
add_action(
|
415 |
$this->single_product_renderer_hook(),
|
427 |
! $this->settings->get( 'button_mini_cart_enabled' );
|
428 |
if (
|
429 |
! $not_enabled_on_minicart
|
430 |
+
&& ! $this->is_free_trial_cart()
|
431 |
) {
|
432 |
add_action(
|
433 |
$this->mini_cart_button_renderer_hook(),
|
434 |
function () {
|
435 |
+
if ( $this->is_cart_price_total_zero() || $this->is_free_trial_cart() ) {
|
436 |
return;
|
437 |
}
|
438 |
|
445 |
);
|
446 |
}
|
447 |
|
448 |
+
if ( $this->is_cart_price_total_zero() && ! $this->is_free_trial_cart() ) {
|
449 |
return false;
|
450 |
}
|
451 |
|
454 |
if (
|
455 |
is_cart()
|
456 |
&& ! $not_enabled_on_cart
|
457 |
+
&& ! $this->is_free_trial_cart()
|
458 |
) {
|
459 |
add_action(
|
460 |
$this->proceed_to_checkout_button_renderer_hook(),
|
672 |
|
673 |
printf(
|
674 |
'<div id="%1$s" style="display:none;">
|
675 |
+
<button type="submit" class="button alt ppcp-dcc-order-button" style="display: none;">%2$s</button>
|
676 |
+
</div>
|
677 |
+
<div id="payments-sdk__contingency-lightbox"></div>
|
678 |
+
<style id="ppcp-hide-dcc">.payment_method_ppcp-credit-card-gateway {display:none;}</style>',
|
679 |
esc_attr( $id ),
|
680 |
esc_html( $label )
|
681 |
);
|
744 |
private function localize_script(): array {
|
745 |
global $wp;
|
746 |
|
747 |
+
$is_free_trial_cart = $this->is_free_trial_cart();
|
748 |
+
|
749 |
$this->request_data->enqueue_nonce_fix();
|
750 |
$localize = array(
|
751 |
'script_attributes' => $this->attributes(),
|
771 |
'endpoint' => \WC_AJAX::get_endpoint( ApproveOrderEndpoint::ENDPOINT ),
|
772 |
'nonce' => wp_create_nonce( ApproveOrderEndpoint::nonce() ),
|
773 |
),
|
774 |
+
'vault_paypal' => array(
|
775 |
+
'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ),
|
776 |
+
'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ),
|
777 |
+
),
|
778 |
),
|
779 |
'enforce_vault' => $this->has_subscriptions(),
|
780 |
'can_save_vault_token' => $this->can_save_vault_token(),
|
781 |
+
'is_free_trial_cart' => $is_free_trial_cart,
|
782 |
+
'vaulted_paypal_email' => ( is_checkout() && $is_free_trial_cart ) ? $this->get_vaulted_paypal_email() : '',
|
783 |
'bn_codes' => $this->bn_codes(),
|
784 |
'payer' => $this->payerData(),
|
785 |
'button' => array(
|
898 |
if ( ! is_checkout() ) {
|
899 |
$disable_funding[] = 'card';
|
900 |
}
|
901 |
+
|
902 |
+
$is_dcc_enabled = $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' );
|
903 |
+
|
904 |
+
if ( is_checkout() && $is_dcc_enabled ) {
|
905 |
$key = array_search( 'card', $disable_funding, true );
|
906 |
if ( false !== $key ) {
|
907 |
unset( $disable_funding[ $key ] );
|
908 |
}
|
909 |
}
|
910 |
|
911 |
+
if ( $this->is_free_trial_cart() ) {
|
912 |
+
$all_sources = $this->all_funding_sources;
|
913 |
+
if ( $is_dcc_enabled ) {
|
914 |
+
$all_sources = array_keys( array_diff_key( $all_sources, array( 'card' => '' ) ) );
|
915 |
+
}
|
916 |
+
$disable_funding = $all_sources;
|
917 |
+
}
|
918 |
+
|
919 |
if ( count( $disable_funding ) > 0 ) {
|
920 |
$params['disable-funding'] = implode( ',', array_unique( $disable_funding ) );
|
921 |
}
|
924 |
if ( $this->settings_status->pay_later_messaging_is_enabled() || ! in_array( 'credit', $disable_funding, true ) ) {
|
925 |
$enable_funding[] = 'paylater';
|
926 |
}
|
927 |
+
|
928 |
+
if ( $this->is_free_trial_cart() ) {
|
929 |
+
$enable_funding = array();
|
930 |
+
}
|
931 |
+
|
932 |
if ( count( $enable_funding ) > 0 ) {
|
933 |
$params['enable-funding'] = implode( ',', array_unique( $enable_funding ) );
|
934 |
}
|
987 |
if ( $this->load_button_component() ) {
|
988 |
$components[] = 'buttons';
|
989 |
}
|
990 |
+
if (
|
991 |
+
$this->messages_apply->for_country()
|
992 |
+
&& ! $this->is_free_trial_cart()
|
993 |
+
) {
|
994 |
$components[] = 'messages';
|
995 |
}
|
996 |
if ( $this->dcc_is_enabled() ) {
|
1226 |
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
|
1227 |
return WC()->cart->get_cart_contents_total() == 0;
|
1228 |
}
|
1229 |
+
|
1230 |
+
/**
|
1231 |
+
* Retrieves all payment tokens for the user, via API or cached if already queried.
|
1232 |
+
*
|
1233 |
+
* @return PaymentToken[]
|
1234 |
+
*/
|
1235 |
+
private function get_payment_tokens(): array {
|
1236 |
+
if ( null === $this->payment_tokens ) {
|
1237 |
+
$this->payment_tokens = $this->payment_token_repository->all_for_user_id( get_current_user_id() );
|
1238 |
+
}
|
1239 |
+
|
1240 |
+
return $this->payment_tokens;
|
1241 |
+
}
|
1242 |
+
|
1243 |
+
/**
|
1244 |
+
* Returns the vaulted PayPal email or empty string.
|
1245 |
+
*
|
1246 |
+
* @return string
|
1247 |
+
*/
|
1248 |
+
private function get_vaulted_paypal_email(): string {
|
1249 |
+
try {
|
1250 |
+
$tokens = $this->get_payment_tokens();
|
1251 |
+
|
1252 |
+
foreach ( $tokens as $token ) {
|
1253 |
+
if ( isset( $token->source()->paypal ) ) {
|
1254 |
+
return $token->source()->paypal->payer->email_address;
|
1255 |
+
}
|
1256 |
+
}
|
1257 |
+
} catch ( Exception $exception ) {
|
1258 |
+
$this->logger->error( 'Failed to get PayPal vaulted email. ' . $exception->getMessage() );
|
1259 |
+
}
|
1260 |
+
return '';
|
1261 |
+
}
|
1262 |
}
|
modules/ppcp-button/src/ButtonModule.php
CHANGED
@@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint;
|
|
16 |
use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
17 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
18 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
|
|
19 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
20 |
use Interop\Container\ServiceProviderInterface;
|
21 |
use Psr\Container\ContainerInterface;
|
@@ -107,6 +108,15 @@ class ButtonModule implements ModuleInterface {
|
|
107 |
$endpoint->handle_request();
|
108 |
}
|
109 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
|
111 |
add_action(
|
112 |
'wc_ajax_' . ChangeCartEndpoint::ENDPOINT,
|
16 |
use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint;
|
17 |
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint;
|
18 |
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint;
|
19 |
+
use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint;
|
20 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
21 |
use Interop\Container\ServiceProviderInterface;
|
22 |
use Psr\Container\ContainerInterface;
|
108 |
$endpoint->handle_request();
|
109 |
}
|
110 |
);
|
111 |
+
add_action(
|
112 |
+
'wc_ajax_' . StartPayPalVaultingEndpoint::ENDPOINT,
|
113 |
+
static function () use ( $container ) {
|
114 |
+
$endpoint = $container->get( 'button.endpoint.vault-paypal' );
|
115 |
+
assert( $endpoint instanceof StartPayPalVaultingEndpoint );
|
116 |
+
|
117 |
+
$endpoint->handle_request();
|
118 |
+
}
|
119 |
+
);
|
120 |
|
121 |
add_action(
|
122 |
'wc_ajax_' . ChangeCartEndpoint::ENDPOINT,
|
modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php
CHANGED
@@ -12,10 +12,10 @@ namespace WooCommerce\PayPalCommerce\Button\Endpoint;
|
|
12 |
use Exception;
|
13 |
use Psr\Log\LoggerInterface;
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
15 |
-
use WooCommerce\PayPalCommerce\ApiClient\Entity\
|
|
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
17 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
18 |
-
use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerName;
|
19 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentMethod;
|
20 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
21 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
@@ -25,7 +25,10 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
|
25 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
26 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
27 |
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
|
|
28 |
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
|
|
|
|
29 |
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
30 |
|
31 |
/**
|
@@ -33,6 +36,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|
33 |
*/
|
34 |
class CreateOrderEndpoint implements EndpointInterface {
|
35 |
|
|
|
|
|
36 |
const ENDPOINT = 'ppc-create-order';
|
37 |
|
38 |
/**
|
@@ -177,6 +182,8 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|
177 |
try {
|
178 |
$data = $this->request_data->read_request( $this->nonce() );
|
179 |
$this->parsed_request_data = $data;
|
|
|
|
|
180 |
$wc_order = null;
|
181 |
if ( 'pay-now' === $data['context'] ) {
|
182 |
$wc_order = wc_get_order( (int) $data['order_id'] );
|
@@ -193,6 +200,21 @@ class CreateOrderEndpoint implements EndpointInterface {
|
|
193 |
$this->purchase_units = array( $this->purchase_unit_factory->from_wc_order( $wc_order ) );
|
194 |
} else {
|
195 |
$this->purchase_units = $this->cart_repository->all();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
}
|
197 |
|
198 |
$this->set_bn_code( $data );
|
12 |
use Exception;
|
13 |
use Psr\Log\LoggerInterface;
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
15 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\Amount;
|
16 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
17 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
18 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
|
|
19 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentMethod;
|
20 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
|
21 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
25 |
use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository;
|
26 |
use WooCommerce\PayPalCommerce\Button\Helper\EarlyOrderHandler;
|
27 |
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
28 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
29 |
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
30 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
31 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
32 |
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
33 |
|
34 |
/**
|
36 |
*/
|
37 |
class CreateOrderEndpoint implements EndpointInterface {
|
38 |
|
39 |
+
use FreeTrialHandlerTrait;
|
40 |
+
|
41 |
const ENDPOINT = 'ppc-create-order';
|
42 |
|
43 |
/**
|
182 |
try {
|
183 |
$data = $this->request_data->read_request( $this->nonce() );
|
184 |
$this->parsed_request_data = $data;
|
185 |
+
$payment_method = $data['payment_method'] ?? '';
|
186 |
+
$funding_source = $data['funding_source'] ?? '';
|
187 |
$wc_order = null;
|
188 |
if ( 'pay-now' === $data['context'] ) {
|
189 |
$wc_order = wc_get_order( (int) $data['order_id'] );
|
200 |
$this->purchase_units = array( $this->purchase_unit_factory->from_wc_order( $wc_order ) );
|
201 |
} else {
|
202 |
$this->purchase_units = $this->cart_repository->all();
|
203 |
+
|
204 |
+
// The cart does not have any info about payment method, so we must handle free trial here.
|
205 |
+
if ( (
|
206 |
+
CreditCardGateway::ID === $payment_method
|
207 |
+
|| ( PayPalGateway::ID === $payment_method && 'card' === $funding_source )
|
208 |
+
)
|
209 |
+
&& $this->is_free_trial_cart()
|
210 |
+
) {
|
211 |
+
$this->purchase_units[0]->set_amount(
|
212 |
+
new Amount(
|
213 |
+
new Money( 1.0, $this->purchase_units[0]->amount()->currency_code() ),
|
214 |
+
$this->purchase_units[0]->amount()->breakdown()
|
215 |
+
)
|
216 |
+
);
|
217 |
+
}
|
218 |
}
|
219 |
|
220 |
$this->set_bn_code( $data );
|
modules/ppcp-button/src/Endpoint/StartPayPalVaultingEndpoint.php
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The endpoint for starting vaulting of PayPal account (for free trial).
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\Button\Endpoint
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\Button\Endpoint;
|
11 |
+
|
12 |
+
use Exception;
|
13 |
+
use Psr\Log\LoggerInterface;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
15 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Class StartPayPalVaultingEndpoint.
|
19 |
+
*/
|
20 |
+
class StartPayPalVaultingEndpoint implements EndpointInterface {
|
21 |
+
|
22 |
+
|
23 |
+
const ENDPOINT = 'ppc-vault-paypal';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The Request Data Helper.
|
27 |
+
*
|
28 |
+
* @var RequestData
|
29 |
+
*/
|
30 |
+
private $request_data;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* The PaymentTokenEndpoint.
|
34 |
+
*
|
35 |
+
* @var PaymentTokenEndpoint
|
36 |
+
*/
|
37 |
+
private $payment_token_endpoint;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* The logger.
|
41 |
+
*
|
42 |
+
* @var LoggerInterface
|
43 |
+
*/
|
44 |
+
private $logger;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* StartPayPalVaultingEndpoint constructor.
|
48 |
+
*
|
49 |
+
* @param RequestData $request_data The Request Data Helper.
|
50 |
+
* @param PaymentTokenEndpoint $payment_token_endpoint The PaymentTokenEndpoint.
|
51 |
+
* @param LoggerInterface $logger The logger.
|
52 |
+
*/
|
53 |
+
public function __construct(
|
54 |
+
RequestData $request_data,
|
55 |
+
PaymentTokenEndpoint $payment_token_endpoint,
|
56 |
+
LoggerInterface $logger
|
57 |
+
) {
|
58 |
+
$this->request_data = $request_data;
|
59 |
+
$this->payment_token_endpoint = $payment_token_endpoint;
|
60 |
+
$this->logger = $logger;
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Returns the nonce.
|
65 |
+
*
|
66 |
+
* @return string
|
67 |
+
*/
|
68 |
+
public static function nonce(): string {
|
69 |
+
return self::ENDPOINT;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Handles the request.
|
74 |
+
*
|
75 |
+
* @return bool
|
76 |
+
*/
|
77 |
+
public function handle_request(): bool {
|
78 |
+
try {
|
79 |
+
$data = $this->request_data->read_request( $this->nonce() );
|
80 |
+
|
81 |
+
$user_id = get_current_user_id();
|
82 |
+
|
83 |
+
$return_url = $data['return_url'];
|
84 |
+
$cancel_url = add_query_arg( array( 'ppcp_vault' => 'cancel' ), $return_url );
|
85 |
+
|
86 |
+
$links = $this->payment_token_endpoint->start_paypal_token_creation(
|
87 |
+
$user_id,
|
88 |
+
$return_url,
|
89 |
+
$cancel_url
|
90 |
+
);
|
91 |
+
|
92 |
+
wp_send_json_success(
|
93 |
+
array(
|
94 |
+
'approve_link' => $links->approve_link(),
|
95 |
+
)
|
96 |
+
);
|
97 |
+
|
98 |
+
return true;
|
99 |
+
} catch ( Exception $error ) {
|
100 |
+
$this->logger->error( 'Failed to start PayPal vaulting: ' . $error->getMessage() );
|
101 |
+
|
102 |
+
wp_send_json_error(
|
103 |
+
array(
|
104 |
+
'name' => is_a( $error, PayPalApiException::class ) ? $error->name() : '',
|
105 |
+
'message' => $error->getMessage(),
|
106 |
+
)
|
107 |
+
);
|
108 |
+
return false;
|
109 |
+
}
|
110 |
+
}
|
111 |
+
}
|
modules/ppcp-onboarding/assets/js/settings.js
CHANGED
@@ -171,6 +171,16 @@ document.addEventListener(
|
|
171 |
return;
|
172 |
}
|
173 |
const allOptions = Array.from(document.querySelectorAll('select[name="ppcp[disable_cards][]"] option'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
const replace = () => {
|
175 |
const validOptions = allOptions.filter(
|
176 |
(option) => {
|
@@ -181,13 +191,35 @@ document.addEventListener(
|
|
181 |
const selectedValidOptions = validOptions.map(
|
182 |
(option) => {
|
183 |
option = option.cloneNode(true);
|
184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
185 |
return option;
|
186 |
}
|
187 |
);
|
|
|
188 |
target.innerHTML = '';
|
189 |
selectedValidOptions.forEach(
|
190 |
(option) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
target.append(option);
|
192 |
}
|
193 |
);
|
171 |
return;
|
172 |
}
|
173 |
const allOptions = Array.from(document.querySelectorAll('select[name="ppcp[disable_cards][]"] option'));
|
174 |
+
const iconVersions = {
|
175 |
+
'visa': {
|
176 |
+
'light': {'label': 'Visa (light)'},
|
177 |
+
'dark' : {'label': 'Visa (dark)', 'value': 'visa-dark'}
|
178 |
+
},
|
179 |
+
'mastercard': {
|
180 |
+
'light': {'label': 'Mastercard (light)'},
|
181 |
+
'dark' : {'label': 'Mastercard (dark)', 'value': 'mastercard-dark'}
|
182 |
+
}
|
183 |
+
}
|
184 |
const replace = () => {
|
185 |
const validOptions = allOptions.filter(
|
186 |
(option) => {
|
191 |
const selectedValidOptions = validOptions.map(
|
192 |
(option) => {
|
193 |
option = option.cloneNode(true);
|
194 |
+
let value = option.value;
|
195 |
+
option.selected = target.querySelector('option[value="' + value + '"]') && target.querySelector('option[value="' + value + '"]').selected;
|
196 |
+
if(value === 'visa' || value === 'mastercard') {
|
197 |
+
let darkOption = option.cloneNode(true);
|
198 |
+
let currentVersion = iconVersions[value];
|
199 |
+
let darkValue = iconVersions[value].dark.value;
|
200 |
+
|
201 |
+
option.text = currentVersion.light.label;
|
202 |
+
darkOption.text = currentVersion.dark.label;
|
203 |
+
darkOption.value = darkValue;
|
204 |
+
darkOption.selected = target.querySelector('option[value="' + darkValue + '"]') && target.querySelector('option[value="' + darkValue + '"]').selected;
|
205 |
+
|
206 |
+
return [option, darkOption];
|
207 |
+
}
|
208 |
return option;
|
209 |
}
|
210 |
);
|
211 |
+
|
212 |
target.innerHTML = '';
|
213 |
selectedValidOptions.forEach(
|
214 |
(option) => {
|
215 |
+
if(Array.isArray(option)){
|
216 |
+
option.forEach(
|
217 |
+
(option) => {
|
218 |
+
target.append(option);
|
219 |
+
}
|
220 |
+
)
|
221 |
+
}
|
222 |
+
|
223 |
target.append(option);
|
224 |
}
|
225 |
);
|
modules/ppcp-onboarding/src/OnboardingRESTController.php
CHANGED
@@ -10,6 +10,7 @@ declare(strict_types=1);
|
|
10 |
namespace WooCommerce\PayPalCommerce\Onboarding;
|
11 |
|
12 |
use Psr\Container\ContainerInterface;
|
|
|
13 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
14 |
|
15 |
/**
|
@@ -206,7 +207,7 @@ class OnboardingRESTController {
|
|
206 |
}
|
207 |
|
208 |
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
|
209 |
-
if ( PayPalGateway::ID === $gateway->id ) {
|
210 |
$gateway->update_option( 'enabled', 'yes' );
|
211 |
break;
|
212 |
}
|
10 |
namespace WooCommerce\PayPalCommerce\Onboarding;
|
11 |
|
12 |
use Psr\Container\ContainerInterface;
|
13 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
14 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
15 |
|
16 |
/**
|
207 |
}
|
208 |
|
209 |
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
|
210 |
+
if ( PayPalGateway::ID === $gateway->id || CreditCardGateway::ID === $gateway->id ) {
|
211 |
$gateway->update_option( 'enabled', 'yes' );
|
212 |
break;
|
213 |
}
|
modules/ppcp-onboarding/src/Render/OnboardingRenderer.php
CHANGED
@@ -107,9 +107,11 @@ class OnboardingRenderer {
|
|
107 |
$is_production ? 'production' : 'sandbox'
|
108 |
);
|
109 |
} catch ( RuntimeException $exception ) {
|
110 |
-
|
111 |
-
|
112 |
-
|
|
|
|
|
113 |
);
|
114 |
}
|
115 |
}
|
107 |
$is_production ? 'production' : 'sandbox'
|
108 |
);
|
109 |
} catch ( RuntimeException $exception ) {
|
110 |
+
echo esc_html(
|
111 |
+
__(
|
112 |
+
'We could not properly connect to PayPal. Try reloading the page.',
|
113 |
+
'woocommerce-paypal-payments'
|
114 |
+
) . " {$exception->getMessage()} {$exception->getFile()}:{$exception->getLine()}"
|
115 |
);
|
116 |
}
|
117 |
}
|
modules/ppcp-subscription/src/FreeTrialHandlerTrait.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Helper trait for the subscriptions handling.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\Subscription
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\Subscription;
|
11 |
+
|
12 |
+
use WC_Order;
|
13 |
+
use WC_Product;
|
14 |
+
use WC_Subscription;
|
15 |
+
use WC_Subscriptions_Product;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Class FreeTrialHandlerTrait
|
19 |
+
*/
|
20 |
+
trait FreeTrialHandlerTrait {
|
21 |
+
use SubscriptionsHandlerTrait;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Checks if the cart contains only free trial.
|
25 |
+
*
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
+
protected function is_free_trial_cart(): bool {
|
29 |
+
if ( ! $this->is_wcs_plugin_active() ) {
|
30 |
+
return false;
|
31 |
+
}
|
32 |
+
|
33 |
+
$cart = WC()->cart;
|
34 |
+
if ( ! $cart || $cart->is_empty() || (float) $cart->get_total( 'numeric' ) > 0 ) {
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
|
38 |
+
foreach ( $cart->get_cart() as $item ) {
|
39 |
+
$product = $item['data'] ?? null;
|
40 |
+
if ( ! $product instanceof WC_Product ) {
|
41 |
+
continue;
|
42 |
+
}
|
43 |
+
if ( WC_Subscriptions_Product::get_trial_length( $product ) > 0 ) {
|
44 |
+
return true;
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
return false;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Checks if the current product contains free trial.
|
53 |
+
*
|
54 |
+
* @return bool
|
55 |
+
*/
|
56 |
+
protected function is_free_trial_product(): bool {
|
57 |
+
if ( ! $this->is_wcs_plugin_active() ) {
|
58 |
+
return false;
|
59 |
+
}
|
60 |
+
|
61 |
+
$product = wc_get_product();
|
62 |
+
|
63 |
+
return $product
|
64 |
+
&& WC_Subscriptions_Product::is_subscription( $product )
|
65 |
+
&& WC_Subscriptions_Product::get_trial_length( $product ) > 0;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Checks if the given order contains only free trial.
|
70 |
+
*
|
71 |
+
* @param WC_Order $wc_order The WooCommerce order.
|
72 |
+
* @return bool
|
73 |
+
*/
|
74 |
+
protected function is_free_trial_order( WC_Order $wc_order ): bool {
|
75 |
+
if ( ! $this->is_wcs_plugin_active() ) {
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
|
79 |
+
if ( (float) $wc_order->get_total( 'numeric' ) > 0 ) {
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
|
83 |
+
$subs = wcs_get_subscriptions_for_order( $wc_order );
|
84 |
+
|
85 |
+
return ! empty(
|
86 |
+
array_filter(
|
87 |
+
$subs,
|
88 |
+
function ( WC_Subscription $sub ): bool {
|
89 |
+
return (float) $sub->get_total_initial_payment() <= 0;
|
90 |
+
}
|
91 |
+
)
|
92 |
+
);
|
93 |
+
}
|
94 |
+
}
|
modules/ppcp-subscription/src/Helper/SubscriptionHelper.php
CHANGED
@@ -11,6 +11,9 @@ declare(strict_types=1);
|
|
11 |
|
12 |
namespace WooCommerce\PayPalCommerce\Subscription\Helper;
|
13 |
|
|
|
|
|
|
|
14 |
/**
|
15 |
* Class SubscriptionHelper
|
16 |
*/
|
@@ -26,7 +29,7 @@ class SubscriptionHelper {
|
|
26 |
return false;
|
27 |
}
|
28 |
$product = wc_get_product();
|
29 |
-
return
|
30 |
}
|
31 |
|
32 |
/**
|
@@ -44,7 +47,7 @@ class SubscriptionHelper {
|
|
44 |
}
|
45 |
|
46 |
foreach ( $cart->get_cart() as $item ) {
|
47 |
-
if ( ! isset( $item['data'] ) || ! is_a( $item['data'],
|
48 |
continue;
|
49 |
}
|
50 |
if ( $item['data']->is_type( 'subscription' ) || $item['data']->is_type( 'subscription_variation' ) ) {
|
@@ -71,24 +74,7 @@ class SubscriptionHelper {
|
|
71 |
return false;
|
72 |
}
|
73 |
|
74 |
-
$
|
75 |
-
if ( is_a( $order, \WC_Order::class ) ) {
|
76 |
-
foreach ( $order->get_items() as $item ) {
|
77 |
-
if ( is_a( $item, \WC_Order_Item_Product::class ) ) {
|
78 |
-
$product = wc_get_product( $item->get_product_id() );
|
79 |
-
/**
|
80 |
-
* Class already exist in subscriptions plugin.
|
81 |
-
*
|
82 |
-
* @psalm-suppress UndefinedClass
|
83 |
-
*/
|
84 |
-
if ( is_a( $product, \WC_Product_Subscription::class ) ) {
|
85 |
-
return true;
|
86 |
-
}
|
87 |
-
}
|
88 |
-
}
|
89 |
-
}
|
90 |
-
|
91 |
-
return false;
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -101,12 +87,10 @@ class SubscriptionHelper {
|
|
101 |
if ( ! $this->plugin_is_active() ) {
|
102 |
return false;
|
103 |
}
|
104 |
-
$accept_manual_renewals =
|
105 |
-
//phpcs:disable Inpsyde.CodeQuality.VariablesName.SnakeCaseVar
|
106 |
\WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals',
|
107 |
-
//phpcs:enable Inpsyde.CodeQuality.VariablesName.SnakeCaseVar
|
108 |
'no'
|
109 |
-
)
|
110 |
return ! $accept_manual_renewals;
|
111 |
}
|
112 |
|
11 |
|
12 |
namespace WooCommerce\PayPalCommerce\Subscription\Helper;
|
13 |
|
14 |
+
use WC_Product;
|
15 |
+
use WC_Subscriptions_Product;
|
16 |
+
|
17 |
/**
|
18 |
* Class SubscriptionHelper
|
19 |
*/
|
29 |
return false;
|
30 |
}
|
31 |
$product = wc_get_product();
|
32 |
+
return $product && WC_Subscriptions_Product::is_subscription( $product );
|
33 |
}
|
34 |
|
35 |
/**
|
47 |
}
|
48 |
|
49 |
foreach ( $cart->get_cart() as $item ) {
|
50 |
+
if ( ! isset( $item['data'] ) || ! is_a( $item['data'], WC_Product::class ) ) {
|
51 |
continue;
|
52 |
}
|
53 |
if ( $item['data']->is_type( 'subscription' ) || $item['data']->is_type( 'subscription_variation' ) ) {
|
74 |
return false;
|
75 |
}
|
76 |
|
77 |
+
return $this->has_subscription( $order_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
}
|
79 |
|
80 |
/**
|
87 |
if ( ! $this->plugin_is_active() ) {
|
88 |
return false;
|
89 |
}
|
90 |
+
$accept_manual_renewals = 'no' !== get_option(
|
|
|
91 |
\WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals',
|
|
|
92 |
'no'
|
93 |
+
);
|
94 |
return ! $accept_manual_renewals;
|
95 |
}
|
96 |
|
modules/ppcp-subscription/src/SubscriptionsHandlerTrait.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Helper trait for the free trial subscriptions handling.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\Subscription
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\Subscription;
|
11 |
+
|
12 |
+
use WC_Subscriptions;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Class SubscriptionsHandlerTrait
|
16 |
+
*/
|
17 |
+
trait SubscriptionsHandlerTrait {
|
18 |
+
/**
|
19 |
+
* Whether the subscription plugin is active or not.
|
20 |
+
*
|
21 |
+
* @return bool
|
22 |
+
*/
|
23 |
+
protected function is_wcs_plugin_active(): bool {
|
24 |
+
return class_exists( WC_Subscriptions::class );
|
25 |
+
}
|
26 |
+
}
|
modules/ppcp-vaulting/services.php
CHANGED
@@ -14,41 +14,47 @@ use WooCommerce\PayPalCommerce\Vaulting\Assets\MyAccountPaymentsAssets;
|
|
14 |
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
|
15 |
|
16 |
return array(
|
17 |
-
'vaulting.module-url'
|
18 |
return plugins_url(
|
19 |
'/modules/ppcp-vaulting/',
|
20 |
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
21 |
);
|
22 |
},
|
23 |
-
'vaulting.assets.myaccount-payments'
|
24 |
return new MyAccountPaymentsAssets(
|
25 |
$container->get( 'vaulting.module-url' ),
|
26 |
$container->get( 'ppcp.asset-version' )
|
27 |
);
|
28 |
},
|
29 |
-
'vaulting.payment-tokens-renderer'
|
30 |
return new PaymentTokensRenderer();
|
31 |
},
|
32 |
-
'vaulting.repository.payment-token'
|
33 |
$factory = $container->get( 'api.factory.payment-token' );
|
34 |
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
35 |
return new PaymentTokenRepository( $factory, $endpoint );
|
36 |
},
|
37 |
-
'vaulting.endpoint.delete'
|
38 |
return new DeletePaymentTokenEndpoint(
|
39 |
$container->get( 'vaulting.repository.payment-token' ),
|
40 |
$container->get( 'button.request-data' ),
|
41 |
$container->get( 'woocommerce.logger.woocommerce' )
|
42 |
);
|
43 |
},
|
44 |
-
'vaulting.payment-token-checker'
|
45 |
return new PaymentTokenChecker(
|
46 |
$container->get( 'vaulting.repository.payment-token' ),
|
|
|
47 |
$container->get( 'wcgateway.settings' ),
|
48 |
$container->get( 'wcgateway.processor.authorized-payments' ),
|
49 |
-
$container->get( 'api.endpoint.order' ),
|
50 |
$container->get( 'api.endpoint.payments' ),
|
51 |
$container->get( 'woocommerce.logger.woocommerce' )
|
52 |
);
|
53 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
);
|
14 |
use WooCommerce\PayPalCommerce\Vaulting\Endpoint\DeletePaymentTokenEndpoint;
|
15 |
|
16 |
return array(
|
17 |
+
'vaulting.module-url' => static function ( ContainerInterface $container ): string {
|
18 |
return plugins_url(
|
19 |
'/modules/ppcp-vaulting/',
|
20 |
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
21 |
);
|
22 |
},
|
23 |
+
'vaulting.assets.myaccount-payments' => function( ContainerInterface $container ) : MyAccountPaymentsAssets {
|
24 |
return new MyAccountPaymentsAssets(
|
25 |
$container->get( 'vaulting.module-url' ),
|
26 |
$container->get( 'ppcp.asset-version' )
|
27 |
);
|
28 |
},
|
29 |
+
'vaulting.payment-tokens-renderer' => static function (): PaymentTokensRenderer {
|
30 |
return new PaymentTokensRenderer();
|
31 |
},
|
32 |
+
'vaulting.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {
|
33 |
$factory = $container->get( 'api.factory.payment-token' );
|
34 |
$endpoint = $container->get( 'api.endpoint.payment-token' );
|
35 |
return new PaymentTokenRepository( $factory, $endpoint );
|
36 |
},
|
37 |
+
'vaulting.endpoint.delete' => function( ContainerInterface $container ) : DeletePaymentTokenEndpoint {
|
38 |
return new DeletePaymentTokenEndpoint(
|
39 |
$container->get( 'vaulting.repository.payment-token' ),
|
40 |
$container->get( 'button.request-data' ),
|
41 |
$container->get( 'woocommerce.logger.woocommerce' )
|
42 |
);
|
43 |
},
|
44 |
+
'vaulting.payment-token-checker' => function( ContainerInterface $container ) : PaymentTokenChecker {
|
45 |
return new PaymentTokenChecker(
|
46 |
$container->get( 'vaulting.repository.payment-token' ),
|
47 |
+
$container->get( 'api.repository.order' ),
|
48 |
$container->get( 'wcgateway.settings' ),
|
49 |
$container->get( 'wcgateway.processor.authorized-payments' ),
|
|
|
50 |
$container->get( 'api.endpoint.payments' ),
|
51 |
$container->get( 'woocommerce.logger.woocommerce' )
|
52 |
);
|
53 |
},
|
54 |
+
'vaulting.customer-approval-listener' => function( ContainerInterface $container ) : CustomerApprovalListener {
|
55 |
+
return new CustomerApprovalListener(
|
56 |
+
$container->get( 'api.endpoint.payment-token' ),
|
57 |
+
$container->get( 'woocommerce.logger.woocommerce' )
|
58 |
+
);
|
59 |
+
},
|
60 |
);
|
modules/ppcp-vaulting/src/CustomerApprovalListener.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Confirm approval token after the PayPal vaulting approval by customer (v2/vault/payment-tokens with CUSTOMER_ACTION_REQUIRED response).
|
4 |
+
*
|
5 |
+
* @package WooCommerce\PayPalCommerce\Vaulting
|
6 |
+
*/
|
7 |
+
|
8 |
+
declare(strict_types=1);
|
9 |
+
|
10 |
+
namespace WooCommerce\PayPalCommerce\Vaulting;
|
11 |
+
|
12 |
+
use Exception;
|
13 |
+
use Psr\Log\LoggerInterface;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokenEndpoint;
|
15 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\AlreadyVaultedException;
|
16 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Class CustomerApprovalListener
|
20 |
+
*/
|
21 |
+
class CustomerApprovalListener {
|
22 |
+
|
23 |
+
use FreeTrialHandlerTrait;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The PaymentTokenEndpoint.
|
27 |
+
*
|
28 |
+
* @var PaymentTokenEndpoint
|
29 |
+
*/
|
30 |
+
private $payment_token_endpoint;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* The logger.
|
34 |
+
*
|
35 |
+
* @var LoggerInterface
|
36 |
+
*/
|
37 |
+
private $logger;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* CustomerApprovalListener constructor.
|
41 |
+
*
|
42 |
+
* @param PaymentTokenEndpoint $payment_token_endpoint The PaymentTokenEndpoint.
|
43 |
+
* @param LoggerInterface $logger The logger.
|
44 |
+
*/
|
45 |
+
public function __construct( PaymentTokenEndpoint $payment_token_endpoint, LoggerInterface $logger ) {
|
46 |
+
$this->payment_token_endpoint = $payment_token_endpoint;
|
47 |
+
$this->logger = $logger;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Listens for redirects after the PayPal vaulting approval by customer.
|
52 |
+
*
|
53 |
+
* @return void
|
54 |
+
*/
|
55 |
+
public function listen(): void {
|
56 |
+
$token = filter_input( INPUT_GET, 'approval_token_id', FILTER_SANITIZE_STRING );
|
57 |
+
if ( ! is_string( $token ) ) {
|
58 |
+
return;
|
59 |
+
}
|
60 |
+
|
61 |
+
$url = (string) filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL );
|
62 |
+
|
63 |
+
$query = wp_parse_url( $url, PHP_URL_QUERY );
|
64 |
+
if ( $query && str_contains( $query, 'ppcp_vault=cancel' ) ) {
|
65 |
+
$this->redirect( $url );
|
66 |
+
return;
|
67 |
+
}
|
68 |
+
|
69 |
+
try {
|
70 |
+
$this->payment_token_endpoint->create_from_approval_token( $token, get_current_user_id() );
|
71 |
+
|
72 |
+
$this->redirect( $url );
|
73 |
+
} catch ( AlreadyVaultedException $exception ) {
|
74 |
+
$this->logger->error( 'Failed to create payment token. ' . $exception->getMessage() );
|
75 |
+
$this->add_wc_error_notice(
|
76 |
+
__(
|
77 |
+
'This PayPal account is already saved on this site. Please check that you are logged in correctly.',
|
78 |
+
'woocommerce-paypal-payments'
|
79 |
+
)
|
80 |
+
);
|
81 |
+
} catch ( Exception $exception ) {
|
82 |
+
$this->logger->error( 'Failed to create payment token. ' . $exception->getMessage() );
|
83 |
+
$this->add_wc_error_notice( $exception->getMessage() );
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Makes the message to be added on the WC init event.
|
89 |
+
*
|
90 |
+
* @param string $message The message text.
|
91 |
+
*/
|
92 |
+
private function add_wc_error_notice( string $message ): void {
|
93 |
+
add_action(
|
94 |
+
'woocommerce_init',
|
95 |
+
function () use ( $message ): void {
|
96 |
+
wc_add_notice( $message, 'error' );
|
97 |
+
}
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Redirects removing the vaulting arguments.
|
103 |
+
*
|
104 |
+
* @param string $current_url The current request URL.
|
105 |
+
*/
|
106 |
+
private function redirect( string $current_url ): void {
|
107 |
+
wp_safe_redirect( remove_query_arg( array( 'ppcp_vault', 'approval_token_id', 'approval_session_id' ), $current_url ) );
|
108 |
+
exit();
|
109 |
+
}
|
110 |
+
}
|
modules/ppcp-vaulting/src/PaymentTokenChecker.php
CHANGED
@@ -13,10 +13,10 @@ use Exception;
|
|
13 |
use Psr\Log\LoggerInterface;
|
14 |
use RuntimeException;
|
15 |
use WC_Order;
|
16 |
-
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
17 |
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
18 |
-
use WooCommerce\PayPalCommerce\ApiClient\
|
19 |
-
use WooCommerce\PayPalCommerce\
|
|
|
20 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
21 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
22 |
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
@@ -26,6 +26,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|
26 |
*/
|
27 |
class PaymentTokenChecker {
|
28 |
|
|
|
|
|
29 |
/**
|
30 |
* The payment token repository.
|
31 |
*
|
@@ -33,6 +35,13 @@ class PaymentTokenChecker {
|
|
33 |
*/
|
34 |
protected $payment_token_repository;
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
/**
|
37 |
* The settings.
|
38 |
*
|
@@ -47,13 +56,6 @@ class PaymentTokenChecker {
|
|
47 |
*/
|
48 |
protected $authorized_payments_processor;
|
49 |
|
50 |
-
/**
|
51 |
-
* The order endpoint.
|
52 |
-
*
|
53 |
-
* @var OrderEndpoint
|
54 |
-
*/
|
55 |
-
protected $order_endpoint;
|
56 |
-
|
57 |
/**
|
58 |
* The payments endpoint.
|
59 |
*
|
@@ -72,24 +74,24 @@ class PaymentTokenChecker {
|
|
72 |
* PaymentTokenChecker constructor.
|
73 |
*
|
74 |
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
|
|
75 |
* @param Settings $settings The settings.
|
76 |
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The authorized payments processor.
|
77 |
-
* @param OrderEndpoint $order_endpoint The order endpoint.
|
78 |
* @param PaymentsEndpoint $payments_endpoint The payments endpoint.
|
79 |
* @param LoggerInterface $logger The logger.
|
80 |
*/
|
81 |
public function __construct(
|
82 |
PaymentTokenRepository $payment_token_repository,
|
|
|
83 |
Settings $settings,
|
84 |
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
85 |
-
OrderEndpoint $order_endpoint,
|
86 |
PaymentsEndpoint $payments_endpoint,
|
87 |
LoggerInterface $logger
|
88 |
) {
|
89 |
$this->payment_token_repository = $payment_token_repository;
|
|
|
90 |
$this->settings = $settings;
|
91 |
$this->authorized_payments_processor = $authorized_payments_processor;
|
92 |
-
$this->order_endpoint = $order_endpoint;
|
93 |
$this->payments_endpoint = $payments_endpoint;
|
94 |
$this->logger = $logger;
|
95 |
}
|
@@ -115,6 +117,18 @@ class PaymentTokenChecker {
|
|
115 |
$tokens = $this->payment_token_repository->all_for_user_id( $customer_id );
|
116 |
if ( $tokens ) {
|
117 |
try {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
$this->capture_authorized_payment( $wc_order );
|
119 |
} catch ( Exception $exception ) {
|
120 |
$this->logger->error( $exception->getMessage() );
|
@@ -126,8 +140,8 @@ class PaymentTokenChecker {
|
|
126 |
$this->logger->error( "Payment for subscription parent order #{$order_id} was not saved on PayPal." );
|
127 |
|
128 |
try {
|
129 |
-
$order = $this->
|
130 |
-
$this->void_authorizations( $order );
|
131 |
} catch ( RuntimeException $exception ) {
|
132 |
$this->logger->warning( $exception->getMessage() );
|
133 |
}
|
@@ -149,55 +163,6 @@ class PaymentTokenChecker {
|
|
149 |
}
|
150 |
}
|
151 |
|
152 |
-
/**
|
153 |
-
* Voids authorizations for the given PayPal order.
|
154 |
-
*
|
155 |
-
* @param Order $order The PayPal order.
|
156 |
-
* @return void
|
157 |
-
* @throws RuntimeException When there is a problem voiding authorizations.
|
158 |
-
*/
|
159 |
-
private function void_authorizations( Order $order ): void {
|
160 |
-
$purchase_units = $order->purchase_units();
|
161 |
-
if ( ! $purchase_units ) {
|
162 |
-
throw new RuntimeException( 'No purchase units.' );
|
163 |
-
}
|
164 |
-
|
165 |
-
$payments = $purchase_units[0]->payments();
|
166 |
-
if ( ! $payments ) {
|
167 |
-
throw new RuntimeException( 'No payments.' );
|
168 |
-
}
|
169 |
-
|
170 |
-
$voidable_authorizations = array_filter(
|
171 |
-
$payments->authorizations(),
|
172 |
-
function ( Authorization $authorization ): bool {
|
173 |
-
return $authorization->is_voidable();
|
174 |
-
}
|
175 |
-
);
|
176 |
-
if ( ! $voidable_authorizations ) {
|
177 |
-
throw new RuntimeException( 'No voidable authorizations.' );
|
178 |
-
}
|
179 |
-
|
180 |
-
foreach ( $voidable_authorizations as $authorization ) {
|
181 |
-
$this->payments_endpoint->void( $authorization );
|
182 |
-
}
|
183 |
-
}
|
184 |
-
|
185 |
-
/**
|
186 |
-
* Gets a PayPal order from the given WooCommerce order.
|
187 |
-
*
|
188 |
-
* @param WC_Order $wc_order The WooCommerce order.
|
189 |
-
* @return Order The PayPal order.
|
190 |
-
* @throws RuntimeException When there is a problem getting the PayPal order.
|
191 |
-
*/
|
192 |
-
private function get_order( WC_Order $wc_order ): Order {
|
193 |
-
$paypal_order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
194 |
-
if ( ! $paypal_order_id ) {
|
195 |
-
throw new RuntimeException( 'PayPal order ID not found in meta.' );
|
196 |
-
}
|
197 |
-
|
198 |
-
return $this->order_endpoint->order( $paypal_order_id );
|
199 |
-
}
|
200 |
-
|
201 |
/**
|
202 |
* Updates WC order and subscription status to failed and canceled respectively.
|
203 |
*
|
13 |
use Psr\Log\LoggerInterface;
|
14 |
use RuntimeException;
|
15 |
use WC_Order;
|
|
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
|
17 |
+
use WooCommerce\PayPalCommerce\ApiClient\Repository\OrderRepository;
|
18 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
19 |
+
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
20 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
21 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
22 |
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
26 |
*/
|
27 |
class PaymentTokenChecker {
|
28 |
|
29 |
+
use FreeTrialHandlerTrait;
|
30 |
+
|
31 |
/**
|
32 |
* The payment token repository.
|
33 |
*
|
35 |
*/
|
36 |
protected $payment_token_repository;
|
37 |
|
38 |
+
/**
|
39 |
+
* The order repository.
|
40 |
+
*
|
41 |
+
* @var OrderRepository
|
42 |
+
*/
|
43 |
+
protected $order_repository;
|
44 |
+
|
45 |
/**
|
46 |
* The settings.
|
47 |
*
|
56 |
*/
|
57 |
protected $authorized_payments_processor;
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
/**
|
60 |
* The payments endpoint.
|
61 |
*
|
74 |
* PaymentTokenChecker constructor.
|
75 |
*
|
76 |
* @param PaymentTokenRepository $payment_token_repository The payment token repository.
|
77 |
+
* @param OrderRepository $order_repository The order repository.
|
78 |
* @param Settings $settings The settings.
|
79 |
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The authorized payments processor.
|
|
|
80 |
* @param PaymentsEndpoint $payments_endpoint The payments endpoint.
|
81 |
* @param LoggerInterface $logger The logger.
|
82 |
*/
|
83 |
public function __construct(
|
84 |
PaymentTokenRepository $payment_token_repository,
|
85 |
+
OrderRepository $order_repository,
|
86 |
Settings $settings,
|
87 |
AuthorizedPaymentsProcessor $authorized_payments_processor,
|
|
|
88 |
PaymentsEndpoint $payments_endpoint,
|
89 |
LoggerInterface $logger
|
90 |
) {
|
91 |
$this->payment_token_repository = $payment_token_repository;
|
92 |
+
$this->order_repository = $order_repository;
|
93 |
$this->settings = $settings;
|
94 |
$this->authorized_payments_processor = $authorized_payments_processor;
|
|
|
95 |
$this->payments_endpoint = $payments_endpoint;
|
96 |
$this->logger = $logger;
|
97 |
}
|
117 |
$tokens = $this->payment_token_repository->all_for_user_id( $customer_id );
|
118 |
if ( $tokens ) {
|
119 |
try {
|
120 |
+
if ( $this->is_free_trial_order( $wc_order ) ) {
|
121 |
+
if ( CreditCardGateway::ID === $wc_order->get_payment_method()
|
122 |
+
|| ( PayPalGateway::ID === $wc_order->get_payment_method() && 'card' === $wc_order->get_meta( PayPalGateway::ORDER_PAYMENT_SOURCE ) )
|
123 |
+
) {
|
124 |
+
$order = $this->order_repository->for_wc_order( $wc_order );
|
125 |
+
$this->authorized_payments_processor->void_authorizations( $order );
|
126 |
+
$wc_order->payment_complete();
|
127 |
+
}
|
128 |
+
|
129 |
+
return;
|
130 |
+
}
|
131 |
+
|
132 |
$this->capture_authorized_payment( $wc_order );
|
133 |
} catch ( Exception $exception ) {
|
134 |
$this->logger->error( $exception->getMessage() );
|
140 |
$this->logger->error( "Payment for subscription parent order #{$order_id} was not saved on PayPal." );
|
141 |
|
142 |
try {
|
143 |
+
$order = $this->order_repository->for_wc_order( $wc_order );
|
144 |
+
$this->authorized_payments_processor->void_authorizations( $order );
|
145 |
} catch ( RuntimeException $exception ) {
|
146 |
$this->logger->warning( $exception->getMessage() );
|
147 |
}
|
163 |
}
|
164 |
}
|
165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
/**
|
167 |
* Updates WC order and subscription status to failed and canceled respectively.
|
168 |
*
|
modules/ppcp-vaulting/src/VaultingModule.php
CHANGED
@@ -43,6 +43,11 @@ class VaultingModule implements ModuleInterface {
|
|
43 |
return;
|
44 |
}
|
45 |
|
|
|
|
|
|
|
|
|
|
|
46 |
add_filter(
|
47 |
'woocommerce_account_menu_items',
|
48 |
function( $menu_links ) {
|
43 |
return;
|
44 |
}
|
45 |
|
46 |
+
$listener = $container->get( 'vaulting.customer-approval-listener' );
|
47 |
+
assert( $listener instanceof CustomerApprovalListener );
|
48 |
+
|
49 |
+
$listener->listen();
|
50 |
+
|
51 |
add_filter(
|
52 |
'woocommerce_account_menu_items',
|
53 |
function( $menu_links ) {
|
modules/ppcp-vaulting/yarn.lock
CHANGED
@@ -1722,9 +1722,9 @@ mimic-fn@^2.1.0:
|
|
1722 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1723 |
|
1724 |
minimist@^1.2.0, minimist@^1.2.5:
|
1725 |
-
version "1.2.
|
1726 |
-
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.
|
1727 |
-
integrity sha512-
|
1728 |
|
1729 |
ms@2.1.2:
|
1730 |
version "2.1.2"
|
1722 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1723 |
|
1724 |
minimist@^1.2.0, minimist@^1.2.5:
|
1725 |
+
version "1.2.6"
|
1726 |
+
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
1727 |
+
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
1728 |
|
1729 |
ms@2.1.2:
|
1730 |
version "2.1.2"
|
modules/ppcp-wc-gateway/extensions.php
CHANGED
@@ -88,8 +88,7 @@ return array(
|
|
88 |
);
|
89 |
},
|
90 |
'woocommerce.logger.woocommerce' => function ( ContainerInterface $container ): LoggerInterface {
|
91 |
-
|
92 |
-
if ( ! function_exists( 'wc_get_logger' ) || ! $settings->has( 'logging_enabled' ) || ! $settings->get( 'logging_enabled' ) ) {
|
93 |
return new NullLogger();
|
94 |
}
|
95 |
|
88 |
);
|
89 |
},
|
90 |
'woocommerce.logger.woocommerce' => function ( ContainerInterface $container ): LoggerInterface {
|
91 |
+
if ( ! function_exists( 'wc_get_logger' ) || ! $container->get( 'wcgateway.logging.is-enabled' ) ) {
|
|
|
92 |
return new NullLogger();
|
93 |
}
|
94 |
|
modules/ppcp-wc-gateway/services.php
CHANGED
@@ -771,21 +771,7 @@ return array(
|
|
771 |
>',
|
772 |
'</a>'
|
773 |
),
|
774 |
-
'options' =>
|
775 |
-
'card' => _x( 'Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
776 |
-
'credit' => _x( 'Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
777 |
-
'sepa' => _x( 'SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
778 |
-
'bancontact' => _x( 'Bancontact', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
779 |
-
'blik' => _x( 'BLIK', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
780 |
-
'eps' => _x( 'eps', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
781 |
-
'giropay' => _x( 'giropay', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
782 |
-
'ideal' => _x( 'iDEAL', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
783 |
-
'mercadopago' => _x( 'Mercado Pago', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
784 |
-
'mybank' => _x( 'MyBank', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
785 |
-
'p24' => _x( 'Przelewy24', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
786 |
-
'sofort' => _x( 'Sofort', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
787 |
-
'venmo' => _x( 'Venmo', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
788 |
-
),
|
789 |
'screens' => array(
|
790 |
State::STATE_START,
|
791 |
State::STATE_ONBOARDED,
|
@@ -1959,13 +1945,15 @@ return array(
|
|
1959 |
'woocommerce-paypal-payments'
|
1960 |
),
|
1961 |
'options' => array(
|
1962 |
-
'visa'
|
1963 |
-
'
|
1964 |
-
'
|
1965 |
-
'
|
1966 |
-
'
|
1967 |
-
'
|
1968 |
-
'
|
|
|
|
|
1969 |
),
|
1970 |
'screens' => array(
|
1971 |
State::STATE_ONBOARDED,
|
@@ -2041,14 +2029,23 @@ return array(
|
|
2041 |
* Here, we filter them out.
|
2042 |
*/
|
2043 |
$card_options = $fields['disable_cards']['options'];
|
|
|
|
|
2044 |
foreach ( $card_options as $card => $label ) {
|
2045 |
if ( $dcc_applies->can_process_card( $card ) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
2046 |
continue;
|
2047 |
}
|
2048 |
unset( $card_options[ $card ] );
|
2049 |
}
|
|
|
2050 |
$fields['disable_cards']['options'] = $card_options;
|
2051 |
-
$fields['card_icons']['options'] = $card_options;
|
2052 |
|
2053 |
/**
|
2054 |
* Display vault message on Pay Later label if vault is enabled.
|
@@ -2064,6 +2061,24 @@ return array(
|
|
2064 |
return $fields;
|
2065 |
},
|
2066 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2067 |
'wcgateway.checkout.address-preset' => static function( ContainerInterface $container ): CheckoutPayPalAddressPreset {
|
2068 |
|
2069 |
return new CheckoutPayPalAddressPreset(
|
@@ -2129,4 +2144,16 @@ return array(
|
|
2129 |
$container->get( 'wcgateway.settings' )
|
2130 |
);
|
2131 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2132 |
);
|
771 |
>',
|
772 |
'</a>'
|
773 |
),
|
774 |
+
'options' => $container->get( 'wcgateway.all-funding-sources' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
775 |
'screens' => array(
|
776 |
State::STATE_START,
|
777 |
State::STATE_ONBOARDED,
|
1945 |
'woocommerce-paypal-payments'
|
1946 |
),
|
1947 |
'options' => array(
|
1948 |
+
'visa' => _x( 'Visa (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1949 |
+
'visa-dark' => _x( 'Visa (dark)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1950 |
+
'mastercard' => _x( 'Mastercard (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1951 |
+
'mastercard-dark' => _x( 'Mastercard (dark)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1952 |
+
'amex' => _x( 'American Express', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1953 |
+
'discover' => _x( 'Discover', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1954 |
+
'jcb' => _x( 'JCB', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1955 |
+
'elo' => _x( 'Elo', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1956 |
+
'hiper' => _x( 'Hiper', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
1957 |
),
|
1958 |
'screens' => array(
|
1959 |
State::STATE_ONBOARDED,
|
2029 |
* Here, we filter them out.
|
2030 |
*/
|
2031 |
$card_options = $fields['disable_cards']['options'];
|
2032 |
+
$card_icons = $fields['card_icons']['options'];
|
2033 |
+
$dark_versions = array();
|
2034 |
foreach ( $card_options as $card => $label ) {
|
2035 |
if ( $dcc_applies->can_process_card( $card ) ) {
|
2036 |
+
if ( 'visa' === $card || 'mastercard' === $card ) {
|
2037 |
+
$dark_versions = array(
|
2038 |
+
'visa-dark' => $card_icons['visa-dark'],
|
2039 |
+
'mastercard-dark' => $card_icons['mastercard-dark'],
|
2040 |
+
);
|
2041 |
+
}
|
2042 |
continue;
|
2043 |
}
|
2044 |
unset( $card_options[ $card ] );
|
2045 |
}
|
2046 |
+
|
2047 |
$fields['disable_cards']['options'] = $card_options;
|
2048 |
+
$fields['card_icons']['options'] = array_merge( $dark_versions, $card_options );
|
2049 |
|
2050 |
/**
|
2051 |
* Display vault message on Pay Later label if vault is enabled.
|
2061 |
return $fields;
|
2062 |
},
|
2063 |
|
2064 |
+
'wcgateway.all-funding-sources' => static function( ContainerInterface $container ): array {
|
2065 |
+
return array(
|
2066 |
+
'card' => _x( 'Credit or debit cards', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2067 |
+
'credit' => _x( 'Pay Later', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2068 |
+
'sepa' => _x( 'SEPA-Lastschrift', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2069 |
+
'bancontact' => _x( 'Bancontact', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2070 |
+
'blik' => _x( 'BLIK', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2071 |
+
'eps' => _x( 'eps', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2072 |
+
'giropay' => _x( 'giropay', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2073 |
+
'ideal' => _x( 'iDEAL', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2074 |
+
'mercadopago' => _x( 'Mercado Pago', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2075 |
+
'mybank' => _x( 'MyBank', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2076 |
+
'p24' => _x( 'Przelewy24', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2077 |
+
'sofort' => _x( 'Sofort', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2078 |
+
'venmo' => _x( 'Venmo', 'Name of payment method', 'woocommerce-paypal-payments' ),
|
2079 |
+
);
|
2080 |
+
},
|
2081 |
+
|
2082 |
'wcgateway.checkout.address-preset' => static function( ContainerInterface $container ): CheckoutPayPalAddressPreset {
|
2083 |
|
2084 |
return new CheckoutPayPalAddressPreset(
|
2144 |
$container->get( 'wcgateway.settings' )
|
2145 |
);
|
2146 |
},
|
2147 |
+
|
2148 |
+
'wcgateway.logging.is-enabled' => function ( ContainerInterface $container ) : bool {
|
2149 |
+
$settings = $container->get( 'wcgateway.settings' );
|
2150 |
+
|
2151 |
+
/**
|
2152 |
+
* Whether the logging of the plugin errors/events is enabled.
|
2153 |
+
*/
|
2154 |
+
return apply_filters(
|
2155 |
+
'woocommerce_paypal_payments_is_logging_enabled',
|
2156 |
+
$settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' )
|
2157 |
+
);
|
2158 |
+
},
|
2159 |
);
|
modules/ppcp-wc-gateway/src/Gateway/CreditCardGateway.php
CHANGED
@@ -331,8 +331,9 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|
331 |
$title_options = $this->card_labels();
|
332 |
$images = array_map(
|
333 |
function ( string $type ) use ( $title_options ): string {
|
|
|
334 |
return '<img
|
335 |
-
title="' . esc_attr( $title_options[ $
|
336 |
src="' . esc_url( $this->module_url ) . 'assets/images/' . esc_attr( $type ) . '.svg"
|
337 |
class="ppcp-card-icon"
|
338 |
> ';
|
@@ -439,7 +440,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|
439 |
parent::init_settings();
|
440 |
|
441 |
// looks like in some cases WC uses this field instead of get_option.
|
442 |
-
$this->enabled = $this->is_enabled();
|
443 |
}
|
444 |
|
445 |
/**
|
@@ -468,6 +469,7 @@ class CreditCardGateway extends \WC_Payment_Gateway_CC {
|
|
468 |
$ret = parent::update_option( $key, $value );
|
469 |
|
470 |
if ( 'enabled' === $key ) {
|
|
|
471 |
$this->config->set( 'dcc_enabled', 'yes' === $value );
|
472 |
$this->config->persist();
|
473 |
|
331 |
$title_options = $this->card_labels();
|
332 |
$images = array_map(
|
333 |
function ( string $type ) use ( $title_options ): string {
|
334 |
+
$striped_dark = str_replace( '-dark', '', $type );
|
335 |
return '<img
|
336 |
+
title="' . esc_attr( $title_options[ $striped_dark ] ) . '"
|
337 |
src="' . esc_url( $this->module_url ) . 'assets/images/' . esc_attr( $type ) . '.svg"
|
338 |
class="ppcp-card-icon"
|
339 |
> ';
|
440 |
parent::init_settings();
|
441 |
|
442 |
// looks like in some cases WC uses this field instead of get_option.
|
443 |
+
$this->enabled = $this->is_enabled() ? 'yes' : '';
|
444 |
}
|
445 |
|
446 |
/**
|
469 |
$ret = parent::update_option( $key, $value );
|
470 |
|
471 |
if ( 'enabled' === $key ) {
|
472 |
+
|
473 |
$this->config->set( 'dcc_enabled', 'yes' === $value );
|
474 |
$this->config->persist();
|
475 |
|
modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php
CHANGED
@@ -37,6 +37,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|
37 |
const INTENT_META_KEY = '_ppcp_paypal_intent';
|
38 |
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
39 |
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
|
|
40 |
const FEES_META_KEY = '_ppcp_paypal_fees';
|
41 |
|
42 |
/**
|
37 |
const INTENT_META_KEY = '_ppcp_paypal_intent';
|
38 |
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
39 |
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
40 |
+
const ORDER_PAYMENT_SOURCE = '_ppcp_paypal_payment_source';
|
41 |
const FEES_META_KEY = '_ppcp_paypal_fees';
|
42 |
|
43 |
/**
|
modules/ppcp-wc-gateway/src/Gateway/ProcessPaymentTrait.php
CHANGED
@@ -11,9 +11,11 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
|
11 |
|
12 |
use Exception;
|
13 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
|
|
14 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
16 |
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
|
|
17 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
18 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
19 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
|
@@ -24,7 +26,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
|
24 |
*/
|
25 |
trait ProcessPaymentTrait {
|
26 |
|
27 |
-
use OrderMetaTrait, PaymentsStatusHandlingTrait, TransactionIdHandlingTrait;
|
28 |
|
29 |
/**
|
30 |
* Process a payment for an WooCommerce order.
|
@@ -53,6 +55,7 @@ trait ProcessPaymentTrait {
|
|
53 |
}
|
54 |
|
55 |
$payment_method = filter_input( INPUT_POST, 'payment_method', FILTER_SANITIZE_STRING );
|
|
|
56 |
|
57 |
/**
|
58 |
* If customer has chosen a saved credit card payment.
|
@@ -115,7 +118,10 @@ trait ProcessPaymentTrait {
|
|
115 |
|
116 |
$this->handle_new_order_status( $order, $wc_order );
|
117 |
|
118 |
-
if ( $this->
|
|
|
|
|
|
|
119 |
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
120 |
}
|
121 |
|
@@ -130,6 +136,28 @@ trait ProcessPaymentTrait {
|
|
130 |
}
|
131 |
}
|
132 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
/**
|
134 |
* If customer has chosen change Subscription payment.
|
135 |
*/
|
11 |
|
12 |
use Exception;
|
13 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
14 |
+
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
15 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
16 |
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
17 |
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
18 |
+
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait;
|
19 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
20 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
21 |
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
|
26 |
*/
|
27 |
trait ProcessPaymentTrait {
|
28 |
|
29 |
+
use OrderMetaTrait, PaymentsStatusHandlingTrait, TransactionIdHandlingTrait, FreeTrialHandlerTrait;
|
30 |
|
31 |
/**
|
32 |
* Process a payment for an WooCommerce order.
|
55 |
}
|
56 |
|
57 |
$payment_method = filter_input( INPUT_POST, 'payment_method', FILTER_SANITIZE_STRING );
|
58 |
+
$funding_source = filter_input( INPUT_POST, 'ppcp-funding-source', FILTER_SANITIZE_STRING );
|
59 |
|
60 |
/**
|
61 |
* If customer has chosen a saved credit card payment.
|
118 |
|
119 |
$this->handle_new_order_status( $order, $wc_order );
|
120 |
|
121 |
+
if ( $this->is_free_trial_order( $wc_order ) ) {
|
122 |
+
$this->authorized_payments_processor->void_authorizations( $order );
|
123 |
+
$wc_order->payment_complete();
|
124 |
+
} elseif ( $this->config->has( 'intent' ) && strtoupper( (string) $this->config->get( 'intent' ) ) === 'CAPTURE' ) {
|
125 |
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
126 |
}
|
127 |
|
136 |
}
|
137 |
}
|
138 |
|
139 |
+
if ( PayPalGateway::ID === $payment_method && 'card' !== $funding_source && $this->is_free_trial_order( $wc_order ) ) {
|
140 |
+
$user_id = (int) $wc_order->get_customer_id();
|
141 |
+
$tokens = $this->payment_token_repository->all_for_user_id( $user_id );
|
142 |
+
if ( ! array_filter(
|
143 |
+
$tokens,
|
144 |
+
function ( PaymentToken $token ): bool {
|
145 |
+
return isset( $token->source()->paypal );
|
146 |
+
}
|
147 |
+
) ) {
|
148 |
+
$this->handle_failure( $wc_order, new Exception( 'No saved PayPal account.' ) );
|
149 |
+
return null;
|
150 |
+
}
|
151 |
+
|
152 |
+
$wc_order->payment_complete();
|
153 |
+
|
154 |
+
$this->session_handler->destroy_session_data();
|
155 |
+
return array(
|
156 |
+
'result' => 'success',
|
157 |
+
'redirect' => $this->get_return_url( $wc_order ),
|
158 |
+
);
|
159 |
+
}
|
160 |
+
|
161 |
/**
|
162 |
* If customer has chosen change Subscription payment.
|
163 |
*/
|
modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php
CHANGED
@@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
|
21 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
|
22 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
23 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
|
|
24 |
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
25 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
26 |
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
@@ -244,6 +245,39 @@ class AuthorizedPaymentsProcessor {
|
|
244 |
}
|
245 |
}
|
246 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
247 |
/**
|
248 |
* Displays the notice for a status.
|
249 |
*
|
21 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
|
22 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
23 |
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
24 |
+
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
25 |
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
|
26 |
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
27 |
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
245 |
}
|
246 |
}
|
247 |
|
248 |
+
/**
|
249 |
+
* Voids authorizations for the given PayPal order.
|
250 |
+
*
|
251 |
+
* @param Order $order The PayPal order.
|
252 |
+
* @return void
|
253 |
+
* @throws RuntimeException When there is a problem voiding authorizations.
|
254 |
+
*/
|
255 |
+
public function void_authorizations( Order $order ): void {
|
256 |
+
$purchase_units = $order->purchase_units();
|
257 |
+
if ( ! $purchase_units ) {
|
258 |
+
throw new RuntimeException( 'No purchase units.' );
|
259 |
+
}
|
260 |
+
|
261 |
+
$payments = $purchase_units[0]->payments();
|
262 |
+
if ( ! $payments ) {
|
263 |
+
throw new RuntimeException( 'No payments.' );
|
264 |
+
}
|
265 |
+
|
266 |
+
$voidable_authorizations = array_filter(
|
267 |
+
$payments->authorizations(),
|
268 |
+
function ( Authorization $authorization ): bool {
|
269 |
+
return $authorization->is_voidable();
|
270 |
+
}
|
271 |
+
);
|
272 |
+
if ( ! $voidable_authorizations ) {
|
273 |
+
throw new RuntimeException( 'No voidable authorizations.' );
|
274 |
+
}
|
275 |
+
|
276 |
+
foreach ( $voidable_authorizations as $authorization ) {
|
277 |
+
$this->payments_endpoint->void( $authorization );
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
/**
|
282 |
* Displays the notice for a status.
|
283 |
*
|
modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php
CHANGED
@@ -37,5 +37,29 @@ trait OrderMetaTrait {
|
|
37 |
PayPalGateway::ORDER_PAYMENT_MODE_META_KEY,
|
38 |
$environment->current_environment_is( Environment::SANDBOX ) ? 'sandbox' : 'live'
|
39 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
}
|
41 |
}
|
37 |
PayPalGateway::ORDER_PAYMENT_MODE_META_KEY,
|
38 |
$environment->current_environment_is( Environment::SANDBOX ) ? 'sandbox' : 'live'
|
39 |
);
|
40 |
+
$payment_source = $this->get_payment_source( $order );
|
41 |
+
if ( $payment_source ) {
|
42 |
+
$wc_order->update_meta_data( PayPalGateway::ORDER_PAYMENT_SOURCE, $payment_source );
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Returns the payment source type or null,
|
48 |
+
*
|
49 |
+
* @param Order $order The PayPal order.
|
50 |
+
* @return string|null
|
51 |
+
*/
|
52 |
+
private function get_payment_source( Order $order ): ?string {
|
53 |
+
$source = $order->payment_source();
|
54 |
+
if ( $source ) {
|
55 |
+
if ( $source->card() ) {
|
56 |
+
return 'card';
|
57 |
+
}
|
58 |
+
if ( $source->wallet() ) {
|
59 |
+
return 'wallet';
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
return null;
|
64 |
}
|
65 |
}
|
modules/ppcp-wc-gateway/yarn.lock
CHANGED
@@ -1639,9 +1639,9 @@ mimic-fn@^2.1.0:
|
|
1639 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1640 |
|
1641 |
minimist@^1.2.0, minimist@^1.2.5:
|
1642 |
-
version "1.2.
|
1643 |
-
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.
|
1644 |
-
integrity sha512-
|
1645 |
|
1646 |
ms@2.1.2:
|
1647 |
version "2.1.2"
|
1639 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1640 |
|
1641 |
minimist@^1.2.0, minimist@^1.2.5:
|
1642 |
+
version "1.2.6"
|
1643 |
+
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
1644 |
+
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
1645 |
|
1646 |
ms@2.1.2:
|
1647 |
version "2.1.2"
|
modules/ppcp-webhooks/yarn.lock
CHANGED
@@ -1722,9 +1722,9 @@ mimic-fn@^2.1.0:
|
|
1722 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1723 |
|
1724 |
minimist@^1.2.0, minimist@^1.2.5:
|
1725 |
-
version "1.2.
|
1726 |
-
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.
|
1727 |
-
integrity sha512-
|
1728 |
|
1729 |
ms@2.1.2:
|
1730 |
version "2.1.2"
|
1722 |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
1723 |
|
1724 |
minimist@^1.2.0, minimist@^1.2.5:
|
1725 |
+
version "1.2.6"
|
1726 |
+
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
1727 |
+
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
1728 |
|
1729 |
ms@2.1.2:
|
1730 |
version "2.1.2"
|
psalm-baseline.xml
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
-
<files psalm-version="4.
|
3 |
<file src="modules/ppcp-api-client/services.php">
|
4 |
<UndefinedConstant occurrences="2">
|
5 |
<code>PAYPAL_API_URL</code>
|
@@ -206,25 +206,12 @@
|
|
206 |
<RedundantCast occurrences="1">
|
207 |
<code>(float) $item_total</code>
|
208 |
</RedundantCast>
|
209 |
-
<RedundantCastGivenDocblockType occurrences="6">
|
210 |
-
<code>(float) $cart->get_discount_total()</code>
|
211 |
-
<code>(float) $cart->get_shipping_total()</code>
|
212 |
-
<code>(float) $cart->get_total( 'numeric' )</code>
|
213 |
-
<code>(float) $order->get_total()</code>
|
214 |
-
<code>(float) $order->get_total_discount( false )</code>
|
215 |
-
<code>(float) $order->get_total_discount( false )</code>
|
216 |
-
</RedundantCastGivenDocblockType>
|
217 |
</file>
|
218 |
<file src="modules/ppcp-api-client/src/Factory/ItemFactory.php">
|
219 |
<ArgumentTypeCoercion occurrences="1"/>
|
220 |
<PossiblyInvalidArgument occurrences="1">
|
221 |
<code>$fees_from_session</code>
|
222 |
</PossiblyInvalidArgument>
|
223 |
-
<RedundantCastGivenDocblockType occurrences="3">
|
224 |
-
<code>(float) $order->get_item_subtotal( $item, false )</code>
|
225 |
-
<code>(float) $order->get_item_subtotal( $item, true )</code>
|
226 |
-
<code>(int) $item->get_quantity()</code>
|
227 |
-
</RedundantCastGivenDocblockType>
|
228 |
</file>
|
229 |
<file src="modules/ppcp-api-client/src/Factory/PayerFactory.php">
|
230 |
<PossiblyNullArgument occurrences="2">
|
@@ -261,18 +248,11 @@
|
|
261 |
<MissingReturnType occurrences="1">
|
262 |
<code>delete</code>
|
263 |
</MissingReturnType>
|
264 |
-
<RedundantCastGivenDocblockType occurrences="1">
|
265 |
-
<code>(bool) set_transient( $this->prefix . $key, $value )</code>
|
266 |
-
</RedundantCastGivenDocblockType>
|
267 |
</file>
|
268 |
<file src="modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php">
|
269 |
<PossiblyFalseArgument occurrences="1">
|
270 |
<code>strrpos( $locale, '-' )</code>
|
271 |
</PossiblyFalseArgument>
|
272 |
-
<RedundantCastGivenDocblockType occurrences="2">
|
273 |
-
<code>(string) home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) )</code>
|
274 |
-
<code>(string) wc_get_checkout_url()</code>
|
275 |
-
</RedundantCastGivenDocblockType>
|
276 |
</file>
|
277 |
<file src="modules/ppcp-api-client/src/Repository/PayPalRequestIdRepository.php">
|
278 |
<UndefinedConstant occurrences="1">
|
@@ -289,9 +269,6 @@
|
|
289 |
</UndefinedConstant>
|
290 |
</file>
|
291 |
<file src="modules/ppcp-button/src/Assets/SmartButton.php">
|
292 |
-
<InvalidScalarArgument occurrences="1">
|
293 |
-
<code>1</code>
|
294 |
-
</InvalidScalarArgument>
|
295 |
<MissingClosureParamType occurrences="1">
|
296 |
<code>$id</code>
|
297 |
</MissingClosureParamType>
|
@@ -419,13 +396,6 @@
|
|
419 |
<PossiblyUndefinedMethod occurrences="1">
|
420 |
<code>get_payment_method</code>
|
421 |
</PossiblyUndefinedMethod>
|
422 |
-
<UndefinedFunction occurrences="5">
|
423 |
-
<code>wcs_get_subscription( absint( $_GET['subscription_id'] ) )</code>
|
424 |
-
<code>wcs_get_subscription( absint( get_query_var( 'order-pay' ) ) )</code>
|
425 |
-
<code>wcs_get_subscription( absint( get_query_var( 'view-subscription' ) ) )</code>
|
426 |
-
<code>wcs_is_view_subscription_page()</code>
|
427 |
-
<code>wcs_order_contains_renewal( $order )</code>
|
428 |
-
</UndefinedFunction>
|
429 |
</file>
|
430 |
<file src="modules/ppcp-onboarding/services.php">
|
431 |
<MissingClosureParamType occurrences="1">
|
@@ -447,13 +417,6 @@
|
|
447 |
<code>PAYPAL_SANDBOX_API_URL</code>
|
448 |
</UndefinedConstant>
|
449 |
</file>
|
450 |
-
<file src="modules/ppcp-onboarding/src/Assets/OnboardingAssets.php">
|
451 |
-
<InvalidScalarArgument occurrences="3">
|
452 |
-
<code>1</code>
|
453 |
-
<code>1</code>
|
454 |
-
<code>1</code>
|
455 |
-
</InvalidScalarArgument>
|
456 |
-
</file>
|
457 |
<file src="modules/ppcp-onboarding/src/OnboardingModule.php">
|
458 |
<MissingClosureParamType occurrences="3">
|
459 |
<code>$config</code>
|
@@ -517,11 +480,6 @@
|
|
517 |
<code>getKey</code>
|
518 |
</MissingReturnType>
|
519 |
</file>
|
520 |
-
<file src="modules/ppcp-subscription/src/Helper/SubscriptionHelper.php">
|
521 |
-
<UndefinedClass occurrences="1">
|
522 |
-
<code>\WC_Subscriptions_Admin</code>
|
523 |
-
</UndefinedClass>
|
524 |
-
</file>
|
525 |
<file src="modules/ppcp-subscription/src/RenewalHandler.php">
|
526 |
<FalsableReturnStatement occurrences="1">
|
527 |
<code>current( $tokens )</code>
|
@@ -530,10 +488,6 @@
|
|
530 |
<code>process_order</code>
|
531 |
<code>renew</code>
|
532 |
</MissingReturnType>
|
533 |
-
<RedundantCastGivenDocblockType occurrences="2">
|
534 |
-
<code>(int) $customer->get_id()</code>
|
535 |
-
<code>(int) $wc_order->get_customer_id()</code>
|
536 |
-
</RedundantCastGivenDocblockType>
|
537 |
<TooManyArguments occurrences="1">
|
538 |
<code>apply_filters( 'woocommerce_paypal_payments_subscriptions_get_token_for_customer', null, $customer, $wc_order )</code>
|
539 |
</TooManyArguments>
|
@@ -556,9 +510,6 @@
|
|
556 |
<PossiblyNullReference occurrences="1">
|
557 |
<code>get</code>
|
558 |
</PossiblyNullReference>
|
559 |
-
<UndefinedClass occurrences="1">
|
560 |
-
<code>\WC_Subscription</code>
|
561 |
-
</UndefinedClass>
|
562 |
</file>
|
563 |
<file src="modules/ppcp-vaulting/services.php">
|
564 |
<PossiblyFalseArgument occurrences="1">
|
@@ -688,9 +639,6 @@
|
|
688 |
</PossiblyUndefinedVariable>
|
689 |
</file>
|
690 |
<file src="modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php">
|
691 |
-
<MissingReturnType occurrences="1">
|
692 |
-
<code>capture_authorizations</code>
|
693 |
-
</MissingReturnType>
|
694 |
<PossiblyNullReference occurrences="1">
|
695 |
<code>authorizations</code>
|
696 |
</PossiblyNullReference>
|
@@ -902,9 +850,6 @@
|
|
902 |
<code>$request['resource']['custom_id']</code>
|
903 |
<code>$request['resource']['id']</code>
|
904 |
</PossiblyNullArrayAccess>
|
905 |
-
<RedundantCastGivenDocblockType occurrences="1">
|
906 |
-
<code>(bool) $wc_order->update_status( 'cancelled' )</code>
|
907 |
-
</RedundantCastGivenDocblockType>
|
908 |
</file>
|
909 |
<file src="modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php">
|
910 |
<InvalidReturnStatement occurrences="2">
|
@@ -919,7 +864,6 @@
|
|
919 |
<PossiblyNullArgument occurrences="1">
|
920 |
<code>$request['event_type']</code>
|
921 |
</PossiblyNullArgument>
|
922 |
-
<RedundantCastGivenDocblockType occurrences="1"/>
|
923 |
</file>
|
924 |
<file src="src/services.php">
|
925 |
<PossiblyFalseArgument occurrences="1">
|
1 |
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<files psalm-version="4.22.0@fc2c6ab4d5fa5d644d8617089f012f3bb84b8703">
|
3 |
<file src="modules/ppcp-api-client/services.php">
|
4 |
<UndefinedConstant occurrences="2">
|
5 |
<code>PAYPAL_API_URL</code>
|
206 |
<RedundantCast occurrences="1">
|
207 |
<code>(float) $item_total</code>
|
208 |
</RedundantCast>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
209 |
</file>
|
210 |
<file src="modules/ppcp-api-client/src/Factory/ItemFactory.php">
|
211 |
<ArgumentTypeCoercion occurrences="1"/>
|
212 |
<PossiblyInvalidArgument occurrences="1">
|
213 |
<code>$fees_from_session</code>
|
214 |
</PossiblyInvalidArgument>
|
|
|
|
|
|
|
|
|
|
|
215 |
</file>
|
216 |
<file src="modules/ppcp-api-client/src/Factory/PayerFactory.php">
|
217 |
<PossiblyNullArgument occurrences="2">
|
248 |
<MissingReturnType occurrences="1">
|
249 |
<code>delete</code>
|
250 |
</MissingReturnType>
|
|
|
|
|
|
|
251 |
</file>
|
252 |
<file src="modules/ppcp-api-client/src/Repository/ApplicationContextRepository.php">
|
253 |
<PossiblyFalseArgument occurrences="1">
|
254 |
<code>strrpos( $locale, '-' )</code>
|
255 |
</PossiblyFalseArgument>
|
|
|
|
|
|
|
|
|
256 |
</file>
|
257 |
<file src="modules/ppcp-api-client/src/Repository/PayPalRequestIdRepository.php">
|
258 |
<UndefinedConstant occurrences="1">
|
269 |
</UndefinedConstant>
|
270 |
</file>
|
271 |
<file src="modules/ppcp-button/src/Assets/SmartButton.php">
|
|
|
|
|
|
|
272 |
<MissingClosureParamType occurrences="1">
|
273 |
<code>$id</code>
|
274 |
</MissingClosureParamType>
|
396 |
<PossiblyUndefinedMethod occurrences="1">
|
397 |
<code>get_payment_method</code>
|
398 |
</PossiblyUndefinedMethod>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
</file>
|
400 |
<file src="modules/ppcp-onboarding/services.php">
|
401 |
<MissingClosureParamType occurrences="1">
|
417 |
<code>PAYPAL_SANDBOX_API_URL</code>
|
418 |
</UndefinedConstant>
|
419 |
</file>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
420 |
<file src="modules/ppcp-onboarding/src/OnboardingModule.php">
|
421 |
<MissingClosureParamType occurrences="3">
|
422 |
<code>$config</code>
|
480 |
<code>getKey</code>
|
481 |
</MissingReturnType>
|
482 |
</file>
|
|
|
|
|
|
|
|
|
|
|
483 |
<file src="modules/ppcp-subscription/src/RenewalHandler.php">
|
484 |
<FalsableReturnStatement occurrences="1">
|
485 |
<code>current( $tokens )</code>
|
488 |
<code>process_order</code>
|
489 |
<code>renew</code>
|
490 |
</MissingReturnType>
|
|
|
|
|
|
|
|
|
491 |
<TooManyArguments occurrences="1">
|
492 |
<code>apply_filters( 'woocommerce_paypal_payments_subscriptions_get_token_for_customer', null, $customer, $wc_order )</code>
|
493 |
</TooManyArguments>
|
510 |
<PossiblyNullReference occurrences="1">
|
511 |
<code>get</code>
|
512 |
</PossiblyNullReference>
|
|
|
|
|
|
|
513 |
</file>
|
514 |
<file src="modules/ppcp-vaulting/services.php">
|
515 |
<PossiblyFalseArgument occurrences="1">
|
639 |
</PossiblyUndefinedVariable>
|
640 |
</file>
|
641 |
<file src="modules/ppcp-wc-gateway/src/Processor/AuthorizedPaymentsProcessor.php">
|
|
|
|
|
|
|
642 |
<PossiblyNullReference occurrences="1">
|
643 |
<code>authorizations</code>
|
644 |
</PossiblyNullReference>
|
850 |
<code>$request['resource']['custom_id']</code>
|
851 |
<code>$request['resource']['id']</code>
|
852 |
</PossiblyNullArrayAccess>
|
|
|
|
|
|
|
853 |
</file>
|
854 |
<file src="modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php">
|
855 |
<InvalidReturnStatement occurrences="2">
|
864 |
<PossiblyNullArgument occurrences="1">
|
865 |
<code>$request['event_type']</code>
|
866 |
</PossiblyNullArgument>
|
|
|
867 |
</file>
|
868 |
<file src="src/services.php">
|
869 |
<PossiblyFalseArgument occurrences="1">
|
psalm.xml.dist
CHANGED
@@ -29,6 +29,7 @@
|
|
29 |
|
30 |
<stubs>
|
31 |
<file name=".psalm/stubs.php"/>
|
|
|
32 |
<file name="vendor/php-stubs/wordpress-stubs/wordpress-stubs.php"/>
|
33 |
<file name="vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php"/>
|
34 |
</stubs>
|
29 |
|
30 |
<stubs>
|
31 |
<file name=".psalm/stubs.php"/>
|
32 |
+
<file name=".psalm/wcs.php"/>
|
33 |
<file name="vendor/php-stubs/wordpress-stubs/wordpress-stubs.php"/>
|
34 |
<file name="vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php"/>
|
35 |
</stubs>
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: woocommerce, paypal, payments, ecommerce, e-commerce, store, sales, sell,
|
|
4 |
Requires at least: 5.3
|
5 |
Tested up to: 5.9
|
6 |
Requires PHP: 7.1
|
7 |
-
Stable tag: 1.
|
8 |
License: GPLv2
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -81,6 +81,17 @@ Follow the steps below to connect the plugin to your PayPal account:
|
|
81 |
|
82 |
== Changelog ==
|
83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
= 1.7.1 =
|
85 |
* Fix - Hide smart buttons for free products and zero-sum carts #499
|
86 |
* Fix - Unprocessable Entity when paying with AMEX card #516
|
4 |
Requires at least: 5.3
|
5 |
Tested up to: 5.9
|
6 |
Requires PHP: 7.1
|
7 |
+
Stable tag: 1.8.0
|
8 |
License: GPLv2
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
81 |
|
82 |
== Changelog ==
|
83 |
|
84 |
+
= 1.8.0 =
|
85 |
+
* Add - Allow free trial subscriptions #580
|
86 |
+
* Fix - The Card Processing does not appear as an available payment method when manually creating an order #562
|
87 |
+
* Fix - Express buttons & Pay Later visible on variable Subscription products /w disabled vaulting #281
|
88 |
+
* Fix - Pay for order (guest) failing when no email address available #535
|
89 |
+
* Fix - Emoji in product description causing INVALID_STRING_LENGTH error #491
|
90 |
+
* Enhancement - Change cart total amount that is sent to PayPal gateway #486
|
91 |
+
* Enhancement - Include dark Visa and Mastercard gateway icon list for PayPal Card Processing #566
|
92 |
+
* Enhancement - Onboarding errors improvements #558
|
93 |
+
* Enhancement - "Place order" button visible during gateway load time when DCC gateway is selected as the default #560
|
94 |
+
|
95 |
= 1.7.1 =
|
96 |
* Fix - Hide smart buttons for free products and zero-sum carts #499
|
97 |
* Fix - Unprocessable Entity when paying with AMEX card #516
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInit16558e4f2223b33dd8a9ed3fc3028843::getLoader();
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -22,15 +22,15 @@ class ComposerAutoloaderInitd9d5a07d2a80f7ccbdaae9d6cdd2640f
|
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
-
spl_autoload_register(array('
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
-
spl_autoload_unregister(array('
|
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\
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
@@ -51,19 +51,19 @@ class ComposerAutoloaderInitd9d5a07d2a80f7ccbdaae9d6cdd2640f
|
|
51 |
$loader->register(true);
|
52 |
|
53 |
if ($useStaticLoader) {
|
54 |
-
$includeFiles = Composer\Autoload\
|
55 |
} else {
|
56 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
57 |
}
|
58 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
59 |
-
|
60 |
}
|
61 |
|
62 |
return $loader;
|
63 |
}
|
64 |
}
|
65 |
|
66 |
-
function
|
67 |
{
|
68 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
69 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInit16558e4f2223b33dd8a9ed3fc3028843
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
22 |
return self::$loader;
|
23 |
}
|
24 |
|
25 |
+
spl_autoload_register(array('ComposerAutoloaderInit16558e4f2223b33dd8a9ed3fc3028843', 'loadClassLoader'), true, true);
|
26 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
27 |
+
spl_autoload_unregister(array('ComposerAutoloaderInit16558e4f2223b33dd8a9ed3fc3028843', '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\ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843::getInitializer($loader));
|
34 |
} else {
|
35 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
36 |
foreach ($map as $namespace => $path) {
|
51 |
$loader->register(true);
|
52 |
|
53 |
if ($useStaticLoader) {
|
54 |
+
$includeFiles = Composer\Autoload\ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843::$files;
|
55 |
} else {
|
56 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
57 |
}
|
58 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
59 |
+
composerRequire16558e4f2223b33dd8a9ed3fc3028843($fileIdentifier, $file);
|
60 |
}
|
61 |
|
62 |
return $loader;
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
function composerRequire16558e4f2223b33dd8a9ed3fc3028843($fileIdentifier, $file)
|
67 |
{
|
68 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
69 |
require $file;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
@@ -172,9 +172,9 @@ class ComposerStaticInitd9d5a07d2a80f7ccbdaae9d6cdd2640f
|
|
172 |
public static function getInitializer(ClassLoader $loader)
|
173 |
{
|
174 |
return \Closure::bind(function () use ($loader) {
|
175 |
-
$loader->prefixLengthsPsr4 =
|
176 |
-
$loader->prefixDirsPsr4 =
|
177 |
-
$loader->classMap =
|
178 |
|
179 |
}, null, ClassLoader::class);
|
180 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
172 |
public static function getInitializer(ClassLoader $loader)
|
173 |
{
|
174 |
return \Closure::bind(function () use ($loader) {
|
175 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843::$prefixLengthsPsr4;
|
176 |
+
$loader->prefixDirsPsr4 = ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843::$prefixDirsPsr4;
|
177 |
+
$loader->classMap = ComposerStaticInit16558e4f2223b33dd8a9ed3fc3028843::$classMap;
|
178 |
|
179 |
}, null, ClassLoader::class);
|
180 |
}
|
woocommerce-paypal-payments.php
CHANGED
@@ -3,13 +3,13 @@
|
|
3 |
* Plugin Name: WooCommerce PayPal Payments
|
4 |
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
|
5 |
* Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
6 |
-
* Version: 1.
|
7 |
* Author: WooCommerce
|
8 |
* Author URI: https://woocommerce.com/
|
9 |
* License: GPL-2.0
|
10 |
* Requires PHP: 7.1
|
11 |
* WC requires at least: 3.9
|
12 |
-
* WC tested up to: 6.
|
13 |
* Text Domain: woocommerce-paypal-payments
|
14 |
*
|
15 |
* @package WooCommerce\PayPalCommerce
|
@@ -21,7 +21,7 @@ namespace WooCommerce\PayPalCommerce;
|
|
21 |
|
22 |
define( 'PAYPAL_API_URL', 'https://api.paypal.com' );
|
23 |
define( 'PAYPAL_SANDBOX_API_URL', 'https://api.sandbox.paypal.com' );
|
24 |
-
define( 'PAYPAL_INTEGRATION_DATE', '
|
25 |
|
26 |
define( 'PPCP_FLAG_SUBSCRIPTION', true );
|
27 |
|
3 |
* Plugin Name: WooCommerce PayPal Payments
|
4 |
* Plugin URI: https://woocommerce.com/products/woocommerce-paypal-payments/
|
5 |
* Description: PayPal's latest complete payments processing solution. Accept PayPal, Pay Later, credit/debit cards, alternative digital wallets local payment types and bank accounts. Turn on only PayPal options or process a full suite of payment methods. Enable global transaction with extensive currency and country coverage.
|
6 |
+
* Version: 1.8.0
|
7 |
* Author: WooCommerce
|
8 |
* Author URI: https://woocommerce.com/
|
9 |
* License: GPL-2.0
|
10 |
* Requires PHP: 7.1
|
11 |
* WC requires at least: 3.9
|
12 |
+
* WC tested up to: 6.4
|
13 |
* Text Domain: woocommerce-paypal-payments
|
14 |
*
|
15 |
* @package WooCommerce\PayPalCommerce
|
21 |
|
22 |
define( 'PAYPAL_API_URL', 'https://api.paypal.com' );
|
23 |
define( 'PAYPAL_SANDBOX_API_URL', 'https://api.sandbox.paypal.com' );
|
24 |
+
define( 'PAYPAL_INTEGRATION_DATE', '2022-04-13' );
|
25 |
|
26 |
define( 'PPCP_FLAG_SUBSCRIPTION', true );
|
27 |
|