Completed
Pull Request — master (#11455)
by
unknown
11:57
created

wc-template-functions.php ➔ woocommerce_get_product_schema()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
eloc 15
nc 4
nop 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A wc-template-functions.php ➔ woocommerce_get_product_thumbnail() 0 14 3
1
<?php
2
/**
3
 * WooCommerce Template
4
 *
5
 * Functions for the templating system.
6
 *
7
 * @author   WooThemes
8
 * @category Core
9
 * @package  WooCommerce/Functions
10
 * @version  2.5.0
11
 */
12
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit; // Exit if accessed directly
15
}
16
17
/**
18
 * Handle redirects before content is output - hooked into template_redirect so is_page works.
19
 */
20
function wc_template_redirect() {
21
	global $wp_query, $wp;
22
23
	// When default permalinks are enabled, redirect shop page to post type archive url
24
	if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && $_GET['page_id'] == wc_get_page_id( 'shop' ) ) {
25
		wp_safe_redirect( get_post_type_archive_link('product') );
26
		exit;
27
	}
28
29
	// When on the checkout with an empty cart, redirect to cart page
30
	elseif ( is_page( wc_get_page_id( 'checkout' ) ) && wc_get_page_id( 'checkout' ) !== wc_get_page_id( 'cart' ) && WC()->cart->is_empty() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) ) {
31
		wc_add_notice( __( 'Checkout is not available whilst your cart is empty.', 'woocommerce' ), 'notice' );
32
		wp_redirect( wc_get_page_permalink( 'cart' ) );
33
		exit;
34
	}
35
36
	// Logout
37
	elseif ( isset( $wp->query_vars['customer-logout'] ) ) {
38
		wp_redirect( str_replace( '&amp;', '&', wp_logout_url( wc_get_page_permalink( 'myaccount' ) ) ) );
39
		exit;
40
	}
41
42
	// Redirect to the product page if we have a single product
43
	elseif ( is_search() && is_post_type_archive( 'product' ) && apply_filters( 'woocommerce_redirect_single_search_result', true ) && 1 === absint( $wp_query->found_posts ) ) {
44
		$product = wc_get_product( $wp_query->post );
45
46
		if ( $product && $product->is_visible() ) {
47
			wp_safe_redirect( get_permalink( $product->id ), 302 );
48
			exit;
49
		}
50
	}
51
52
	// Ensure payment gateways are loaded early
53
	elseif ( is_add_payment_method_page() ) {
54
55
		WC()->payment_gateways();
56
57
	}
58
59
	// Checkout pages handling
60
	elseif ( is_checkout() ) {
61
		// Buffer the checkout page
62
		ob_start();
63
64
		// Ensure gateways and shipping methods are loaded early
65
		WC()->payment_gateways();
66
		WC()->shipping();
67
	}
68
}
69
add_action( 'template_redirect', 'wc_template_redirect' );
70
71
/**
72
 * When loading sensitive checkout or account pages, send a HTTP header to limit rendering of pages to same origin iframes for security reasons.
73
 *
74
 * Can be disabled with: remove_action( 'template_redirect', 'wc_send_frame_options_header' );
75
 *
76
 * @since  2.3.10
77
 */
78
function wc_send_frame_options_header() {
79
	if ( is_checkout() || is_account_page() ) {
80
		send_frame_options_header();
81
	}
82
}
83
add_action( 'template_redirect', 'wc_send_frame_options_header' );
84
85
/**
86
 * No index our endpoints.
87
 * Prevent indexing pages like order-received.
88
 *
89
 * @since 2.5.3
90
 */
91
function wc_prevent_endpoint_indexing() {
92
	if ( is_wc_endpoint_url() || isset( $_GET['download_file'] ) ) {
93
		@header( 'X-Robots-Tag: noindex' );
94
	}
95
}
96
add_action( 'template_redirect', 'wc_prevent_endpoint_indexing' );
97
98
/**
99
 * Remove adjacent_posts_rel_link_wp_head - pointless for products.
100
 *
101
 * @since 2.7.0
102
 */
103
function wc_prevent_adjacent_posts_rel_link_wp_head() {
104
	if ( is_singular( 'product' ) ) {
105
		remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
106
	}
107
}
108
add_action( 'template_redirect', 'wc_prevent_adjacent_posts_rel_link_wp_head' );
109
110
/**
111
 * When the_post is called, put product data into a global.
112
 *
113
 * @param mixed $post
114
 * @return WC_Product
115
 */
116
function wc_setup_product_data( $post ) {
117
	unset( $GLOBALS['product'] );
118
119
	if ( is_int( $post ) )
120
		$post = get_post( $post );
121
122
	if ( empty( $post->post_type ) || ! in_array( $post->post_type, array( 'product', 'product_variation' ) ) )
123
		return;
124
125
	$GLOBALS['product'] = wc_get_product( $post );
126
127
	return $GLOBALS['product'];
128
}
129
add_action( 'the_post', 'wc_setup_product_data' );
130
131
if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
132
133
	/**
134
	 * Reset the loop's index and columns when we're done outputting a product loop.
135
	 * @subpackage	Loop
136
	 */
137
	function woocommerce_reset_loop() {
138
		$GLOBALS['woocommerce_loop'] = array(
139
			'loop'    => '',
140
			'columns' => '',
141
			'name'    => '',
142
		);
143
	}
144
}
145
add_filter( 'loop_end', 'woocommerce_reset_loop' );
146
147
/**
148
 * Products RSS Feed.
149
 * @deprecated 2.6
150
 * @access public
151
 */
152
function wc_products_rss_feed() {
153
	// Product RSS
154
	if ( is_post_type_archive( 'product' ) || is_singular( 'product' ) ) {
155
156
		$feed = get_post_type_archive_feed_link( 'product' );
157
158
		echo '<link rel="alternate" type="application/rss+xml"  title="' . esc_attr__( 'New products', 'woocommerce' ) . '" href="' . esc_url( $feed ) . '" />';
159
160
	} elseif ( is_tax( 'product_cat' ) ) {
161
162
		$term = get_term_by( 'slug', esc_attr( get_query_var('product_cat') ), 'product_cat' );
163
164 View Code Duplication
		if ( $term ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
			$feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) );
166
			echo '<link rel="alternate" type="application/rss+xml"  title="' . esc_attr( sprintf( __( 'New products added to %s', 'woocommerce' ), $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
167
		}
168
169
	} elseif ( is_tax( 'product_tag' ) ) {
170
171
		$term = get_term_by('slug', esc_attr( get_query_var('product_tag') ), 'product_tag');
172
173 View Code Duplication
		if ( $term ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
174
			$feed = add_query_arg('product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ));
175
			echo '<link rel="alternate" type="application/rss+xml"  title="' . sprintf(__( 'New products tagged %s', 'woocommerce' ), urlencode($term->name)) . '" href="' . esc_url( $feed ) . '" />';
176
		}
177
	}
178
}
179
180
/**
181
 * Output generator tag to aid debugging.
182
 *
183
 * @access public
184
 */
185
function wc_generator_tag( $gen, $type ) {
186
	switch ( $type ) {
187
		case 'html':
188
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '">';
189
			break;
190
		case 'xhtml':
191
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '" />';
192
			break;
193
	}
194
	return $gen;
195
}
196
197
/**
198
 * Add body classes for WC pages.
199
 *
200
 * @param  array $classes
201
 * @return array
202
 */
203
function wc_body_class( $classes ) {
204
	$classes = (array) $classes;
205
206
	if ( is_woocommerce() ) {
207
		$classes[] = 'woocommerce';
208
		$classes[] = 'woocommerce-page';
209
	}
210
211
	elseif ( is_checkout() ) {
212
		$classes[] = 'woocommerce-checkout';
213
		$classes[] = 'woocommerce-page';
214
	}
215
216
	elseif ( is_cart() ) {
217
		$classes[] = 'woocommerce-cart';
218
		$classes[] = 'woocommerce-page';
219
	}
220
221
	elseif ( is_account_page() ) {
222
		$classes[] = 'woocommerce-account';
223
		$classes[] = 'woocommerce-page';
224
	}
225
226
	if ( is_store_notice_showing() ) {
227
		$classes[] = 'woocommerce-demo-store';
228
	}
229
230
	foreach ( WC()->query->query_vars as $key => $value ) {
231
		if ( is_wc_endpoint_url( $key ) ) {
232
			$classes[] = 'woocommerce-' . sanitize_html_class( $key );
233
		}
234
	}
235
236
	return array_unique( $classes );
237
}
238
239
/**
240
 * Display the classes for the product cat div.
241
 *
242
 * @since 2.4.0
243
 * @param string|array $class One or more classes to add to the class list.
244
 * @param object $category object Optional.
245
 */
246
function wc_product_cat_class( $class = '', $category = null ) {
247
	// Separates classes with a single space, collates classes for post DIV
248
	echo 'class="' . esc_attr( join( ' ', wc_get_product_cat_class( $class, $category ) ) ) . '"';
249
}
250
251
/**
252
 * Get classname for loops based on $woocommerce_loop global.
253
 * @since 2.6.0
254
 * @return string
255
 */
256
function wc_get_loop_class() {
257
	global $woocommerce_loop;
258
259
	$woocommerce_loop['loop']    = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1   : 1;
260
	$woocommerce_loop['columns'] = ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 );
261
262
	if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
263
		return 'first';
264
	} elseif ( 0 === $woocommerce_loop['loop'] % $woocommerce_loop['columns'] ) {
265
		return 'last';
266
	} else {
267
		return '';
268
	}
269
}
270
271
/**
272
 * Get the classes for the product cat div.
273
 *
274
 * @since 2.4.0
275
 * @param string|array $class One or more classes to add to the class list.
276
 * @param object $category object Optional.
277
 */
