Completed
Push — master ( c7783b...124719 )
by Mike
13:48
created

wc-account-functions.php ➔ wc_get_account_menu_items()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 21
c 2
b 0
f 0
nc 18
nop 0
dl 0
loc 35
rs 6.7272
1
<?php
2
/**
3
 * WooCommerce Account Functions
4
 *
5
 * Functions for account specific things.
6
 *
7
 * @author   WooThemes
8
 * @category Core
9
 * @package  WooCommerce/Functions
10
 * @version  2.6.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Returns the url to the lost password endpoint url.
19
 *
20
 * @access public
21
 * @param  string $default_url
22
 * @return string
23
 */
24
function wc_lostpassword_url( $default_url = '' ) {
25
	$wc_password_reset_url = wc_get_page_permalink( 'myaccount' );
26
27
	if ( false !== $wc_password_reset_url ) {
28
		return wc_get_endpoint_url( 'lost-password', '', $wc_password_reset_url );
29
	} else {
30
		return $default_url;
31
	}
32
}
33
34
add_filter( 'lostpassword_url', 'wc_lostpassword_url', 10, 1 );
35
36
/**
37
 * Get the link to the edit account details page.
38
 *
39
 * @return string
40
 */
41
function wc_customer_edit_account_url() {
42
	$edit_account_url = wc_get_endpoint_url( 'edit-account', '', wc_get_page_permalink( 'myaccount' ) );
43
44
	return apply_filters( 'woocommerce_customer_edit_account_url', $edit_account_url );
45
}
46
47
/**
48
 * Get the edit address slug translation.
49
 *
50
 * @param  string  $id   Address ID.
51
 * @param  bool    $flip Flip the array to make it possible to retrieve the values ​​from both sides.
52
 *
53
 * @return string        Address slug i18n.
54
 */
55
function wc_edit_address_i18n( $id, $flip = false ) {
56
	$slugs = apply_filters( 'woocommerce_edit_address_slugs', array(
57
		'billing'  => sanitize_title( _x( 'billing', 'edit-address-slug', 'woocommerce' ) ),
58
		'shipping' => sanitize_title( _x( 'shipping', 'edit-address-slug', 'woocommerce' ) )
59
	) );
60
61
	if ( $flip ) {
62
		$slugs = array_flip( $slugs );
63
	}
64
65
	if ( ! isset( $slugs[ $id ] ) ) {
66
		return $id;
67
	}
68
69
	return $slugs[ $id ];
70
}
71
72
/**
73
 * Get My Account menu items.
74
 *
75
 * @since 2.6.0
76
 * @return array
77
 */
78
function wc_get_account_menu_items() {
79
	$items = array(
80
		'dashboard'       => __( 'Dashboard', 'woocommerce' ),
81
		'orders'          => __( 'Orders', 'woocommerce' ),
82
		'downloads'       => __( 'Downloads', 'woocommerce' ),
83
		'edit-address'    => __( 'Addresses', 'woocommerce' ),
84
		'payment-methods' => __( 'Payment Methods', 'woocommerce' ),
85
		'edit-account'    => __( 'Account Details', 'woocommerce' ),
86
		'customer-logout' => __( 'Logout', 'woocommerce' ),
87
	);
88
89
	// Remove empty items.
90
	if ( ! empty( WC()->customer ) ) {
91
		$downloads = WC()->customer->get_downloadable_products();
92
93
		if ( ! sizeof( $downloads ) ) {
94
			unset( $items['downloads'] );
95
		}
96
	}
97
98
	// Check if payment gateways support add new payment methods.
99
	$support_payment_methods = false;
100
	foreach ( WC()->payment_gateways->get_available_payment_gateways() as $gateway ) {
101
		if ( $gateway->supports( 'add_payment_method' ) || $gateway->supports( 'tokenization' ) ) {
102
			$support_payment_methods = true;
103
			break;
104
		}
105
	}
106
107
	if ( ! $support_payment_methods ) {
108
		unset( $items['payment-methods'] );
109
	}
110
111
	return apply_filters( 'woocommerce_account_menu_items', $items );
112
}
113
114
/**
115
 * Get account menu item classes.
116
 *
117
 * @since 2.6.0
118
 * @param string $endpoint
119
 * @return string
120
 */
