Skip to content

Commit 60711aa

Browse files
authored
feat: Account URL added to Auth URLs. (#755)
* feat: Account URL added to Auth URLs. * fix: Account URL issues resolved + Variation Attribute connections refactored.
1 parent d2260ab commit 60711aa

15 files changed

+442
-106
lines changed

composer.lock

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

includes/admin/class-general.php

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public static function get_other_nonce_values( $excluded ) {
2525
[
2626
'cart_url' => woographql_setting( 'cart_url_nonce_param', '_wc_cart' ),
2727
'checkout_url' => woographql_setting( 'checkout_url_nonce_param', '_wc_checkout' ),
28+
'account_url' => woographql_setting( 'account_url_nonce_param', '_wc_account' ),
2829
'add_payment_method_url' => woographql_setting( 'add_payment_method_url_nonce_param', '_wc_payment' ),
2930
]
3031
);
@@ -33,25 +34,36 @@ public static function get_other_nonce_values( $excluded ) {
3334
}
3435

3536
/**
36-
* Returns General settings fields.
37+
* Returns the enabled authorizing URL fields.
3738
*
3839
* @return array
3940
*/
40-
public static function get_fields() {
41-
$custom_endpoint = apply_filters( 'woographql_authorizing_url_endpoint', null );
42-
$enabled_authorizing_url_fields = woographql_setting( 'enable_authorizing_url_fields', [] );
43-
$enabled_authorizing_url_fields = ! empty( $enabled_authorizing_url_fields ) ? array_keys( $enabled_authorizing_url_fields ) : [];
44-
$all_urls_checked = apply_filters(
41+
public static function enabled_authorizing_url_fields_value() {
42+
return apply_filters(
4543
'woographql_enabled_authorizing_url_fields',
4644
[
4745
'cart_url' => 'cart_url',
4846
'checkout_url' => 'checkout_url',
47+
'account_url' => 'account_url',
4948
'add_payment_method_url' => 'add_payment_method_url',
5049
]
5150
);
51+
}
52+
53+
/**
54+
* Returns General settings fields.
55+
*
56+
* @return array
57+
*/
58+
public static function get_fields() {
59+
$custom_endpoint = apply_filters( 'woographql_authorizing_url_endpoint', null );
60+
$enabled_authorizing_url_fields = woographql_setting( 'enable_authorizing_url_fields', [] );
61+
$enabled_authorizing_url_fields = ! empty( $enabled_authorizing_url_fields ) ? array_keys( $enabled_authorizing_url_fields ) : [];
62+
$all_urls_checked = self::enabled_authorizing_url_fields_value();
5263

5364
$cart_url_hardcoded = defined( 'CART_URL_NONCE_PARAM' ) && ! empty( constant( 'CART_URL_NONCE_PARAM' ) );
5465
$checkout_url_hardcoded = defined( 'CHECKOUT_URL_NONCE_PARAM' ) && ! empty( constant( 'CHECKOUT_URL_NONCE_PARAM' ) );
66+
$account_url_hardcoded = defined( 'ACCOUNT_URL_NONCE_PARAM' ) && ! empty( constant( 'ACCOUNT_URL_NONCE_PARAM' ) );
5567
$add_payment_method_url_hardcoded = defined( 'ADD_PAYMENT_METHOD_URL_NONCE_PARAM' ) && ! empty( constant( 'ADD_PAYMENT_METHOD_URL_NONCE_PARAM' ) );
5668

5769
$enable_auth_urls_hardcoded = defined( 'WPGRAPHQL_WOOCOMMERCE_ENABLE_AUTH_URLS' ) && ! empty( constant( 'ADD_PAYMENT_METHOD_URL_NONCE_PARAM' ) );
@@ -84,6 +96,7 @@ public static function get_fields() {
8496
[
8597
'cart_url' => __( 'Cart URL. Field name: <strong>cartUrl</strong>', 'wp-graphql-woocommerce' ),
8698
'checkout_url' => __( 'Checkout URL. Field name: <strong>checkoutUrl</strong>', 'wp-graphql-woocommerce' ),
99+
'account_url' => __( 'Account URL. Field name: <strong>accountUrl</strong>', 'wp-graphql-woocommerce' ),
87100
'add_payment_method_url' => __( 'Add Payment Method URL. Field name: <strong>addPaymentMethodUrl</strong>', 'wp-graphql-woocommerce' ),
88101
]
89102
),
@@ -158,6 +171,30 @@ public static function get_fields() {
158171
return $value;
159172
},
160173
],
174+
[
175+
'name' => 'account_url_nonce_param',
176+
'label' => __( 'Account URL nonce name', 'wp-graphql-woocommerce' ),
177+
'desc' => __( 'Query parameter name of the nonce included in the "accountUrl" field', 'wp-graphql-woocommerce' )
178+
. ( $account_url_hardcoded ? __( ' This setting is disabled. The "ACCOUNT_URL_NONCE_PARAM" flag has been set with code', 'wp-graphql-woocommerce' ) : '' ),
179+
'type' => 'text',
180+
'value' => $account_url_hardcoded ? ACCOUNT_URL_NONCE_PARAM : woographql_setting( 'account_url_nonce_param', '_wc_account' ),
181+
'disabled' => defined( 'ACCOUNT_URL_NONCE_PARAM' ) || ! in_array( 'account_url', $enabled_authorizing_url_fields, true ),
182+
'sanitize_callback' => function ( $value ) {
183+
$other_nonces = self::get_other_nonce_values( 'account_url' );
184+
if ( in_array( $value, $other_nonces, true ) ) {
185+
add_settings_error(
186+
'account_url_nonce_param',
187+
'unique',
188+
__( 'The <strong>Account URL nonce name</strong> field must be unique', 'wp-graphql-woocommerce' ),
189+
'error'
190+
);
191+
192+
return '_wc_account';
193+
}
194+
195+
return $value;
196+
},
197+
],
161198
[
162199
'name' => 'add_payment_method_url_nonce_param',
163200
'label' => __( 'Add Payment Method URL nonce name', 'wp-graphql-woocommerce' ),

includes/class-woocommerce-filters.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,7 @@ public static function is_session_handler_disabled() {
5757
*/
5858
public static function enabled_authorizing_url_fields() {
5959
if ( defined( 'WPGRAPHQL_WOOCOMMERCE_ENABLE_AUTH_URLS' ) ) {
60-
return apply_filters(
61-
'woographql_enabled_authorizing_url_fields',
62-
[
63-
'cart_url' => 'cart_url',
64-
'checkout_url' => 'checkout_url',
65-
'add_payment_method_url' => 'add_payment_method_url',
66-
]
67-
);
60+
return \WPGraphQL\WooCommerce\Admin\General::enabled_authorizing_url_fields_value();
6861
}
6962
return woographql_setting( 'enable_authorizing_url_fields', [] );
7063
}

includes/data/connection/class-variation-attribute-connection-resolver.php

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,57 @@ class Variation_Attribute_Connection_Resolver {
2525
/**
2626
* Returns data array from WC_Product_Attribute ArrayAccess object.
2727
*
28-
* @param array $attrs WC_Product_Attribute object.
29-
* @param string|int $parent_id ProductVariation Relay ID.
28+
* @param array $attrs Source Product's WC_Product_Attribute(s) object.
29+
* @param int $product_id Source Product ID.
30+
* @return array
31+
*/
32+
public static function product_attributes_to_data_array( $attrs, $product_id ) {
33+
$attributes = [];
34+
35+
foreach ( $attrs as $attribute ) {
36+
if ( ! is_a( $attribute, 'WC_Product_Attribute' ) ) {
37+
continue;
38+
}
39+
$name = wc_attribute_label( $attribute->get_name() );
40+
41+
if ( $attribute->is_taxonomy() ) {
42+
$attribute_taxonomy = $attribute->get_taxonomy_object();
43+
$attribute_values = wc_get_product_terms( $product_id, $attribute->get_name(), [ 'fields' => 'all' ] );
44+
foreach ( $attribute_values as $attribute_value ) {
45+
$id = base64_encode( $product_id . '|' . $name . '|' . $attribute_value->name ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
46+
$attributes[] = [
47+
'id' => $id,
48+
'attributeId' => $attribute_value->term_id,
49+
'name' => $name,
50+
'value' => $attribute_value->name,
51+
];
52+
}
53+
} else {
54+
$values = $attribute->get_options();
55+
foreach ( $values as $attribute_value ) {
56+
$id = base64_encode( $product_id . '|' . $name . '|' . $attribute_value ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
57+
$attributes[] = [
58+
'id' => $id,
59+
'attributeId' => 0,
60+
'name' => $name,
61+
'value' => $attribute_value,
62+
];
63+
}
64+
}//end if
65+
}//end foreach
66+
67+
return $attributes;
68+
}
69+
70+
/**
71+
* Returns data array from WC_Product_Attribute ArrayAccess object.
72+
*
73+
* @param array $attrs WC_Product_Attribute object.
74+
* @param string|int $variation_id Variable Product or Variation ID.
3075
*
3176
* @return array
3277
*/
33-
public static function to_data_array( $attrs = [], $parent_id = 0 ) {
78+
public static function variation_attributes_to_data_array( $attrs, $variation_id ) {
3479
$attributes = [];
3580

3681
// Bail early if explicitly '0' attributes.
@@ -43,26 +88,23 @@ public static function to_data_array( $attrs = [], $parent_id = 0 ) {
4388

4489
// ID create for caching only, not object retrieval.
4590
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
46-
$id = base64_encode( $parent_id . '||' . $name . '||' . $value );
91+
$id = base64_encode( $variation_id . '||' . $name . '||' . $value );
4792

4893
if ( ! $term instanceof \WP_Term ) {
4994
$attributes[] = [
50-
5195
'id' => $id,
5296
'attributeId' => 0,
5397
'name' => $name,
5498
'value' => $value,
5599
];
56-
57-
continue;
100+
} else {
101+
$attributes[] = [
102+
'id' => $id,
103+
'attributeId' => $term->term_id,
104+
'name' => $term->taxonomy,
105+
'value' => $term->name,
106+
];
58107
}
59-
60-
$attributes[] = [
61-
'id' => $id,
62-
'attributeId' => $term->term_id,
63-
'name' => $term->taxonomy,
64-
'value' => $term->name,
65-
];
66108
}//end foreach
67109

68110
return $attributes;
@@ -79,10 +121,13 @@ public static function to_data_array( $attrs = [], $parent_id = 0 ) {
79121
* @return array|null
80122
*/
81123
public function resolve( $source, array $args, AppContext $context, ResolveInfo $info ) {
82-
if ( is_a( $source, Product::class ) ) {
83-
$attributes = self::to_data_array( $source->default_attributes, $source->ID );
124+
if ( is_a( $source, Product::class ) && 'simple' === $source->get_type() ) {
125+
$attributes = self::product_attributes_to_data_array( $source->attributes, $source->ID );
84126
} else {
85-
$attributes = self::to_data_array( $source->attributes, $source->ID );
127+
$attributes = self::variation_attributes_to_data_array(
128+
is_a( $source, Product::class ) ? $source->default_attributes : $source->attributes,
129+
$source->ID
130+
);
86131
}
87132

88133
$connection = Relay::connectionFromArray( $attributes, $args );

includes/type/object/class-cart-type.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ public static function register_cart_item() {
685685
}
686686
}
687687

688-
return Variation_Attribute_Connection_Resolver::to_data_array( $attributes, $variation->ID );
688+
return Variation_Attribute_Connection_Resolver::variation_attributes_to_data_array( $attributes, $variation->ID );
689689
},
690690
],
691691
],

includes/type/object/class-customer-type.php

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,64 @@ public static function register_authorizing_url_fields( $fields_to_register ) {
438438
);
439439
}//end if
440440

441+
if ( in_array( 'account_url', $fields_to_register, true ) ) {
442+
register_graphql_fields(
443+
'Customer',
444+
[
445+
'accountUrl' => [
446+
'type' => 'String',
447+
'description' => __( 'A nonce link to the account page for session user. Expires in 24 hours.', 'wp-graphql-woocommerce' ),
448+
'resolve' => function( $source ) {
449+
if ( ! is_user_logged_in() ) {
450+
return null;
451+
}
452+
453+
// Get current customer and user ID.
454+
$customer_id = $source->ID;
455+
$current_user_id = get_current_user_id();
456+
457+
// Return null if current user not user being queried.
458+
if ( 0 !== $current_user_id && $current_user_id !== $customer_id ) {
459+
return null;
460+
}
461+
462+
// Build nonced url as an unauthenticated user.
463+
$nonce_name = woographql_setting( 'account_url_nonce_param', '_wc_account' );
464+
$url = add_query_arg(
465+
[
466+
'session_id' => $customer_id,
467+
$nonce_name => woographql_create_nonce( "load-account_{$customer_id}" ),
468+
],
469+
site_url( woographql_setting( 'authorizing_url_endpoint', 'transfer-session' ) )
470+
);
471+
472+
return esc_url_raw( $url );
473+
},
474+
],
475+
'accountNonce' => [
476+
'type' => 'String',
477+
'description' => __( 'A nonce for the account page. By default, it expires in 1 hour.', 'wp-graphql-woocommerce' ),
478+
'resolve' => function( $source ) {
479+
if ( ! is_user_logged_in() ) {
480+
return null;
481+
}
482+
483+
// Get current customer and user ID.
484+
$customer_id = $source->ID;
485+
$current_user_id = get_current_user_id();
486+
487+
// Return null if current user not user being queried.
488+
if ( 0 !== $current_user_id && $current_user_id !== $customer_id ) {
489+
return null;
490+
}
491+
492+
return woographql_create_nonce( "load-account_{$customer_id}" );
493+
},
494+
],
495+
]
496+
);
497+
}//end if
498+
441499
if ( in_array( 'add_payment_method_url', $fields_to_register, true ) ) {
442500
register_graphql_fields(
443501
'Customer',
@@ -464,7 +522,7 @@ public static function register_authorizing_url_fields( $fields_to_register ) {
464522
$url = add_query_arg(
465523
[
466524
'session_id' => $customer_id,
467-
$nonce_name => woographql_create_nonce( "load-account_{$customer_id}" ),
525+
$nonce_name => woographql_create_nonce( "add-payment-method_{$customer_id}" ),
468526
],
469527
site_url( woographql_setting( 'authorizing_url_endpoint', 'transfer-session' ) )
470528
);
@@ -476,6 +534,10 @@ public static function register_authorizing_url_fields( $fields_to_register ) {
476534
'type' => 'String',
477535
'description' => __( 'A nonce for the add payment method page. By default, it expires in 1 hour.', 'wp-graphql-woocommerce' ),
478536
'resolve' => function( $source ) {
537+
if ( ! is_user_logged_in() ) {
538+
return null;
539+
}
540+
479541
// Get current customer and user ID.
480542
$customer_id = $source->ID;
481543
$current_user_id = get_current_user_id();
@@ -485,7 +547,7 @@ public static function register_authorizing_url_fields( $fields_to_register ) {
485547
return null;
486548
}
487549

488-
return woographql_create_nonce( "load-account_{$customer_id}" );
550+
return woographql_create_nonce( "add-payment-method_{$customer_id}" );
489551
},
490552
],
491553
]

includes/utils/class-protected-router.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ public static function get_nonce_names() {
222222
foreach ( array_keys( $enabled_authorizing_url_fields ) as $field ) {
223223
$nonce_names[ $field ] = WooCommerce_Filters::get_authorizing_url_nonce_param_name( $field );
224224
}
225+
225226
return array_filter( $nonce_names );
226227
}
227228

@@ -237,8 +238,10 @@ public function get_nonce_prefix( $field ) {
237238
return 'load-cart_';
238239
case 'checkout_url':
239240
return 'load-checkout_';
240-
case 'add_payment_method_url':
241+
case 'account_url':
241242
return 'load-account_';
243+
case 'add_payment_method_url':
244+
return 'add-payment-method_';
242245
default:
243246
return apply_filters( 'woographql_auth_nonce_prefix', null, $field, $this );
244247
}
@@ -247,15 +250,23 @@ public function get_nonce_prefix( $field ) {
247250
/**
248251
* Returns the target endpoint url for the provided field.
249252
*
253+
* @todo Add error logging here when WC Page needs to be created.
254+
*
250255
* @param string $field Field.
251256
* @return string|null
252257
*/
253258
public function get_target_endpoint( $field ) {
254259
switch ( $field ) {
255260
case 'cart_url':
256-
return wc_get_endpoint_url( 'cart' );
261+
$cart_page_id = wc_get_page_id( 'cart' );
262+
$cart_page_url = get_permalink( $cart_page_id );
263+
return $cart_page_url ? $cart_page_url : null;
257264
case 'checkout_url':
258265
return wc_get_endpoint_url( 'checkout' );
266+
case 'account_url':
267+
$account_page_id = get_option( 'woocommerce_myaccount_page_id' );
268+
$account_page_url = get_permalink( $account_page_id );
269+
return $account_page_url ? $account_page_url : null;
259270
case 'add_payment_method_url':
260271
return wc_get_account_endpoint_url( 'add-payment-method' );
261272
default:

0 commit comments

Comments
 (0)