278
function wc_get_product_cat_class( $class = '', $category = null ) {
279
	$classes   = is_array( $class ) ? $class : array_map( 'trim', explode( ' ', $class ) );
280
	$classes[] = 'product-category';
281
	$classes[] = 'product';
282
	$classes[] = wc_get_loop_class();
283
	$classes   = apply_filters( 'product_cat_class', $classes, $class, $category );
284
285
	return array_unique( array_filter( $classes ) );
286
}
287
288
/**
289
 * Adds extra post classes for products.
290
 *
291
 * @since 2.1.0
292
 * @param array $classes
293
 * @param string|array $class
294
 * @param int $post_id
295
 * @return array
296
 */
297
function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
0 ignored issues
show
Unused Code introduced by
The parameter $class is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
298
	if ( ! $post_id || 'product' !== get_post_type( $post_id ) ) {
299
		return $classes;
300
	}
301
302
	$product = wc_get_product( $post_id );
303
304
	if ( $product ) {
305
		$classes[] = wc_get_loop_class();
306
		$classes[] = $product->stock_status;
307
308
		if ( $product->is_on_sale() ) {
309
			$classes[] = 'sale';
310
		}
311
		if ( $product->is_featured() ) {
312
			$classes[] = 'featured';
313
		}
314
		if ( $product->is_downloadable() ) {
315
			$classes[] = 'downloadable';
316
		}
317
		if ( $product->is_virtual() ) {
318
			$classes[] = 'virtual';
319
		}
320
		if ( $product->is_sold_individually() ) {
321
			$classes[] = 'sold-individually';
322
		}
323
		if ( $product->is_taxable() ) {
324
			$classes[] = 'taxable';
325
		}
326
		if ( $product->is_shipping_taxable() ) {
327
			$classes[] = 'shipping-taxable';
328
		}
329
		if ( $product->is_purchasable() ) {
330
			$classes[] = 'purchasable';
331
		}
332
		if ( $product->get_type() ) {
333
			$classes[] = "product-type-" . $product->get_type();
334
		}
335
		if ( $product->is_type( 'variable' ) ) {
336
			if ( $product->has_default_attributes() ) {
337
				$classes[] = 'has-default-attributes';
338
			}
339
			if ( $product->has_child() ) {
340
				$classes[] = 'has-children';
341
			}
342
		}
343
	}
344
345
	if ( false !== ( $key = array_search( 'hentry', $classes ) ) ) {
346
		unset( $classes[ $key ] );
347
	}
348
349
	return $classes;
350
}
351
352
/**
353
 * Outputs hidden form inputs for each query string variable.
354
 * @since 2.7.0
355
 * @param array $values Name value pairs.
356
 * @param array $exclude Keys to exclude.
357
 * @param string $current_key Current key we are outputting.
358
 */
359
function wc_query_string_form_fields( $values = null, $exclude = array(), $current_key = '', $return = false ) {
360
	if ( is_null( $values ) ) {
361
		$values = $_GET;
362
	}
363
	$html = '';
364
365
	foreach ( $values as $key => $value ) {
366
		if ( in_array( $key, $exclude, true ) ) {
367
			continue;
368
		}
369
		if ( $current_key ) {
370
			$key = $current_key . '[' . $key . ']';
371
		}
372
		if ( is_array( $value ) ) {
373
			$html .= wc_query_string_form_fields( $value, $exclude, $key, true );
374
		} else {
375
			$html .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
376
		}
377
	}
378
379
	if ( $return ) {
380
		return $html;
381
	} else {
382
		echo $html;
383
	}
384
}
385
386
/** Template pages ********************************************************/
387
388
if ( ! function_exists( 'woocommerce_content' ) ) {
389
390
	/**
391
	 * Output WooCommerce content.
392
	 *
393
	 * This function is only used in the optional 'woocommerce.php' template.
394
	 * which people can add to their themes to add basic woocommerce support.
395
	 * without hooks or modifying core templates.
396
	 *
397
	 */
398
	function woocommerce_content() {
399
400
		if ( is_singular( 'product' ) ) {
401
402
			while ( have_posts() ) : the_post();
403
404
				wc_get_template_part( 'content', 'single-product' );
405
406
			endwhile;
407
408
		} else { ?>
409
410
			<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
411
412
				<h1 class="page-title"><?php woocommerce_page_title(); ?></h1>
413
414
			<?php endif; ?>
415
416
			<?php do_action( 'woocommerce_archive_description' ); ?>
417
418 View Code Duplication
			<?php if ( have_posts() ) : ?>
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
419
420
				<?php do_action('woocommerce_before_shop_loop'); ?>
421
422
				<?php woocommerce_product_loop_start(); ?>
423
424
					<?php woocommerce_product_subcategories(); ?>
425
426
					<?php while ( have_posts() ) : the_post(); ?>
427
428
						<?php wc_get_template_part( 'content', 'product' ); ?>
429
430
					<?php endwhile; // end of the loop. ?>
431
432
				<?php woocommerce_product_loop_end(); ?>
433
434
				<?php do_action('woocommerce_after_shop_loop'); ?>
435
436
			<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
437
438
				<?php do_action( 'woocommerce_no_products_found' ); ?>
439
440
			<?php endif;
441
442
		}
443
	}
444
}
445
446
/** Global ****************************************************************/
447
448
if ( ! function_exists( 'woocommerce_output_content_wrapper' ) ) {
449
450
	/**
451
	 * Output the start of the page wrapper.
452
	 *
453
	 */
454
	function woocommerce_output_content_wrapper() {
455
		wc_get_template( 'global/wrapper-start.php' );
456
	}
457
}
458
if ( ! function_exists( 'woocommerce_output_content_wrapper_end' ) ) {
459
460
	/**
461
	 * Output the end of the page wrapper.
462
	 *
463
	 */
464
	function woocommerce_output_content_wrapper_end() {
465
		wc_get_template( 'global/wrapper-end.php' );
466
	}
467
}
468
469
if ( ! function_exists( 'woocommerce_get_sidebar' ) ) {
470
471
	/**
472
	 * Get the shop sidebar template.
473
	 *
474
	 */
475
	function woocommerce_get_sidebar() {
476
		wc_get_template( 'global/sidebar.php' );
477
	}
478
}
479
480
if ( ! function_exists( 'woocommerce_demo_store' ) ) {
481
482
	/**
483
	 * Adds a demo store banner to the site if enabled.
484
	 *
485
	 */
486
	function woocommerce_demo_store() {
487
		if ( ! is_store_notice_showing() ) {
488
			return;
489
		}
490
491
		$notice = get_option( 'woocommerce_demo_store_notice' );
492
493
		if ( empty( $notice ) ) {
494
			$notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
495
		}
496
497
		echo apply_filters( 'woocommerce_demo_store', '<p class="demo_store">' . wp_kses_post( $notice ) . '</p>', $notice );
498
	}
499
}
500
501
/** Loop ******************************************************************/
502
503
if ( ! function_exists( 'woocommerce_page_title' ) ) {
504
505
	/**
506
	 * woocommerce_page_title function.
507
	 *
508
	 * @param  bool $echo
509
	 * @return string
510
	 */
511
	function woocommerce_page_title( $echo = true ) {
512
513
		if ( is_search() ) {
514
			$page_title = sprintf( __( 'Search Results: &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() );
515
516
			if ( get_query_var( 'paged' ) )
517
				$page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'woocommerce' ), get_query_var( 'paged' ) );
518
519
		} elseif ( is_tax() ) {
520
521
			$page_title = single_term_title( "", false );
522
523
		} else {
524
525
			$shop_page_id = wc_get_page_id( 'shop' );
526
			$page_title   = get_the_title( $shop_page_id );
527
528
		}
529
530
		$page_title = apply_filters( 'woocommerce_page_title', $page_title );
531
532
		if ( $echo )
533
			echo $page_title;
534
		else
535
			return $page_title;
536
	}
537
}
538
539
if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
540
541
	/**
542
	 * Output the start of a product loop. By default this is a UL.
543
	 *
544
	 * @param bool $echo
545
	 * @return string
546
	 */
547
	function woocommerce_product_loop_start( $echo = true ) {
548
		ob_start();
549
		$GLOBALS['woocommerce_loop']['loop'] = 0;
550
		wc_get_template( 'loop/loop-start.php' );
551
		if ( $echo )
552
			echo ob_get_clean();
553
		else
554
			return ob_get_clean();
555
	}
556
}
557
if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
558
559
	/**
560
	 * Output the end of a product loop. By default this is a UL.
561
	 *
562
	 * @param bool $echo
563
	 * @return string
564
	 */
565
	function woocommerce_product_loop_end( $echo = true ) {
566
		ob_start();
567
568
		wc_get_template( 'loop/loop-end.php' );
569
570
		if ( $echo )
571
			echo ob_get_clean();
572
		else
573
			return ob_get_clean();
574
	}
575
}
576
if (  ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
577
578
	/**
579
	 * Show the product title in the product loop. By default this is an H3.
580
	 */
581
	function woocommerce_template_loop_product_title() {
582
		echo '<h3>' . get_the_title() . '</h3>';
583
	}
584
}
585
if (  ! function_exists( 'woocommerce_template_loop_category_title' ) ) {
586
587
	/**
588
	 * Show the subcategory title in the product loop.
589
	 */
590
	function woocommerce_template_loop_category_title( $category ) {
591
		?>
592
		<h3>
593
			<?php
594
				echo $category->name;
595
596
				if ( $category->count > 0 )
597
					echo apply_filters( 'woocommerce_subcategory_count_html', ' <mark class="count">(' . $category->count . ')</mark>', $category );
598
			?>
599
		</h3>
600
		<?php
601
	}
602
}
603
/**
604
 * Insert the opening anchor tag for products in the loop.
605
 */
606
function woocommerce_template_loop_product_link_open() {
607
	echo '<a href="' . get_the_permalink() . '" class="woocommerce-LoopProduct-link">';
608
}
609
/**
610
 * Insert the opening anchor tag for products in the loop.
611
 */
612
function woocommerce_template_loop_product_link_close() {
613
	echo '</a>';
614
}
615
/**
616
 * Insert the opening anchor tag for categories in the loop.
617
 */
618
function woocommerce_template_loop_category_link_open( $category ) {
619
	echo '<a href="' . get_term_link( $category, 'product_cat' ) . '">';
620
}
621
/**
622
 * Insert the opening anchor tag for categories in the loop.
623
 */