121
function wc_get_account_menu_item_classes( $endpoint ) {
122
	global $wp;
123
124
	$classes = array(
125
		'woocommerce-MyAccount-navigation-link',
126
		'woocommerce-MyAccount-navigation-link--' . $endpoint,
127
	);
128
129
	// Set current item class.
130
	$current = isset( $wp->query_vars[ $endpoint ] );
131
	if ( 'dashboard' === $endpoint && ( isset( $wp->query_vars['page'] ) || empty( $wp->query_vars ) ) ) {
132
		$current = true; // Dashboard is not an endpoint, so needs a custom check.
133
	}
134
135
	if ( $current ) {
136
		$classes[] = 'is-active';
137
	}
138
139
	$classes = apply_filters( 'woocommerce_account_menu_item_classes', $classes, $endpoint );
140
141
	return implode( ' ', array_map( 'sanitize_html_class', $classes ) );
142
}
143
144
/**
145
 * Get account endpoint URL.
146
 *
147
 * @since 2.6.0
148
 * @param string $endpoint
149
 * @return string
150
 */
151
function wc_get_account_endpoint_url( $endpoint ) {
152
	if ( 'dashboard' === $endpoint ) {
153
		return wc_get_page_permalink( 'myaccount' );
154
	}
155
156
	return wc_get_endpoint_url( $endpoint );
157
}
158
159
/**
160
 * Get My Account > Orders columns.
161
 *
162
 * @since 2.6.0
163
 * @return array
164
 */
165
function wc_get_account_orders_columns() {
166
	$columns = apply_filters( 'woocommerce_account_orders_columns', array(
167
		'order-number'  => __( 'Order', 'woocommerce' ),
168
		'order-date'    => __( 'Date', 'woocommerce' ),
169
		'order-status'  => __( 'Status', 'woocommerce' ),
170
		'order-total'   => __( 'Total', 'woocommerce' ),
171
		'order-actions' => '&nbsp;',
172
	) );
173
174
	// Deprecated filter since 2.6.0.
175
	return apply_filters( 'woocommerce_my_account_my_orders_columns', $columns );
176
}
177
178
/**
179
 * Get My Account > Downloads columns.
180
 *
181
 * @since 2.6.0
182
 * @return array
183
 */
184
function wc_get_account_downloads_columns() {
185
	return apply_filters( 'woocommerce_account_downloads_columns', array(
186
		'download-file'      => __( 'File', 'woocommerce' ),
187
		'download-remaining' => __( 'Remaining', 'woocommerce' ),
188
		'download-expires'   => __( 'Expires', 'woocommerce' ),
189
		'download-actions'   => '&nbsp;',
190
	) );
191
}
192
193
/**
194
 * Get My Account > Payment methods columns.
195
 *
196
 * @since 2.6.0
197
 * @return array
198
 */
199
function wc_get_account_payment_methods_columns() {
200
	return apply_filters( 'woocommerce_account_payment_methods_columns', array(
201
		'method'  => __( 'Method', 'woocommerce' ),
202
		'expires' => __( 'Expires', 'woocommerce' ),
203
		'actions' => '&nbsp;',
204
	) );
205
}
206
207
/**
208
 * Get My Account > Payment methods types
209
 *
210
 * @since 2.6.0
211
 * @return array
212
 */
213
function wc_get_account_payment_methods_types() {
214
	return apply_filters( 'woocommerce_payment_methods_types', array(
215
		'cc'     => __( 'Credit Card', 'woocommerce' ),
216
		'echeck' => __( 'eCheck', 'woocommerce' ),
217
	) );
218
}
219
220
/**
221
 * Returns an array of a user's saved payments list for output on the account tab.
222
 *
223
 * @since  2.6
224
 * @param  array $list         List of payment methods passed from wc_get_customer_saved_methods_list()
225
 * @param  int   $customer_id  The customer to fetch payment methods for
226
 * @return array               Filtered list of customers payment methods
227
 */
228
function wc_get_account_saved_payment_methods_list( $list, $customer_id ) {
229
	$payment_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id );