624
function woocommerce_template_loop_category_link_close() {
625
	echo '</a>';
626
}
627
if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
628
629
	/**
630
	 * Show an archive description on taxonomy archives.
631
	 *
632
	 * @subpackage	Archives
633
	 */
634
	function woocommerce_taxonomy_archive_description() {
635
		if ( is_product_taxonomy() && 0 === absint( get_query_var( 'paged' ) ) ) {
636
			$description = wc_format_content( term_description() );
637
			if ( $description ) {
638
				echo '<div class="term-description">' . $description . '</div>';
639
			}
640
		}
641
	}
642
}
643
if ( ! function_exists( 'woocommerce_product_archive_description' ) ) {
644
645
	/**
646
	 * Show a shop page description on product archives.
647
	 *
648
	 * @subpackage	Archives
649
	 */
650
	function woocommerce_product_archive_description() {
651
		// Don't display the description on search results page
652
		if ( is_search() ) {
653
			return;
654
		}
655
656
		if ( is_post_type_archive( 'product' ) && 0 === absint( get_query_var( 'paged' ) ) ) {
657
			$shop_page   = get_post( wc_get_page_id( 'shop' ) );
658
			if ( $shop_page ) {
659
				$description = wc_format_content( $shop_page->post_content );
660
				if ( $description ) {
661
					echo '<div class="page-description">' . $description . '</div>';
662
				}
663
			}
664
		}
665
	}
666
}
667
668
if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
669
670
	/**
671
	 * Get the add to cart template for the loop.
672
	 *
673
	 * @subpackage	Loop
674
	 */
675
	function woocommerce_template_loop_add_to_cart( $args = array() ) {
676
		global $product;
677
678
		if ( $product ) {
679
			$defaults = array(
680
				'quantity' => 1,
681
				'class'    => implode( ' ', array_filter( array(
682
						'button',
683
						'product_type_' . $product->product_type,
684
						$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
685
						$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : ''
686
				) ) )
687
			);
688
689
			$args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product );
690
691
			wc_get_template( 'loop/add-to-cart.php', $args );
692
		}
693
	}
694
}
695
if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) {
696
697
	/**
698
	 * Get the product thumbnail for the loop.
699
	 *
700
	 * @subpackage	Loop
701
	 */
702
	function woocommerce_template_loop_product_thumbnail() {
703
		echo woocommerce_get_product_thumbnail();
704
	}
705
}
706
if ( ! function_exists( 'woocommerce_template_loop_price' ) ) {
707
708
	/**
709
	 * Get the product price for the loop.
710
	 *
711
	 * @subpackage	Loop
712
	 */
713
	function woocommerce_template_loop_price() {
714
		wc_get_template( 'loop/price.php' );
715
	}
716
}
717
if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) {
718
719
	/**
720
	 * Display the average rating in the loop.
721
	 *
722
	 * @subpackage	Loop
723
	 */
724
	function woocommerce_template_loop_rating() {
725
		wc_get_template( 'loop/rating.php' );
726
	}
727
}
728
if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) {
729
730
	/**
731
	 * Get the sale flash for the loop.
732
	 *
733
	 * @subpackage	Loop
734
	 */
735
	function woocommerce_show_product_loop_sale_flash() {
736
		wc_get_template( 'loop/sale-flash.php' );
737
	}
738
}
739
740
if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
741
742
	/**
743
	 * Get the product thumbnail, or the placeholder if not set.
744
	 *
745
	 * @subpackage	Loop
746
	 * @param string $size (default: 'shop_catalog')
747
	 * @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0)
748
	 * @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0)
749
	 * @return string
750
	 */
751
	function woocommerce_get_product_thumbnail( $size = 'shop_catalog', $deprecated1 = 0, $deprecated2 = 0 ) {
0 ignored issues
show
Unused Code introduced by
The parameter $deprecated1 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $deprecated2 is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
752
		global $post;
753
		$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
754
755
		if ( has_post_thumbnail() ) {
756
			$props = wc_get_product_attachment_props( get_post_thumbnail_id(), $post );
757
			return get_the_post_thumbnail( $post->ID, $image_size, array(
758
				'title'	 => $props['title'],
759
				'alt'    => $props['alt'],
760
			) );
761
		} elseif ( wc_placeholder_img_src() ) {
762
			return wc_placeholder_img( $image_size );
763
		}
764
	}
765
}
766
767
if ( ! function_exists( 'woocommerce_result_count' ) ) {
768
769
	/**
770
	 * Output the result count text (Showing x - x of x results).
771
	 *
772
	 * @subpackage	Loop
773
	 */
774
	function woocommerce_result_count() {
775
		wc_get_template( 'loop/result-count.php' );
776
	}
777
}
778
779
if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
780
781
	/**
782
	 * Output the product sorting options.
783
	 *
784
	 * @subpackage	Loop
785
	 */
786
	function woocommerce_catalog_ordering() {
787
		global $wp_query;
788
789
		if ( 1 === $wp_query->found_posts || ! woocommerce_products_will_display() ) {
790
			return;
791
		}
792
793
		$orderby                 = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
794
		$show_default_orderby    = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
795
		$catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array(
796
			'menu_order' => __( 'Default sorting', 'woocommerce' ),
797
			'popularity' => __( 'Sort by popularity', 'woocommerce' ),
798
			'rating'     => __( 'Sort by average rating', 'woocommerce' ),
799
			'date'       => __( 'Sort by newness', 'woocommerce' ),
800
			'price'      => __( 'Sort by price: low to high', 'woocommerce' ),
801
			'price-desc' => __( 'Sort by price: high to low', 'woocommerce' )
802
		) );
803
804
		if ( ! $show_default_orderby ) {
805
			unset( $catalog_orderby_options['menu_order'] );
806
		}
807
808
		if ( 'no' === get_option( 'woocommerce_enable_review_rating' ) ) {
809
			unset( $catalog_orderby_options['rating'] );
810
		}
811
812
		wc_get_template( 'loop/orderby.php', array( 'catalog_orderby_options' => $catalog_orderby_options, 'orderby' => $orderby, 'show_default_orderby' => $show_default_orderby ) );
813
	}
814
}
815
816
if ( ! function_exists( 'woocommerce_pagination' ) ) {
817
818
	/**
819
	 * Output the pagination.
820
	 *
821
	 * @subpackage	Loop
822
	 */
823
	function woocommerce_pagination() {
824
		wc_get_template( 'loop/pagination.php' );
825
	}
826
}
827
828
/** Single Product ********************************************************/
829
830
if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
831
832
	/**
833
	 * Output the product image before the single product summary.
834
	 *
835
	 * @subpackage	Product
836
	 */
837
	function woocommerce_show_product_images() {
838
		wc_get_template( 'single-product/product-image.php' );
839
	}
840
}
841
if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) {
842
843
	/**
844
	 * Output the product thumbnails.
845
	 *
846
	 * @subpackage	Product
847
	 */
848
	function woocommerce_show_product_thumbnails() {
849
		wc_get_template( 'single-product/product-thumbnails.php' );
850
	}
851
}
852
if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
853
854
	/**
855
	 * Output the product tabs.
856
	 *
857
	 * @subpackage	Product/Tabs
858
	 */
859
	function woocommerce_output_product_data_tabs() {
860
		wc_get_template( 'single-product/tabs/tabs.php' );
861
	}
862
}
863
if ( ! function_exists( 'woocommerce_template_single_title' ) ) {
864
865
	/**
866
	 * Output the product title.
867
	 *
868
	 * @subpackage	Product
869
	 */
870
	function woocommerce_template_single_title() {
871
		wc_get_template( 'single-product/title.php' );
872
	}
873
}
874
if ( ! function_exists( 'woocommerce_template_single_rating' ) ) {
875
876
	/**
877
	 * Output the product rating.
878
	 *
879
	 * @subpackage	Product
880
	 */
881
	function woocommerce_template_single_rating() {
882
		wc_get_template( 'single-product/rating.php' );
883
	}
884
}
885
if ( ! function_exists( 'woocommerce_template_single_price' ) ) {
886
887
	/**
888
	 * Output the product price.
889
	 *
890
	 * @subpackage	Product
891
	 */
892
	function woocommerce_template_single_price() {
893
		wc_get_template( 'single-product/price.php' );
894
	}
895
}
896
if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) {
897
898
	/**
899
	 * Output the product short description (excerpt).
900
	 *
901
	 * @subpackage	Product
902
	 */
903
	function woocommerce_template_single_excerpt() {
904
		wc_get_template( 'single-product/short-description.php' );
905
	}
906
}
907
if ( ! function_exists( 'woocommerce_template_single_meta' ) ) {
908
909
	/**
910
	 * Output the product meta.
911
	 *
912
	 * @subpackage	Product
913
	 */
914
	function woocommerce_template_single_meta() {
915
		wc_get_template( 'single-product/meta.php' );
916
	}
917
}
918
if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) {
919
920
	/**
921
	 * Output the product sharing.
922
	 *
923
	 * @subpackage	Product
924
	 */
925
	function woocommerce_template_single_sharing() {
926
		wc_get_template( 'single-product/share.php' );
927
	}
928
}
929
if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) {
930
931
	/**
932
	 * Output the product sale flash.
933
	 *
934
	 * @subpackage	Product
935
	 */
936
	function woocommerce_show_product_sale_flash() {
937
		wc_get_template( 'single-product/sale-flash.php' );
938
	}
939
}
940
941
if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) {
942
943
	/**
944
	 * Trigger the single product add to cart action.
945
	 *
946
	 * @subpackage	Product
947
	 */
948
	function woocommerce_template_single_add_to_cart() {
949
		global $product;
950
		do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );
951
	}
952
}
953
if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) {
954
955
	/**
956
	 * Output the simple product add to cart area.
957
	 *
958
	 * @subpackage	Product
959
	 */
960
	function woocommerce_simple_add_to_cart() {
961
		wc_get_template( 'single-product/add-to-cart/simple.php' );
962
	}
963
}
964
if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
965
966
	/**
967
	 * Output the grouped product add to cart area.
968
	 *
969
	 * @subpackage	Product
970
	 */
971
	function woocommerce_grouped_add_to_cart() {
972
		global $product;
973
974
		wc_get_template( 'single-product/add-to-cart/grouped.php', array(
975
			'grouped_product'    => $product,
976
			'grouped_products'   => $product->get_children(),
977
			'quantites_required' => false
978
		) );
979
	}
980
}
981
if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) {
982
983
	/**
984
	 * Output the variable product add to cart area.
985
	 *
986
	 * @subpackage	Product
987
	 */
988
	function woocommerce_variable_add_to_cart() {
989
		global $product;
990
991
		// Enqueue variation scripts
992
		wp_enqueue_script( 'wc-add-to-cart-variation' );
993
994
		// Get Available variations?
995
		$get_variations = sizeof( $product->get_children() ) <= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product );
996
997
		// Load the template
998
		wc_get_template( 'single-product/add-to-cart/variable.php', array(
999
			'available_variations' => $get_variations ? $product->get_available_variations() : false,
1000
			'attributes'           => $product->get_variation_attributes(),
1001
			'selected_attributes'  => $product->get_variation_default_attributes()
1002
		) );
1003
	}
1004
}
1005
if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) {
1006
1007
	/**
1008
	 * Output the external product add to cart area.
1009
	 *
1010
	 * @subpackage	Product
1011
	 */
1012
	function woocommerce_external_add_to_cart() {
1013
		global $product;
1014
1015
		if ( ! $product->add_to_cart_url() ) {
1016
			return;
1017
		}
1018
1019
		wc_get_template( 'single-product/add-to-cart/external.php', array(
1020
			'product_url' => $product->add_to_cart_url(),
1021
			'button_text' => $product->single_add_to_cart_text()
1022
		) );
1023
	}
1024
}
1025
1026
if ( ! function_exists( 'woocommerce_quantity_input' ) ) {
1027
1028
	/**
1029
	 * Output the quantity input for add to cart forms.
1030
	 *
1031
	 * @param  array $args Args for the input
1032
	 * @param  WC_Product|null $product
1033
	 * @param  boolean $echo Whether to return or echo|string
1034
	 */
1035
	function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
1036
		if ( is_null( $product ) ) {
1037
			$product = $GLOBALS['product'];
1038
		}
1039
1040
		$defaults = array(
1041
			'input_name'  => 'quantity',
1042
			'input_value' => '1',
1043
			'max_value'   => apply_filters( 'woocommerce_quantity_input_max', '', $product ),
1044
			'min_value'   => apply_filters( 'woocommerce_quantity_input_min', '', $product ),
1045
			'step'        => apply_filters( 'woocommerce_quantity_input_step', '1', $product ),
1046
			'pattern'     => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
1047
			'inputmode'   => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
1048
		);
1049
1050
		$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
1051
1052
		// Set min and max value to empty string if not set.
1053
		$args['min_value'] = isset( $args['min_value'] ) ? $args['min_value'] : '';
1054
		$args['max_value'] = isset( $args['max_value'] ) ? $args['max_value'] : '';
1055
1056
		// Apply sanity to min/max args - min cannot be lower than 0
1057
		if ( '' !== $args['min_value'] && is_numeric( $args['min_value'] ) && $args['min_value'] < 0 ) {
1058
			$args['min_value'] = 0; // Cannot be lower than 0
1059
		}
1060
1061
		// Max cannot be lower than 0 or min
1062
		if ( '' !== $args['max_value'] && is_numeric( $args['max_value'] ) ) {
1063
			$args['max_value'] = $args['max_value'] < 0 ? 0 : $args['max_value'];
1064
			$args['max_value'] = $args['max_value'] < $args['min_value'] ? $args['min_value'] : $args['max_value'];
1065
		}
1066
1067
		ob_start();
1068
1069
		wc_get_template( 'global/quantity-input.php', $args );
1070
1071
		if ( $echo ) {
1072
			echo ob_get_clean();
1073
		} else {
1074
			return ob_get_clean();
1075
		}
1076
	}
1077
}
1078
1079
if ( ! function_exists( 'woocommerce_product_description_tab' ) ) {
1080
1081
	/**
1082
	 * Output the description tab content.
1083
	 *
1084
	 * @subpackage	Product/Tabs
1085
	 */
1086
	function woocommerce_product_description_tab() {
1087
		wc_get_template( 'single-product/tabs/description.php' );
1088
	}
1089
}
1090
if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
1091
1092
	/**
1093
	 * Output the attributes tab content.
1094
	 *
1095
	 * @subpackage	Product/Tabs
1096
	 */
1097
	function woocommerce_product_additional_information_tab() {
1098
		wc_get_template( 'single-product/tabs/additional-information.php' );
1099
	}
1100
}
1101
if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
1102
1103
	/**
1104
	 * Output the reviews tab content.
1105
	 * @deprecated  2.4.0 Unused
1106
	 * @subpackage	Product/Tabs
1107
	 */
1108
	function woocommerce_product_reviews_tab() {
1109
		_deprecated_function( 'woocommerce_product_reviews_tab', '2.4', '' );
1110
	}
1111
}
1112
1113
if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
1114
1115
	/**
1116
	 * Add default product tabs to product pages.
1117
	 *
1118
	 * @param array $tabs
1119
	 * @return array
1120
	 */
1121
	function woocommerce_default_product_tabs( $tabs = array() ) {
1122
		global $product, $post;
1123
1124
		// Description tab - shows product content
1125
		if ( $post->post_content ) {
1126
			$tabs['description'] = array(
1127
				'title'    => __( 'Description', 'woocommerce' ),
1128
				'priority' => 10,
1129
				'callback' => 'woocommerce_product_description_tab'
1130
			);
1131
		}
1132
1133
		// Additional information tab - shows attributes
1134
		if ( $product && ( $product->has_attributes() || $product->enable_dimensions_display() ) ) {
1135
			$tabs['additional_information'] = array(
1136
				'title'    => __( 'Additional Information', 'woocommerce' ),
1137
				'priority' => 20,
1138
				'callback' => 'woocommerce_product_additional_information_tab'
1139
			);
1140
		}
1141
1142
		// Reviews tab - shows comments
1143
		if ( comments_open() ) {
1144
			$tabs['reviews'] = array(
1145
				'title'    => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ),
1146
				'priority' => 30,
1147
				'callback' => 'comments_template'
1148
			);
1149
		}
1150
1151
		return $tabs;
1152
	}
1153
}
1154
1155
if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) {
1156
1157
	/**
1158
	 * Sort tabs by priority.
1159
	 *
1160
	 * @param array $tabs
1161
	 * @return array
1162
	 */
1163
	function woocommerce_sort_product_tabs( $tabs = array() ) {
1164
1165
		// Make sure the $tabs parameter is an array
1166
		if ( ! is_array( $tabs ) ) {
1167
			trigger_error( "Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array." );
1168
			$tabs = array( );
1169
		}
1170
1171
		// Re-order tabs by priority
1172
		if ( ! function_exists( '_sort_priority_callback' ) ) {
1173
			function _sort_priority_callback( $a, $b ) {
1174
				if ( $a['priority'] === $b['priority'] )
1175
					return 0;
1176
				return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
1177
			}
1178
		}
1179
1180
		uasort( $tabs, '_sort_priority_callback' );
1181
1182
		return $tabs;
1183
	}
1184
}
1185
1186
if ( ! function_exists( 'woocommerce_comments' ) ) {
1187
1188
	/**
1189
	 * Output the Review comments template.
1190
	 *
1191
	 * @subpackage	Product
1192
	 * @param WP_Comment $comment
1193
	 * @param array $args
1194
	 * @param int $depth
1195
	 */
1196
	function woocommerce_comments( $comment, $args, $depth ) {
1197
		$GLOBALS['comment'] = $comment;
1198
		wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) );
1199
	}
1200
}
1201
1202
if ( ! function_exists( 'woocommerce_review_display_gravatar' ) ) {
1203
	/**
1204
	 * Display the review authors gravatar
1205
	 *
1206
	 * @param array $comment WP_Comment.
1207
	 * @return void
1208
	 */
1209
	function woocommerce_review_display_gravatar( $comment ) {
1210
		echo get_avatar( $comment, apply_filters( 'woocommerce_review_gravatar_size', '60' ), '' );
1211
	}
1212
}
1213
1214
if ( ! function_exists( 'woocommerce_review_display_rating' ) ) {
1215
	/**
1216
	 * Display the reviewers star rating
1217
	 *
1218
	 * @return void
1219
	 */
1220
	function woocommerce_review_display_rating() {
1221
		wc_get_template( 'single-product/review-rating.php' );
1222
	}
1223
}
1224
1225
if ( ! function_exists( 'woocommerce_review_display_meta' ) ) {
1226
	/**
1227
	 * Display the review authors meta (name, verified owner, review date)
1228
	 *
1229
	 * @return void
1230
	 */
1231
	function woocommerce_review_display_meta() {
1232
		wc_get_template( 'single-product/review-meta.php' );
1233
	}
1234
}
1235
1236
if ( ! function_exists( 'woocommerce_review_display_comment_text' ) ) {
1237
1238
	/**
1239
	 * Display the review content.
1240
	 */
1241
	function woocommerce_review_display_comment_text() {
1242
		echo '<div class="description">';
1243
		comment_text();
1244
		echo '</div>';
1245
	}
1246
}
1247
1248
if ( ! function_exists( 'woocommerce_output_related_products' ) ) {
1249
1250
	/**
1251
	 * Output the related products.
1252
	 *
1253
	 * @subpackage	Product
1254
	 */
1255
	function woocommerce_output_related_products() {
1256
1257
		$args = array(
1258
			'posts_per_page' 	=> 4,
1259
			'columns' 			=> 4,
1260
			'orderby' 			=> 'rand'
1261
		);
1262
1263
		woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) );
1264
	}