230
	foreach ( $payment_tokens as $payment_token ) {
231
		$delete_url      = wc_get_endpoint_url( 'delete-payment-method', $payment_token->get_id() );
232
		$delete_url      = wp_nonce_url( $delete_url, 'delete-payment-method-' . $payment_token->get_id() );
233
		$set_default_url = wc_get_endpoint_url( 'set-default-payment-method', $payment_token->get_id() );
234
		$set_default_url = wp_nonce_url( $set_default_url, 'set-default-payment-method-' . $payment_token->get_id() );
235
236
		$type            = strtolower( $payment_token->get_type() );
237
		$list[ $type ][] = array(
238
			'method' => array(
239
				'gateway' => $payment_token->get_gateway_id(),
240
			),
241
			'expires'    => esc_html__( 'N/A', 'woocommerce' ),
242
			'is_default' => $payment_token->is_default(),
243
			'actions'    => array(
244
				'delete' => array(
245
					'url'  => $delete_url,
246
					'name' => esc_html__( 'Delete', 'woocommerce' ),
247
				),
248
			),
249
		);
250
		$key = key( array_slice( $list[ $type ], -1, 1, true ) );
251
252
		if ( ! $payment_token->is_default() ) {
253
			$list[ $type ][$key]['actions']['default'] = array(
254
				'url' => $set_default_url,
255
				'name' => esc_html__( 'Make Default', 'woocommerce' ),
256
			);
257
		}
258
259
		$list[ $type ][ $key ] = apply_filters( 'woocommerce_payment_methods_list_item', $list[ $type ][ $key ], $payment_token );
260
	}
261
	return $list;
262
}
263
264
add_filter( 'woocommerce_saved_payment_methods_list', 'wc_get_account_saved_payment_methods_list', 10, 2 );
265
266
/**
267
 * Controls the output for credit cards on the my account page.
268
 *
269
 * @since 2.6
270
 * @param  array             $item         Individual list item from woocommerce_saved_payment_methods_list
271
 * @param  WC_Payment_Token $payment_token The payment token associated with this method entry
272
 * @return array                           Filtered item
273
 */
274
function wc_get_account_saved_payment_methods_list_item_cc( $item, $payment_token ) {
275
	if ( 'cc' !== strtolower( $payment_token->get_type() ) ) {
276
		return $item;
277
	}
278
279
	$card_type               = $payment_token->get_card_type();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Payment_Token as the method get_card_type() does only exist in the following sub-classes of WC_Payment_Token: WC_Payment_Token_CC. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
280
	$item['method']['last4'] = $payment_token->get_last4();
281
	$item['method']['brand'] = ( ! empty( $card_type ) ? ucfirst( $card_type ) : esc_html__( 'Credit Card', 'woocommerce' ) );
282
	$item['expires']         = $payment_token->get_expiry_month() . '/' . substr( $payment_token->get_expiry_year(), -2 );
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Payment_Token as the method get_expiry_month() does only exist in the following sub-classes of WC_Payment_Token: WC_Payment_Token_CC. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class WC_Payment_Token as the method get_expiry_year() does only exist in the following sub-classes of WC_Payment_Token: WC_Payment_Token_CC. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
283
284
	return $item;
285
}
286
287
add_filter( 'woocommerce_payment_methods_list_item', 'wc_get_account_saved_payment_methods_list_item_cc', 10, 2 );
288
289
/**
290
 * Controls the output for eChecks on the my account page.
291
 *
292
 * @since 2.6
293
 * @param  array             $item         Individual list item from woocommerce_saved_payment_methods_list
294
 * @param  WC_Payment_Token $payment_token The payment token associated with this method entry
295
 * @return array                           Filtered item
296
 */
297
function wc_get_account_saved_payment_methods_list_item_echeck( $item, $payment_token ) {
298
	if ( 'echeck' !== strtolower( $payment_token->get_type() ) ) {
299
		return $item;
300
	}
301
302
	$item['method']['last4'] = $payment_token->get_last4();
303
	$item['method']['brand'] =  esc_html__( 'eCheck', 'woocommerce' );
304
305
	return $item;
306
}
307
308
add_filter( 'woocommerce_payment_methods_list_item', 'wc_get_account_saved_payment_methods_list_item_echeck', 10, 2 );
309