1265
}
1266
1267
if ( ! function_exists( 'woocommerce_related_products' ) ) {
1268
1269
	/**
1270
	 * Output the related products.
1271
	 *
1272
	 * @param array Provided arguments
1273
	 * @param bool Columns argument for backwards compat
1274
	 * @param bool Order by argument for backwards compat
1275
	 */
1276
	function woocommerce_related_products( $args = array(), $columns = false, $orderby = false ) {
1277
		if ( ! is_array( $args ) ) {
1278
			_deprecated_argument( __FUNCTION__, '2.1', __( 'Use $args argument as an array instead. Deprecated argument will be removed in WC 2.2.', 'woocommerce' ) );
1279
1280
			$argsvalue = $args;
1281
1282
			$args = array(
1283
				'posts_per_page' => $argsvalue,
1284
				'columns'        => $columns,
1285
				'orderby'        => $orderby,
1286
			);
1287
		}
1288
1289
		$defaults = array(
1290
			'posts_per_page' => 2,
1291
			'columns'        => 2,
1292
			'orderby'        => 'rand'
1293
		);
1294
1295
		$args = wp_parse_args( $args, $defaults );
1296
1297
		wc_get_template( 'single-product/related.php', $args );
1298
	}
1299
}
1300
1301
if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
1302
1303
	/**
1304
	 * Output product up sells.
1305
	 *
1306
	 * @param int $posts_per_page (default: -1)
1307
	 * @param int $columns (default: 4)
1308
	 * @param string $orderby (default: 'rand')
1309
	 */
1310
	function woocommerce_upsell_display( $posts_per_page = '-1', $columns = 4, $orderby = 'rand' ) {
1311
		$args = apply_filters( 'woocommerce_upsell_display_args', array(
1312
			'posts_per_page'	=> $posts_per_page,
1313
			'orderby'			=> apply_filters( 'woocommerce_upsells_orderby', $orderby ),
1314
			'columns'			=> $columns
1315
		) );
1316
1317
		wc_get_template( 'single-product/up-sells.php', $args );
1318
	}
1319
}
1320
1321
/** Cart ******************************************************************/
1322
1323
if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) {
1324
1325
	/**
1326
	 * Output the cart shipping calculator.
1327
	 *
1328
	 * @subpackage	Cart
1329
	 */
1330
	function woocommerce_shipping_calculator() {
1331
		wc_get_template( 'cart/shipping-calculator.php' );
1332
	}
1333
}
1334
1335
if ( ! function_exists( 'woocommerce_cart_totals' ) ) {
1336
1337
	/**
1338
	 * Output the cart totals.
1339
	 *
1340
	 * @subpackage	Cart
1341
	 */
1342
	function woocommerce_cart_totals() {
1343
		if ( is_checkout() ) {
1344
			return;
1345
		}
1346
		wc_get_template( 'cart/cart-totals.php' );
1347
	}
1348
}
1349
1350
if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
1351
1352
	/**
1353
	 * Output the cart cross-sells.
1354
	 *
1355
	 * @param  int $posts_per_page (default: 2)
1356
	 * @param  int $columns (default: 2)
1357
	 * @param  string $orderby (default: 'rand')
1358
	 */
1359
	function woocommerce_cross_sell_display( $posts_per_page = 2, $columns = 2, $orderby = 'rand' ) {
1360
		if ( is_checkout() ) {
1361
			return;
1362
		}
1363
		wc_get_template( 'cart/cross-sells.php', array(
1364
			'posts_per_page' => $posts_per_page,
1365
			'orderby'        => $orderby,
1366
			'columns'        => $columns
1367
		) );
1368
	}
1369
}
1370
1371
if ( ! function_exists( 'woocommerce_button_proceed_to_checkout' ) ) {
1372
1373
	/**
1374
	 * Output the proceed to checkout button.
1375
	 *
1376
	 * @subpackage	Cart
1377
	 */
1378
	function woocommerce_button_proceed_to_checkout() {
1379
		wc_get_template( 'cart/proceed-to-checkout-button.php' );
1380
	}
1381
}
1382
1383 View Code Duplication
if ( ! function_exists( 'woocommerce_widget_shopping_cart_button_view_cart' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1384
1385
	/**
1386
	 * Output the proceed to checkout button.
1387
	 *
1388
	 * @subpackage	Cart
1389
	 */
1390
	function woocommerce_widget_shopping_cart_button_view_cart() {
1391
		echo '<a href="' . esc_url( wc_get_cart_url() ) . '" class="button wc-forward">' . __( 'View Cart', 'woocommerce' ) . '</a>';
1392
	}
1393
}
1394
1395 View Code Duplication
if ( ! function_exists( 'woocommerce_widget_shopping_cart_proceed_to_checkout' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1396
1397
	/**
1398
	 * Output the proceed to checkout button.
1399
	 *
1400
	 * @subpackage	Cart
1401
	 */
1402
	function woocommerce_widget_shopping_cart_proceed_to_checkout() {
1403
		echo '<a href="' . esc_url( wc_get_checkout_url() ) . '" class="button checkout wc-forward">' . __( 'Checkout', 'woocommerce' ) . '</a>';
1404
	}
1405
}
1406
1407
/** Mini-Cart *************************************************************/
1408
1409
if ( ! function_exists( 'woocommerce_mini_cart' ) ) {
1410
1411
	/**
1412
	 * Output the Mini-cart - used by cart widget.
1413
	 *
1414
	 * @param array $args
1415
	 */
1416
	function woocommerce_mini_cart( $args = array() ) {
1417
1418
		$defaults = array(
1419
			'list_class' => ''
1420
		);
1421
1422
		$args = wp_parse_args( $args, $defaults );
1423
1424
		wc_get_template( 'cart/mini-cart.php', $args );
1425
	}
1426
}
1427
1428
/** Login *****************************************************************/
1429
1430
if ( ! function_exists( 'woocommerce_login_form' ) ) {
1431
1432
	/**
1433
	 * Output the WooCommerce Login Form.
1434
	 *
1435
	 * @subpackage	Forms
1436
	 * @param array $args
1437
	 */
1438
	function woocommerce_login_form( $args = array() ) {
1439
1440
		$defaults = array(
1441
			'message'  => '',
1442
			'redirect' => '',
1443
			'hidden'   => false
1444
		);
1445
1446
		$args = wp_parse_args( $args, $defaults  );
1447
1448
		wc_get_template( 'global/form-login.php', $args );
1449
	}
1450
}
1451
1452
if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) {
1453
1454
	/**
1455
	 * Output the WooCommerce Checkout Login Form.
1456
	 *
1457
	 * @subpackage	Checkout
1458
	 */
1459
	function woocommerce_checkout_login_form() {
1460
		wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) );
1461
	}
1462
}
1463
1464
if ( ! function_exists( 'woocommerce_breadcrumb' ) ) {
1465
1466
	/**
1467
	 * Output the WooCommerce Breadcrumb.
1468
	 *
1469
	 * @param array $args
1470
	 */
1471
	function woocommerce_breadcrumb( $args = array() ) {
1472
		$args = wp_parse_args( $args, apply_filters( 'woocommerce_breadcrumb_defaults', array(
1473
			'delimiter'   => '&nbsp;&#47;&nbsp;',
1474
			'wrap_before' => '<nav class="woocommerce-breadcrumb">',
1475
			'wrap_after'  => '</nav>',
1476
			'before'      => '',
1477
			'after'       => '',
1478
			'home'        => _x( 'Home', 'breadcrumb', 'woocommerce' )
1479
		) ) );
1480
1481
		$breadcrumbs = new WC_Breadcrumb();
1482
1483
		if ( ! empty( $args['home'] ) ) {
1484
			$breadcrumbs->add_crumb( $args['home'], apply_filters( 'woocommerce_breadcrumb_home_url', home_url() ) );
1485
		}
1486
1487
		$args['breadcrumb'] = $breadcrumbs->generate();
1488
1489
		/**
1490
		 * @hooked WC_Structured_Data::generate_breadcrumblist_data() - 10
1491
		 */
1492
		do_action( 'woocommerce_breadcrumb', $args );
1493
1494
		wc_get_template( 'global/breadcrumb.php', $args );
1495
	}
1496
}
1497
1498
if ( ! function_exists( 'woocommerce_order_review' ) ) {
1499
1500
	/**
1501
	 * Output the Order review table for the checkout.
1502
	 *
1503
	 * @subpackage	Checkout
1504
	 */
1505
	function woocommerce_order_review( $deprecated = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $deprecated is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1506
		wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
1507
	}
1508
}
1509
1510
if ( ! function_exists( 'woocommerce_checkout_payment' ) ) {
1511
1512
	/**
1513
	 * Output the Payment Methods on the checkout.
1514
	 *
1515
	 * @subpackage	Checkout
1516
	 */
1517
	function woocommerce_checkout_payment() {
1518
		if ( WC()->cart->needs_payment() ) {
1519
			$available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
1520
			WC()->payment_gateways()->set_current_gateway( $available_gateways );
1521
		} else {
1522
			$available_gateways = array();
1523
		}
1524
1525
		wc_get_template( 'checkout/payment.php', array(
1526
			'checkout'           => WC()->checkout(),
1527
			'available_gateways' => $available_gateways,
1528
			'order_button_text'  => apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) )
1529
		) );
1530
	}
1531
}
1532
1533
if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
1534
1535
	/**
1536
	 * Output the Coupon form for the checkout.
1537
	 *
1538
	 * @subpackage	Checkout
1539
	 */
1540
	function woocommerce_checkout_coupon_form() {
1541
		wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) );
1542
	}
1543
}
1544
1545
if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
1546
1547
	/**
1548
	 * Check if we will be showing products or not (and not sub-categories only).
1549
	 * @subpackage	Loop
1550
	 * @return bool
1551
	 */
1552
	function woocommerce_products_will_display() {
1553
		global $wpdb;
1554
1555
		if ( is_shop() ) {
1556
			return 'subcategories' !== get_option( 'woocommerce_shop_page_display' ) || is_search();
1557
		}
1558
1559
		if ( ! is_product_taxonomy() ) {
1560
			return false;
1561
		}
1562
1563
		if ( is_search() || is_filtered() || is_paged() ) {
1564
			return true;
1565
		}
1566
1567
		$term = get_queried_object();
1568
1569
		if ( is_product_category() ) {
1570
			switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
1571
				case 'subcategories' :
1572
					// Nothing - we want to continue to see if there are products/subcats
1573
				break;
1574
				case 'products' :
1575
				case 'both' :
1576
					return true;
1577
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1578
				default :
1579
					// Default - no setting
1580
					if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) {
1581
						return true;
1582
					}
1583
				break;
1584
			}
1585
		}
1586
1587
		// Begin subcategory logic
1588
		if ( empty( $term->term_id ) || empty( $term->taxonomy ) ) {
1589
			return true;
1590
		}
1591
1592
		$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
1593
1594
		if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) {
1595
			$has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) );
1596
1597
			if ( $has_children ) {
1598
				// Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
1599
				if ( sizeof( get_objects_in_term( $has_children, $term->taxonomy ) ) > 0 ) {
1600
					$products_will_display = false;
1601
				} else {
1602
					// If we get here, the parents were empty so we're forced to check children
1603
					foreach ( $has_children as $term_id ) {
1604
						$children = get_term_children( $term_id, $term->taxonomy );
1605
1606
						if ( sizeof( get_objects_in_term( $children, $term->taxonomy ) ) > 0 ) {
1607
							$products_will_display = false;
1608
							break;
1609
						}
1610
					}
1611
				}
1612
			} else {
1613
				$products_will_display = true;
1614
			}
1615
		}
1616
1617
		set_transient( $transient_name, $products_will_display, DAY_IN_SECONDS * 30 );
1618
1619
		return $products_will_display;
1620
	}
1621
}
1622
1623
if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
1624
1625
	/**
1626
	 * Display product sub categories as thumbnails.
1627
	 *
1628
	 * @subpackage	Loop
1629
	 * @param array $args
1630
	 * @return null|boolean
1631
	 */
1632
	function woocommerce_product_subcategories( $args = array() ) {
1633
		global $wp_query;
1634
1635
		$defaults = array(
1636
			'before'        => '',
1637
			'after'         => '',
1638
			'force_display' => false
1639
		);
1640
1641
		$args = wp_parse_args( $args, $defaults );
1642
1643
		extract( $args );
1644
1645
		// Main query only
1646
		if ( ! is_main_query() && ! $force_display ) {
1647
			return;
1648
		}
1649
1650
		// Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive
1651
		if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) {
1652
			return;
1653
		}
1654
1655
		// Check categories are enabled
1656
		if ( is_shop() && '' === get_option( 'woocommerce_shop_page_display' ) ) {
1657
			return;
1658
		}
1659
1660
		// Find the category + category parent, if applicable
1661
		$term 			= get_queried_object();
1662
		$parent_id 		= empty( $term->term_id ) ? 0 : $term->term_id;
1663
1664
		if ( is_product_category() ) {
1665
			$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1666
1667
			switch ( $display_type ) {
1668
				case 'products' :
1669
					return;
1670
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
1671
				case '' :
1672
					if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
1673
						return;
1674
					}
1675
				break;
1676
			}
1677
		}
1678
1679
		// NOTE: using child_of instead of parent - this is not ideal but due to a WP bug ( https://core.trac.wordpress.org/ticket/15626 ) pad_counts won't work
1680
		$product_categories = get_categories( apply_filters( 'woocommerce_product_subcategories_args', array(
1681
			'parent'       => $parent_id,
1682
			'menu_order'   => 'ASC',
1683
			'hide_empty'   => 0,
1684
			'hierarchical' => 1,
1685
			'taxonomy'     => 'product_cat',
1686
			'pad_counts'   => 1
1687
		) ) );
1688
1689
		if ( ! apply_filters( 'woocommerce_product_subcategories_hide_empty', false ) ) {
1690
			$product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' );
1691
		}
1692
1693
		if ( $product_categories ) {
1694
			echo $before;
1695
1696
			foreach ( $product_categories as $category ) {
1697
				wc_get_template( 'content-product_cat.php', array(
1698
					'category' => $category
1699
				) );
1700
			}
1701
1702
			// If we are hiding products disable the loop and pagination
1703
			if ( is_product_category() ) {
1704
				$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1705
1706
				switch ( $display_type ) {
1707
					case 'subcategories' :
1708
						$wp_query->post_count    = 0;
1709
						$wp_query->max_num_pages = 0;
1710
					break;
1711
					case '' :
1712
						if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) {
1713
							$wp_query->post_count    = 0;
1714
							$wp_query->max_num_pages = 0;
1715
						}
1716
					break;
1717
				}
1718
			}
1719
1720
			if ( is_shop() && 'subcategories' === get_option( 'woocommerce_shop_page_display' ) ) {
1721
				$wp_query->post_count    = 0;
1722
				$wp_query->max_num_pages = 0;
1723
			}
1724
1725
			echo $after;
1726
1727
			return true;
1728
		}
1729
	}
1730
}
1731
1732
if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
1733
1734
	/**
1735
	 * Show subcategory thumbnails.
1736
	 *
1737
	 * @param mixed $category
1738
	 * @subpackage	Loop
1739
	 */
1740
	function woocommerce_subcategory_thumbnail( $category ) {
1741
		$small_thumbnail_size  	= apply_filters( 'subcategory_archive_thumbnail_size', 'shop_catalog' );
1742
		$dimensions    			= wc_get_image_size( $small_thumbnail_size );
1743
		$thumbnail_id  			= get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true  );
1744
1745
		if ( $thumbnail_id ) {
1746
			$image        = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size  );
1747
			$image        = $image[0];
1748
			$image_srcset = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $thumbnail_id, $small_thumbnail_size ) : false;
1749
			$image_sizes  = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $small_thumbnail_size ) : false;
1750
		} else {
1751
			$image        = wc_placeholder_img_src();
1752
			$image_srcset = $image_sizes = false;
1753
		}
1754
1755
		if ( $image ) {
1756
			// Prevent esc_url from breaking spaces in urls for image embeds
1757
			// Ref: https://core.trac.wordpress.org/ticket/23605
1758
			$image = str_replace( ' ', '%20', $image );
1759
1760
			// Add responsive image markup if available
1761
			if ( $image_srcset && $image_sizes ) {
1762
				echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" srcset="' . esc_attr( $image_srcset ) . '" sizes="' . esc_attr( $image_sizes ) . '" />';
1763
			} else {
1764
				echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
1765
			}
1766
		}
1767
	}
1768
}
1769
1770
if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
1771
1772
	/**
1773
	 * Displays order details in a table.
1774
	 *
1775
	 * @param mixed $order_id
1776
	 * @subpackage	Orders
1777
	 */
1778
	function woocommerce_order_details_table( $order_id ) {
1779
		if ( ! $order_id ) return;
1780
1781
		wc_get_template( 'order/order-details.php', array(
1782
			'order_id' => $order_id
1783
		) );
1784
	}
1785
}
1786
1787
1788
if ( ! function_exists( 'woocommerce_order_again_button' ) ) {
1789
1790
	/**
1791
	 * Display an 'order again' button on the view order page.
1792
	 *
1793
	 * @param object $order
1794
	 * @subpackage	Orders
1795
	 */
1796
	function woocommerce_order_again_button( $order ) {
1797
		if ( ! $order || ! $order->has_status( 'completed' ) || ! is_user_logged_in() ) {
1798
			return;
1799
		}
1800
1801
		wc_get_template( 'order/order-again.php', array(
1802
			'order' => $order
1803
		) );
1804
	}
1805
}
1806
1807
/** Forms ****************************************************************/
1808
1809
if ( ! function_exists( 'woocommerce_form_field' ) ) {
1810
1811
	/**
1812
	 * Outputs a checkout/address form field.
1813
	 *
1814
	 * @subpackage	Forms
1815
	 * @param string $key
1816
	 * @param mixed $args
1817
	 * @param string $value (default: null)
1818
	 * @todo This function needs to be broken up in smaller pieces
1819
	 */
1820
	function woocommerce_form_field( $key, $args, $value = null ) {
1821
		$defaults = array(
1822
			'type'              => 'text',
1823
			'label'             => '',
1824
			'description'       => '',
1825
			'placeholder'       => '',
1826
			'maxlength'         => false,
1827
			'required'          => false,
1828
			'autocomplete'      => false,
1829
			'id'                => $key,
1830
			'class'             => array(),
1831
			'label_class'       => array(),
1832
			'input_class'       => array(),
1833
			'return'            => false,
1834
			'options'           => array(),
1835
			'custom_attributes' => array(),
1836
			'validate'          => array(),
1837
			'default'           => '',
1838
		);
1839
1840
		$args = wp_parse_args( $args, $defaults );
1841
		$args = apply_filters( 'woocommerce_form_field_args', $args, $key, $value );
1842
1843
		if ( $args['required'] ) {
1844
			$args['class'][] = 'validate-required';
1845
			$required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce'  ) . '">*</abbr>';
1846
		} else {
1847
			$required = '';
1848
		}
1849
1850
		$args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
1851
1852
		$args['autocomplete'] = ( $args['autocomplete'] ) ? 'autocomplete="' . esc_attr( $args['autocomplete'] ) . '"' : '';
1853
1854
		if ( is_string( $args['label_class'] ) ) {
1855
			$args['label_class'] = array( $args['label_class'] );
1856
		}
1857
1858
		if ( is_null( $value ) ) {
1859
			$value = $args['default'];
1860
		}
1861
1862
		// Custom attribute handling
1863
		$custom_attributes = array();
1864
1865 View Code Duplication
		if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1866
			foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
1867
				$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
1868
			}
1869
		}
1870
1871
		if ( ! empty( $args['validate'] ) ) {
1872
			foreach( $args['validate'] as $validate ) {
0 ignored issues
show
Bug introduced by
The expression $args['validate'] of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1873
				$args['class'][] = 'validate-' . $validate;
1874
			}
1875
		}
1876
1877
		$field = '';
1878
		$label_id = $args['id'];
1879
		$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
1880
1881
		switch ( $args['type'] ) {
1882
			case 'country' :
1883
1884
				$countries = 'shipping_country' === $key ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
1885
1886
				if ( 1 === sizeof( $countries ) ) {
1887
1888
					$field .= '<strong>' . current( array_values( $countries ) ) . '</strong>';
1889
1890
					$field .= '<input type="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . current( array_keys($countries ) ) . '" ' . implode( ' ', $custom_attributes ) . ' class="country_to_state" />';
1891
1892
				} else {
1893
1894
					$field = '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" ' . $args['autocomplete'] . ' class="country_to_state country_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" ' . implode( ' ', $custom_attributes ) . '>'
1895
							. '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
1896
1897 View Code Duplication
					foreach ( $countries as $ckey => $cvalue ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1898
						$field .= '<option value="' . esc_attr( $ckey ) . '" '. selected( $value, $ckey, false ) . '>'. __( $cvalue, 'woocommerce' ) .'</option>';
1899
					}
1900
1901
					$field .= '</select>';
1902
1903
					$field .= '<noscript><input type="submit" name="woocommerce_checkout_update_totals" value="' . esc_attr__( 'Update country', 'woocommerce' ) . '" /></noscript>';
1904
1905
				}
1906
1907
				break;
1908
			case 'state' :
1909
1910
				/* Get Country */
1911
				$country_key = 'billing_state' === $key ? 'billing_country' : 'shipping_country';
1912
				$current_cc  = WC()->checkout->get_value( $country_key );
1913
				$states      = WC()->countries->get_states( $current_cc );
1914
1915
				if ( is_array( $states ) && empty( $states ) ) {
1916
1917
					$field_container = '<p class="form-row %1$s" id="%2$s" style="display: none">%3$s</p>';
1918
1919
					$field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key )  . '" id="' . esc_attr( $args['id'] ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
1920
1921
				} elseif ( is_array( $states ) ) {
1922
1923
					$field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['autocomplete'] . '>
1924
						<option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
1925
1926 View Code Duplication
					foreach ( $states as $ckey => $cvalue ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1927
						$field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
1928
					}
1929
1930
					$field .= '</select>';
1931
1932
				} else {
1933
1934
					$field .= '<input type="text" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" value="' . esc_attr( $value ) . '"  placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['autocomplete'] . ' name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
1935
1936
				}
1937
1938
				break;
1939
			case 'textarea' :
1940
1941
				$field .= '<textarea name="' . esc_attr( $key ) . '" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['maxlength'] . ' ' . $args['autocomplete'] . ' ' . ( empty( $args['custom_attributes']['rows'] ) ? ' rows="2"' : '' ) . ( empty( $args['custom_attributes']['cols'] ) ? ' cols="5"' : '' ) . implode( ' ', $custom_attributes ) . '>'. esc_textarea( $value  ) .'</textarea>';
1942
1943
				break;
1944 View Code Duplication
			case 'checkbox' :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1945
1946
				$field = '<label class="checkbox ' . implode( ' ', $args['label_class'] ) .'" ' . implode( ' ', $custom_attributes ) . '>
1947
						<input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" '.checked( $value, 1, false ) .' /> '
1948
						 . $args['label'] . $required . '</label>';
1949
1950
				break;
1951
			case 'password' :
1952
			case 'text' :
1953
			case 'email' :
1954
			case 'tel' :
1955 View Code Duplication
			case 'number' :
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1956
1957
				$field .= '<input type="' . esc_attr( $args['type'] ) . '" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['maxlength'] . ' ' . $args['autocomplete'] . ' value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
1958
1959
				break;
1960
			case 'select' :
1961
1962
				$options = $field = '';
1963
1964
				if ( ! empty( $args['options'] ) ) {
1965
					foreach ( $args['options'] as $option_key => $option_text ) {
1966
						if ( '' === $option_key ) {
1967
							// If we have a blank option, select2 needs a placeholder
1968
							if ( empty( $args['placeholder'] ) ) {
1969
								$args['placeholder'] = $option_text ? $option_text : __( 'Choose an option', 'woocommerce' );
1970
							}
1971
							$custom_attributes[] = 'data-allow_clear="true"';
1972
						}
1973
						$options .= '<option value="' . esc_attr( $option_key ) . '" '. selected( $value, $option_key, false ) . '>' . esc_attr( $option_text ) .'</option>';
1974
					}
1975
1976
					$field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="select '. esc_attr( implode( ' ', $args['input_class'] ) ) . '" ' . implode( ' ', $custom_attributes ) . ' data-placeholder="' . esc_attr( $args['placeholder'] ) . '" ' . $args['autocomplete'] . '>
1977
							' . $options . '
1978
						</select>';
1979
				}
1980
1981
				break;
1982
			case 'radio' :
1983
1984
				$label_id = current( array_keys( $args['options'] ) );
1985
1986
				if ( ! empty( $args['options'] ) ) {
1987
					foreach ( $args['options'] as $option_key => $option_text ) {
0 ignored issues
show
Bug introduced by
The expression $args['options'] of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1988
						$field .= '<input type="radio" class="input-radio ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" value="' . esc_attr( $option_key ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '"' . checked( $value, $option_key, false ) . ' />';
1989
						$field .= '<label for="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" class="radio ' . implode( ' ', $args['label_class'] ) .'">' . $option_text . '</label>';
1990
					}
1991
				}
1992
1993
				break;
1994
		}
1995
1996
		if ( ! empty( $field ) ) {
1997
			$field_html = '';
1998
1999
			if ( $args['label'] && 'checkbox' != $args['type'] ) {
2000
				$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) .'">' . $args['label'] . $required . '</label>';
2001
			}
2002
2003
			$field_html .= $field;
2004
2005
			if ( $args['description'] ) {
2006
				$field_html .= '<span class="description">' . esc_html( $args['description'] ) . '</span>';
2007
			}
2008
2009
			$container_class = 'form-row ' . esc_attr( implode( ' ', $args['class'] ) );
2010
			$container_id = esc_attr( $args['id'] ) . '_field';
2011
2012
			$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
2013
2014
			$field = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
2015
		}
2016
2017
		$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );
2018
2019
		if ( $args['return'] ) {
2020
			return $field;
2021
		} else {
2022
			echo $field;
2023
		}
2024
	}
2025
}
2026
2027
if ( ! function_exists( 'get_product_search_form' ) ) {
2028
2029
	/**
2030
	 * Display product search form.
2031
	 *
2032
	 * Will first attempt to locate the product-searchform.php file in either the child or.
2033
	 * the parent, then load it. If it doesn't exist, then the default search form.
2034
	 * will be displayed.
2035
	 *
2036
	 * The default searchform uses html5.
2037
	 *
2038
	 * @subpackage	Forms
2039
	 * @param bool $echo (default: true)
2040
	 * @return string
2041
	 */
2042
	function get_product_search_form( $echo = true  ) {
2043
		global $product_search_form_index;
2044
2045
		ob_start();
2046
2047
		if ( empty( $product_search_form_index ) ) {
2048
			$product_search_form_index = 0;
2049
		}
2050
2051
		do_action( 'pre_get_product_search_form'  );
2052
2053
		wc_get_template( 'product-searchform.php', array(
2054
			'index' => $product_search_form_index++,
2055
		) );
2056
2057
		$form = apply_filters( 'get_product_search_form', ob_get_clean() );
2058
2059
		if ( $echo ) {
2060
			echo $form;
2061
		} else {
2062
			return $form;
2063
		}
2064
	}
2065
}
2066
2067
if ( ! function_exists( 'woocommerce_output_auth_header' ) ) {
2068
2069
	/**
2070
	 * Output the Auth header.
2071
	 */
2072
	function woocommerce_output_auth_header() {
2073
		wc_get_template( 'auth/header.php' );
2074
	}
2075
}
2076
2077
if ( ! function_exists( 'woocommerce_output_auth_footer' ) ) {
2078
2079
	/**
2080
	 * Output the Auth footer.
2081
	 */
2082
	function woocommerce_output_auth_footer() {
2083
		wc_get_template( 'auth/footer.php' );
2084
	}
2085
}
2086
2087
if ( ! function_exists( 'woocommerce_single_variation' ) ) {
2088
2089
	/**
2090
	 * Output placeholders for the single variation.
2091
	 */
2092
	function woocommerce_single_variation() {
2093
		echo '<div class="woocommerce-variation single_variation"></div>';
2094
	}
2095
}
2096
2097
if ( ! function_exists( 'woocommerce_single_variation_add_to_cart_button' ) ) {
2098
2099
	/**
2100
	 * Output the add to cart button for variations.
2101
	 */
2102
	function woocommerce_single_variation_add_to_cart_button() {
2103
		wc_get_template( 'single-product/add-to-cart/variation-add-to-cart-button.php' );
2104
	}
2105
}
2106
2107
if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
2108
2109
	/**
2110
	 * Output a list of variation attributes for use in the cart forms.
2111
	 *
2112
	 * @param array $args
2113
	 * @since 2.4.0
2114
	 */
2115
	function wc_dropdown_variation_attribute_options( $args = array() ) {
2116
		$args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array(
2117
			'options'          => false,
2118
			'attribute'        => false,
2119
			'product'          => false,
2120
			'selected' 	       => false,
2121
			'name'             => '',
2122
			'id'               => '',
2123
			'class'            => '',
2124
			'show_option_none' => __( 'Choose an option', 'woocommerce' )
2125
		) );
2126
2127
		$options   = $args['options'];
2128
		$product   = $args['product'];
2129
		$attribute = $args['attribute'];
2130
		$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
2131
		$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );
2132
		$class     = $args['class'];
2133
2134
		if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
2135
			$attributes = $product->get_variation_attributes();
2136
			$options    = $attributes[ $attribute ];
2137
		}
2138
2139
		$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '">';
2140
2141
		if ( $args['show_option_none'] ) {
2142
			$html .= '<option value="">' . esc_html( $args['show_option_none'] ) . '</option>';
2143
		}
2144
2145
		if ( ! empty( $options ) ) {
2146
			if ( $product && taxonomy_exists( $attribute ) ) {
2147
				// Get terms if this is a taxonomy - ordered. We need the names too.
2148
				$terms = wc_get_product_terms( $product->id, $attribute, array( 'fields' => 'all' ) );
2149
2150 View Code Duplication
				foreach ( $terms as $term ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2151
					if ( in_array( $term->slug, $options ) ) {
2152
						$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>';
2153
					}
2154
				}
2155
			} else {
2156
				foreach ( $options as $option ) {
2157
					// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
2158
					$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
2159
					$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
2160
				}
2161
			}
2162
		}
2163
2164
		$html .= '</select>';
2165
2166
		echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
2167
	}
2168
}
2169
2170
if ( ! function_exists( 'woocommerce_account_content' ) ) {
2171
2172
	/**
2173
	 * My Account content output.
2174
	 */
2175
	function woocommerce_account_content() {
2176
		global $wp;
2177
2178
		foreach ( $wp->query_vars as $key => $value ) {
2179
			// Ignore pagename param.
2180
			if ( 'pagename' === $key ) {
2181
				continue;
2182
			}
2183
2184
			if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
2185
				do_action( 'woocommerce_account_' . $key . '_endpoint', $value );
2186
				return;
2187
			}
2188
		}
2189
2190
		// No endpoint found? Default to dashboard.
2191
		wc_get_template( 'myaccount/dashboard.php', array(
2192
			'current_user' => get_user_by( 'id', get_current_user_id() ),
2193
		) );
2194
	}
2195
}
2196
2197
if ( ! function_exists( 'woocommerce_account_navigation' ) ) {
2198
2199
	/**
2200
	 * My Account navigation template.
2201
	 */
2202
	function woocommerce_account_navigation() {
2203
		wc_get_template( 'myaccount/navigation.php' );
2204
	}
2205
}
2206
2207
if ( ! function_exists( 'woocommerce_account_orders' ) ) {
2208
2209
	/**
2210
	 * My Account > Orders template.
2211
	 *
2212
	 * @param int $current_page Current page number.
2213
	 */
2214
	function woocommerce_account_orders( $current_page ) {
2215
		$current_page    = empty( $current_page ) ? 1 : absint( $current_page );
2216
		$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 'customer' => get_current_user_id(), 'page' => $current_page, 'paginate' => true ) ) );
2217
2218
		wc_get_template(
2219
			'myaccount/orders.php',
2220
			array(
2221
				'current_page' => absint( $current_page ),
2222
				'customer_orders' => $customer_orders,
2223
				'has_orders' => 0 < $customer_orders->total,
2224
			)
2225
		);
2226
	}
2227
}
2228
2229
if ( ! function_exists( 'woocommerce_account_view_order' ) ) {
2230
2231
	/**
2232
	 * My Account > View order template.
2233
	 *
2234
	 * @param int $order_id Order ID.
2235
	 */
2236
	function woocommerce_account_view_order( $order_id ) {
2237
		WC_Shortcode_My_Account::view_order( absint( $order_id ) );
2238
	}
2239
}
2240
2241
if ( ! function_exists( 'woocommerce_account_downloads' ) ) {
2242
2243
	/**
2244
	 * My Account > Downloads template.
2245
	 */
2246
	function woocommerce_account_downloads() {
2247
		wc_get_template( 'myaccount/downloads.php' );
2248
	}
2249
}
2250
2251
if ( ! function_exists( 'woocommerce_account_edit_address' ) ) {
2252
2253
	/**
2254
	 * My Account > Edit address template.
2255
	 *
2256
	 * @param string $type Address type.
2257
	 */
2258
	function woocommerce_account_edit_address( $type ) {
2259
		$type = wc_edit_address_i18n( sanitize_title( $type ), true );
2260
2261
		WC_Shortcode_My_Account::edit_address( $type );
2262
	}
2263
}
2264
2265
if ( ! function_exists( 'woocommerce_account_payment_methods' ) ) {
2266
2267
	/**
2268
	 * My Account > Downloads template.
2269
	 */
2270
	function woocommerce_account_payment_methods() {
2271
		wc_get_template( 'myaccount/payment-methods.php' );
2272
	}
2273
}
2274
2275
if ( ! function_exists( 'woocommerce_account_add_payment_method' ) ) {
2276
2277
	/**
2278
	 * My Account > Add payment method template.
2279
	 */
2280
	function woocommerce_account_add_payment_method() {
2281
		WC_Shortcode_My_Account::add_payment_method();
2282
	}
2283
}
2284
2285
if ( ! function_exists( 'woocommerce_account_edit_account' ) ) {
2286
2287
	/**
2288
	 * My Account > Edit account template.
2289
	 */
2290
	function woocommerce_account_edit_account() {
2291
		WC_Shortcode_My_Account::edit_account();
2292
	}
2293
}
2294
2295
if ( ! function_exists( 'wc_no_products_found' ) ) {
2296
2297
	/**
2298
	 * Show no products found message.
2299
	 */
2300
	function wc_no_products_found() {
2301
		wc_get_template( 'loop/no-products-found.php' );
2302
	}
2303
}
2304
2305
2306
if ( ! function_exists( 'wc_get_email_order_items' ) ) {
2307
	/**
2308
	 * Get HTML for the order items to be shown in emails.
2309
	 * @param WC_Order $order
2310
	 * @param array $args
2311
	 * @since 2.7.0
2312
	 */
2313
	function wc_get_email_order_items( $order, $args = array() ) {
2314
		ob_start();
2315
2316
		$defaults = array(
2317
			'show_sku'      => false,
2318
			'show_image'    => false,
2319
			'image_size'    => array( 32, 32 ),
2320
			'plain_text'    => false,
2321
			'sent_to_admin' => false,
2322
		);
2323
2324
		$args     = wp_parse_args( $args, $defaults );
2325
		$template = $args['plain_text'] ? 'emails/plain/email-order-items.php' : 'emails/email-order-items.php';
2326
2327
		wc_get_template( $template, array(
2328
			'order'               => $order,
2329
			'items'               => $order->get_items(),
2330
			'show_download_links' => $order->is_download_permitted(),
2331
			'show_sku'            => $args['show_sku'],
2332
			'show_purchase_note'  => $order->is_paid(),
2333
			'show_image'          => $args['show_image'],
2334
			'image_size'          => $args['image_size'],
2335
			'plain_text'          => $args['plain_text'],
2336
			'sent_to_admin'       => $args['sent_to_admin'],
2337
		) );
2338
2339
		return apply_filters( 'woocommerce_email_order_items_table', ob_get_clean(), $order );
2340
	}
2341
}
2342
2343
if ( ! function_exists( 'wc_display_item_meta' ) ) {
2344
	/**
2345
	 * Display item meta data.
2346
	 * @since  2.7.0
2347
	 * @param  WC_Item $item
2348
	 * @param  array   $args
2349
	 * @return string|void
2350
	 */
2351
	function wc_display_item_meta( $item, $args = array() ) {
2352
		$strings = array();
2353
		$html    = '';
2354
		$args    = wp_parse_args( $args, array(
2355
			'before'    => '<ul class="wc-item-meta"><li>',
2356
			'after'     => '</li></ul>',
2357
			'separator' => '</li><li>',
2358
			'echo'      => true,
2359
			'autop'     => false,
2360
		) );
2361
2362
		foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) {
2363
			if ( '_' === substr( $meta->key, 0, 1 ) ) {
2364
				continue;
2365
			}
2366
			$value = $args['autop'] ? wp_kses_post( wpautop( make_clickable( $meta->display_value ) ) ) : wp_kses_post( make_clickable( $meta->display_value ) );
2367
			$strings[] = '<strong class="wc-item-meta-label">' . wp_kses_post( $meta->display_key ) . ':</strong> ' . $value;
2368
		}
2369
2370 View Code Duplication
		if ( $strings ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $strings of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2371
			$html = $args['before'] . implode( $args['separator'], $strings ) . $args['after'];
2372
		}
2373
2374
		$html = apply_filters( 'woocommerce_display_item_meta', $html, $item, $args );
2375
2376
		if ( $args['echo'] ) {
2377
			echo $html;
2378
		} else {
2379
			return $html;
2380
		}
2381
	}
2382
}
2383
2384
if ( ! function_exists( 'wc_display_item_downloads' ) ) {
2385
	/**
2386
	 * Display item download links.
2387
	 * @since  2.7.0
2388
	 * @param  WC_Item $item
2389
	 * @param  array   $args
2390
	 * @return string|void
2391
	 */
2392
	function wc_display_item_downloads( $item, $args = array() ) {
2393
		$strings = array();
2394
		$html    = '';
2395
		$args    = wp_parse_args( $args, array(
2396
			'before'    => '<ul class ="wc-item-downloads"><li>',
2397
			'after'     => '</li></ul>',
2398
			'separator' => '</li><li>',
2399
			'echo'      => true,
2400
			'show_url'  => false,
2401
		) );
2402
2403
		if ( is_object( $item ) && $item->is_type( 'line_item' ) && ( $downloads = $item->get_item_downloads() ) ) {
2404
			$i = 0;
2405
			foreach ( $downloads as $file ) {
2406
				$i ++;
2407
2408
				if ( $args['show_url'] ) {
2409
					$strings[] = '<strong class="wc-item-download-label">' .  esc_html( $file['name'] ) . ':</strong> ' . esc_html( $file['download_url'] );
2410
				} else {
2411
					$prefix = sizeof( $downloads ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' );
2412
					$strings[] = '<strong class="wc-item-download-label">' . $prefix . ':</strong> <a href="' . esc_url( $file['download_url'] ) . '" target="_blank">' . esc_html( $file['name'] ) . '</a>';
2413
				}
2414
			}
2415
		}
2416
2417 View Code Duplication
		if ( $strings ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $strings of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2418
			$html = $args['before'] . implode( $args['separator'], $strings ) . $args['after'];
2419
		}
2420
2421
		$html = apply_filters( 'woocommerce_display_item_downloads', $html, $item, $args );
2422
2423
		if ( $args['echo'] ) {
2424
			echo $html;
2425
		} else {
2426
			return $html;
2427
		}
2428
	}
2429
}
2430