Completed
Pull Request — master (#11455)
by
unknown
07:40
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()->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
 * When the_post is called, put product data into a global.
100
 *
101
 * @param mixed $post
102
 * @return WC_Product
103
 */
104
function wc_setup_product_data( $post ) {
105
	unset( $GLOBALS['product'] );
106
107
	if ( is_int( $post ) )
108
		$post = get_post( $post );
109
110
	if ( empty( $post->post_type ) || ! in_array( $post->post_type, array( 'product', 'product_variation' ) ) )
111
		return;
112
113
	$GLOBALS['product'] = wc_get_product( $post );
114
115
	return $GLOBALS['product'];
116
}
117
add_action( 'the_post', 'wc_setup_product_data' );
118
119
if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
120
121
	/**
122
	 * Reset the loop's index and columns when we're done outputting a product loop.
123
	 * @subpackage	Loop
124
	 */
125
	function woocommerce_reset_loop() {
126
		$GLOBALS['woocommerce_loop'] = array(
127
			'loop'    => '',
128
			'columns' => '',
129
			'name'    => '',
130
		);
131
	}
132
}
133
add_filter( 'loop_end', 'woocommerce_reset_loop' );
134
135
/**
136
 * Products RSS Feed.
137
 * @deprecated 2.6
138
 * @access public
139
 */
140
function wc_products_rss_feed() {
141
	// Product RSS
142
	if ( is_post_type_archive( 'product' ) || is_singular( 'product' ) ) {
143
144
		$feed = get_post_type_archive_feed_link( 'product' );
145
146
		echo '<link rel="alternate" type="application/rss+xml"  title="' . esc_attr__( 'New products', 'woocommerce' ) . '" href="' . esc_url( $feed ) . '" />';
147
148
	} elseif ( is_tax( 'product_cat' ) ) {
149
150
		$term = get_term_by( 'slug', esc_attr( get_query_var('product_cat') ), 'product_cat' );
151
152 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...
153
			$feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) );
154
			echo '<link rel="alternate" type="application/rss+xml"  title="' . esc_attr( sprintf( __( 'New products added to %s', 'woocommerce' ), $term->name ) ) . '" href="' . esc_url( $feed ) . '" />';
155
		}
156
157
	} elseif ( is_tax( 'product_tag' ) ) {
158
159
		$term = get_term_by('slug', esc_attr( get_query_var('product_tag') ), 'product_tag');
160
161 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...
162
			$feed = add_query_arg('product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ));
163
			echo '<link rel="alternate" type="application/rss+xml"  title="' . sprintf(__( 'New products tagged %s', 'woocommerce' ), urlencode($term->name)) . '" href="' . esc_url( $feed ) . '" />';
164
		}
165
	}
166
}
167
168
/**
169
 * Output generator tag to aid debugging.
170
 *
171
 * @access public
172
 */
173
function wc_generator_tag( $gen, $type ) {
174
	switch ( $type ) {
175
		case 'html':
176
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '">';
177
			break;
178
		case 'xhtml':
179
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '" />';
180
			break;
181
	}
182
	return $gen;
183
}
184
185
/**
186
 * Add body classes for WC pages.
187
 *
188
 * @param  array $classes
189
 * @return array
190
 */
191
function wc_body_class( $classes ) {
192
	$classes = (array) $classes;
193
194
	if ( is_woocommerce() ) {
195
		$classes[] = 'woocommerce';
196
		$classes[] = 'woocommerce-page';
197
	}
198
199
	elseif ( is_checkout() ) {
200
		$classes[] = 'woocommerce-checkout';
201
		$classes[] = 'woocommerce-page';
202
	}
203
204
	elseif ( is_cart() ) {
205
		$classes[] = 'woocommerce-cart';
206
		$classes[] = 'woocommerce-page';
207
	}
208
209
	elseif ( is_account_page() ) {
210
		$classes[] = 'woocommerce-account';
211
		$classes[] = 'woocommerce-page';
212
	}
213
214
	if ( is_store_notice_showing() ) {
215
		$classes[] = 'woocommerce-demo-store';
216
	}
217
218
	foreach ( WC()->query->query_vars as $key => $value ) {
219
		if ( is_wc_endpoint_url( $key ) ) {
220
			$classes[] = 'woocommerce-' . sanitize_html_class( $key );
221
		}
222
	}
223
224
	return array_unique( $classes );
225
}
226
227
/**
228
 * Display the classes for the product cat div.
229
 *
230
 * @since 2.4.0
231
 * @param string|array $class One or more classes to add to the class list.
232
 * @param object $category object Optional.
233
 */
234
function wc_product_cat_class( $class = '', $category = null ) {
235
	// Separates classes with a single space, collates classes for post DIV
236
	echo 'class="' . esc_attr( join( ' ', wc_get_product_cat_class( $class, $category ) ) ) . '"';
237
}
238
239
/**
240
 * Get classname for loops based on $woocommerce_loop global.
241
 * @since 2.6.0
242
 * @return string
243
 */
244
function wc_get_loop_class() {
245
	global $woocommerce_loop;
246
247
	$woocommerce_loop['loop']    = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1   : 1;
248
	$woocommerce_loop['columns'] = ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 );
249
250
	if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
251
		return 'first';
252
	} elseif ( 0 === $woocommerce_loop['loop'] % $woocommerce_loop['columns'] ) {
253
		return 'last';
254
	} else {
255
		return '';
256
	}
257
}
258
259
/**
260
 * Get the classes for the product cat div.
261
 *
262
 * @since 2.4.0
263
 * @param string|array $class One or more classes to add to the class list.
264
 * @param object $category object Optional.
265
 */
266
function wc_get_product_cat_class( $class = '', $category = null ) {
267
	$classes   = is_array( $class ) ? $class : array_map( 'trim', explode( ' ', $class ) );
268
	$classes[] = 'product-category';
269
	$classes[] = 'product';
270
	$classes[] = wc_get_loop_class();
271
	$classes   = apply_filters( 'product_cat_class', $classes, $class, $category );
272
273
	return array_unique( array_filter( $classes ) );
274
}
275
276
/**
277
 * Adds extra post classes for products.
278
 *
279
 * @since 2.1.0
280
 * @param array $classes
281
 * @param string|array $class
282
 * @param int $post_id
283
 * @return array
284
 */
285
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...
286
	if ( ! $post_id || 'product' !== get_post_type( $post_id ) ) {
287
		return $classes;
288
	}
289
290
	$product = wc_get_product( $post_id );
291
292
	if ( $product ) {
293
		$classes[] = wc_get_loop_class();
294
		$classes[] = $product->stock_status;
295
296
		if ( $product->is_on_sale() ) {
297
			$classes[] = 'sale';
298
		}
299
		if ( $product->is_featured() ) {
300
			$classes[] = 'featured';
301
		}
302
		if ( $product->is_downloadable() ) {
303
			$classes[] = 'downloadable';
304
		}
305
		if ( $product->is_virtual() ) {
306
			$classes[] = 'virtual';
307
		}
308
		if ( $product->is_sold_individually() ) {
309
			$classes[] = 'sold-individually';
310
		}
311
		if ( $product->is_taxable() ) {
312
			$classes[] = 'taxable';
313
		}
314
		if ( $product->is_shipping_taxable() ) {
315
			$classes[] = 'shipping-taxable';
316
		}
317
		if ( $product->is_purchasable() ) {
318
			$classes[] = 'purchasable';
319
		}
320
		if ( $product->get_type() ) {
321
			$classes[] = "product-type-" . $product->get_type();
322
		}
323
		if ( $product->is_type( 'variable' ) ) {
324
			if ( $product->has_default_attributes() ) {
325
				$classes[] = 'has-default-attributes';
326
			}
327
			if ( $product->has_child() ) {
328
				$classes[] = 'has-children';
329
			}
330
		}
331
	}
332
333
	if ( false !== ( $key = array_search( 'hentry', $classes ) ) ) {
334
		unset( $classes[ $key ] );
335
	}
336
337
	return $classes;
338
}
339
340
/** Template pages ********************************************************/
341
342
if ( ! function_exists( 'woocommerce_content' ) ) {
343
344
	/**
345
	 * Output WooCommerce content.
346
	 *
347
	 * This function is only used in the optional 'woocommerce.php' template.
348
	 * which people can add to their themes to add basic woocommerce support.
349
	 * without hooks or modifying core templates.
350
	 *
351
	 */
352
	function woocommerce_content() {
353
354
		if ( is_singular( 'product' ) ) {
355
356
			while ( have_posts() ) : the_post();
357
358
				wc_get_template_part( 'content', 'single-product' );
359
360
			endwhile;
361
362
		} else { ?>
363
364
			<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
365
366
				<h1 class="page-title"><?php woocommerce_page_title(); ?></h1>
367
368
			<?php endif; ?>
369
370
			<?php do_action( 'woocommerce_archive_description' ); ?>
371
372 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...
373
374
				<?php do_action('woocommerce_before_shop_loop'); ?>
375
376
				<?php woocommerce_product_loop_start(); ?>
377
378
					<?php woocommerce_product_subcategories(); ?>
379
380
					<?php while ( have_posts() ) : the_post(); ?>
381
382
						<?php wc_get_template_part( 'content', 'product' ); ?>
383
384
					<?php endwhile; // end of the loop. ?>
385
386
				<?php woocommerce_product_loop_end(); ?>
387
388
				<?php do_action('woocommerce_after_shop_loop'); ?>
389
390
			<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
391
392
				<?php wc_get_template( 'loop/no-products-found.php' ); ?>
393
394
			<?php endif;
395
396
		}
397
	}
398
}
399
400
/** Global ****************************************************************/
401
402
if ( ! function_exists( 'woocommerce_output_content_wrapper' ) ) {
403
404
	/**
405
	 * Output the start of the page wrapper.
406
	 *
407
	 */
408
	function woocommerce_output_content_wrapper() {
409
		wc_get_template( 'global/wrapper-start.php' );
410
	}
411
}
412
if ( ! function_exists( 'woocommerce_output_content_wrapper_end' ) ) {
413
414
	/**
415
	 * Output the end of the page wrapper.
416
	 *
417
	 */
418
	function woocommerce_output_content_wrapper_end() {
419
		wc_get_template( 'global/wrapper-end.php' );
420
	}
421
}
422
423
if ( ! function_exists( 'woocommerce_get_sidebar' ) ) {
424
425
	/**
426
	 * Get the shop sidebar template.
427
	 *
428
	 */
429
	function woocommerce_get_sidebar() {
430
		wc_get_template( 'global/sidebar.php' );
431
	}
432
}
433
434
if ( ! function_exists( 'woocommerce_demo_store' ) ) {
435
436
	/**
437
	 * Adds a demo store banner to the site if enabled.
438
	 *
439
	 */
440
	function woocommerce_demo_store() {
441
		if ( ! is_store_notice_showing() ) {
442
			return;
443
		}
444
445
		$notice = get_option( 'woocommerce_demo_store_notice' );
446
447
		if ( empty( $notice ) ) {
448
			$notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
449
		}
450
451
		echo apply_filters( 'woocommerce_demo_store', '<p class="demo_store">' . wp_kses_post( $notice ) . '</p>', $notice );
452
	}
453
}
454
455
/** Loop ******************************************************************/
456
457
if ( ! function_exists( 'woocommerce_page_title' ) ) {
458
459
	/**
460
	 * woocommerce_page_title function.
461
	 *
462
	 * @param  bool $echo
463
	 * @return string
464
	 */
465
	function woocommerce_page_title( $echo = true ) {
466
467
		if ( is_search() ) {
468
			$page_title = sprintf( __( 'Search Results: &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() );
469
470
			if ( get_query_var( 'paged' ) )
471
				$page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'woocommerce' ), get_query_var( 'paged' ) );
472
473
		} elseif ( is_tax() ) {
474
475
			$page_title = single_term_title( "", false );
476
477
		} else {
478
479
			$shop_page_id = wc_get_page_id( 'shop' );
480
			$page_title   = get_the_title( $shop_page_id );
481
482
		}
483
484
		$page_title = apply_filters( 'woocommerce_page_title', $page_title );
485
486
		if ( $echo )
487
			echo $page_title;
488
		else
489
			return $page_title;
490
	}
491
}
492
493
if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
494
495
	/**
496
	 * Output the start of a product loop. By default this is a UL.
497
	 *
498
	 * @param bool $echo
499
	 * @return string
500
	 */
501
	function woocommerce_product_loop_start( $echo = true ) {
502
		ob_start();
503
		$GLOBALS['woocommerce_loop']['loop'] = 0;
504
		wc_get_template( 'loop/loop-start.php' );
505
		if ( $echo )
506
			echo ob_get_clean();
507
		else
508
			return ob_get_clean();
509
	}
510
}
511
if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
512
513
	/**
514
	 * Output the end of a product loop. By default this is a UL.
515
	 *
516
	 * @param bool $echo
517
	 * @return string
518
	 */
519
	function woocommerce_product_loop_end( $echo = true ) {
520
		ob_start();
521
522
		wc_get_template( 'loop/loop-end.php' );
523
524
		if ( $echo )
525
			echo ob_get_clean();
526
		else
527
			return ob_get_clean();
528
	}
529
}
530
if (  ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
531
532
	/**
533
	 * Show the product title in the product loop. By default this is an H3.
534
	 */
535
	function woocommerce_template_loop_product_title() {
536
		echo '<h3>' . get_the_title() . '</h3>';
537
	}
538
}
539
if (  ! function_exists( 'woocommerce_template_loop_category_title' ) ) {
540
541
	/**
542
	 * Show the subcategory title in the product loop.
543
	 */
544
	function woocommerce_template_loop_category_title( $category ) {
545
		?>
546
		<h3>
547
			<?php
548
				echo $category->name;
549
550
				if ( $category->count > 0 )
551
					echo apply_filters( 'woocommerce_subcategory_count_html', ' <mark class="count">(' . $category->count . ')</mark>', $category );
552
			?>
553
		</h3>
554
		<?php
555
	}
556
}
557
/**
558
 * Insert the opening anchor tag for products in the loop.
559
 */
560
function woocommerce_template_loop_product_link_open() {
561
	echo '<a href="' . get_the_permalink() . '" class="woocommerce-LoopProduct-link">';
562
}
563
/**
564
 * Insert the opening anchor tag for products in the loop.
565
 */
566
function woocommerce_template_loop_product_link_close() {
567
	echo '</a>';
568
}
569
/**
570
 * Insert the opening anchor tag for categories in the loop.
571
 */
572
function woocommerce_template_loop_category_link_open( $category ) {
573
	echo '<a href="' . get_term_link( $category, 'product_cat' ) . '">';
574
}
575
/**
576
 * Insert the opening anchor tag for categories in the loop.
577
 */
578
function woocommerce_template_loop_category_link_close() {
579
	echo '</a>';
580
}
581
if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
582
583
	/**
584
	 * Show an archive description on taxonomy archives.
585
	 *
586
	 * @subpackage	Archives
587
	 */
588
	function woocommerce_taxonomy_archive_description() {
589
		if ( is_tax( array( 'product_cat', 'product_tag' ) ) && 0 === absint( get_query_var( 'paged' ) ) ) {
590
			$description = wc_format_content( term_description() );
591
			if ( $description ) {
592
				echo '<div class="term-description">' . $description . '</div>';
593
			}
594
		}
595
	}
596
}
597
if ( ! function_exists( 'woocommerce_product_archive_description' ) ) {
598
599
	/**
600
	 * Show a shop page description on product archives.
601
	 *
602
	 * @subpackage	Archives
603
	 */
604
	function woocommerce_product_archive_description() {
605
		// Don't display the description on search results page
606
		if ( is_search() ) {
607
			return;
608
		}
609
610
		if ( is_post_type_archive( 'product' ) && 0 === absint( get_query_var( 'paged' ) ) ) {
611
			$shop_page   = get_post( wc_get_page_id( 'shop' ) );
612
			if ( $shop_page ) {
613
				$description = wc_format_content( $shop_page->post_content );
614
				if ( $description ) {
615
					echo '<div class="page-description">' . $description . '</div>';
616
				}
617
			}
618
		}
619
	}
620
}
621
622
if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
623
624
	/**
625
	 * Get the add to cart template for the loop.
626
	 *
627
	 * @subpackage	Loop
628
	 */
629
	function woocommerce_template_loop_add_to_cart( $args = array() ) {
630
		global $product;
631
632
		if ( $product ) {
633
			$defaults = array(
634
				'quantity' => 1,
635
				'class'    => implode( ' ', array_filter( array(
636
						'button',
637
						'product_type_' . $product->product_type,
638
						$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
639
						$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : ''
640
				) ) )
641
			);
642
643
			$args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product );
644
645
			wc_get_template( 'loop/add-to-cart.php', $args );
646
		}
647
	}
648
}
649
if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) {
650
651
	/**
652
	 * Get the product thumbnail for the loop.
653
	 *
654
	 * @subpackage	Loop
655
	 */
656
	function woocommerce_template_loop_product_thumbnail() {
657
		echo woocommerce_get_product_thumbnail();
658
	}
659
}
660
if ( ! function_exists( 'woocommerce_template_loop_price' ) ) {
661
662
	/**
663
	 * Get the product price for the loop.
664
	 *
665
	 * @subpackage	Loop
666
	 */
667
	function woocommerce_template_loop_price() {
668
		wc_get_template( 'loop/price.php' );
669
	}
670
}
671
if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) {
672
673
	/**
674
	 * Display the average rating in the loop.
675
	 *
676
	 * @subpackage	Loop
677
	 */
678
	function woocommerce_template_loop_rating() {
679
		wc_get_template( 'loop/rating.php' );
680
	}
681
}
682
if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) {
683
684
	/**
685
	 * Get the sale flash for the loop.
686
	 *
687
	 * @subpackage	Loop
688
	 */
689
	function woocommerce_show_product_loop_sale_flash() {
690
		wc_get_template( 'loop/sale-flash.php' );
691
	}
692
}
693
694
if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
695
696
	/**
697
	 * Get the product thumbnail, or the placeholder if not set.
698
	 *
699
	 * @subpackage	Loop
700
	 * @param string $size (default: 'shop_catalog')
701
	 * @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0)
702
	 * @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0)
703
	 * @return string
704
	 */
705
	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...
706
		global $post;
707
		$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
708
709
		if ( has_post_thumbnail() ) {
710
			$props = wc_get_product_attachment_props( get_post_thumbnail_id(), $post );
711
			return get_the_post_thumbnail( $post->ID, $image_size, array(
712
				'title'	 => $props['title'],
713
				'alt'    => $props['alt'],
714
			) );
715
		} elseif ( wc_placeholder_img_src() ) {
716
			return wc_placeholder_img( $image_size );
717
		}
718
	}
719
}
720
721
if ( ! function_exists( 'woocommerce_result_count' ) ) {
722
723
	/**
724
	 * Output the result count text (Showing x - x of x results).
725
	 *
726
	 * @subpackage	Loop
727
	 */
728
	function woocommerce_result_count() {
729
		wc_get_template( 'loop/result-count.php' );
730
	}
731
}
732
733
if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
734
735
	/**
736
	 * Output the product sorting options.
737
	 *
738
	 * @subpackage	Loop
739
	 */
740
	function woocommerce_catalog_ordering() {
741
		global $wp_query;
742
743
		if ( 1 === $wp_query->found_posts || ! woocommerce_products_will_display() ) {
744
			return;
745
		}
746
747
		$orderby                 = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
748
		$show_default_orderby    = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
749
		$catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array(
750
			'menu_order' => __( 'Default sorting', 'woocommerce' ),
751
			'popularity' => __( 'Sort by popularity', 'woocommerce' ),
752
			'rating'     => __( 'Sort by average rating', 'woocommerce' ),
753
			'date'       => __( 'Sort by newness', 'woocommerce' ),
754
			'price'      => __( 'Sort by price: low to high', 'woocommerce' ),
755
			'price-desc' => __( 'Sort by price: high to low', 'woocommerce' )
756
		) );
757
758
		if ( ! $show_default_orderby ) {
759
			unset( $catalog_orderby_options['menu_order'] );
760
		}
761
762
		if ( 'no' === get_option( 'woocommerce_enable_review_rating' ) ) {
763
			unset( $catalog_orderby_options['rating'] );
764
		}
765
766
		wc_get_template( 'loop/orderby.php', array( 'catalog_orderby_options' => $catalog_orderby_options, 'orderby' => $orderby, 'show_default_orderby' => $show_default_orderby ) );
767
	}
768
}
769
770
if ( ! function_exists( 'woocommerce_pagination' ) ) {
771
772
	/**
773
	 * Output the pagination.
774
	 *
775
	 * @subpackage	Loop
776
	 */
777
	function woocommerce_pagination() {
778
		wc_get_template( 'loop/pagination.php' );
779
	}
780
}
781
782
/** Single Product ********************************************************/
783
784
if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
785
786
	/**
787
	 * Output the product image before the single product summary.
788
	 *
789
	 * @subpackage	Product
790
	 */
791
	function woocommerce_show_product_images() {
792
		wc_get_template( 'single-product/product-image.php' );
793
	}
794
}
795
if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) {
796
797
	/**
798
	 * Output the product thumbnails.
799
	 *
800
	 * @subpackage	Product
801
	 */
802
	function woocommerce_show_product_thumbnails() {
803
		wc_get_template( 'single-product/product-thumbnails.php' );
804
	}
805
}
806
if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
807
808
	/**
809
	 * Output the product tabs.
810
	 *
811
	 * @subpackage	Product/Tabs
812
	 */
813
	function woocommerce_output_product_data_tabs() {
814
		wc_get_template( 'single-product/tabs/tabs.php' );
815
	}
816
}
817
if ( ! function_exists( 'woocommerce_template_single_title' ) ) {
818
819
	/**
820
	 * Output the product title.
821
	 *
822
	 * @subpackage	Product
823
	 */
824
	function woocommerce_template_single_title() {
825
		wc_get_template( 'single-product/title.php' );
826
	}
827
}
828
if ( ! function_exists( 'woocommerce_template_single_rating' ) ) {
829
830
	/**
831
	 * Output the product rating.
832
	 *
833
	 * @subpackage	Product
834
	 */
835
	function woocommerce_template_single_rating() {
836
		wc_get_template( 'single-product/rating.php' );
837
	}
838
}
839
if ( ! function_exists( 'woocommerce_template_single_price' ) ) {
840
841
	/**
842
	 * Output the product price.
843
	 *
844
	 * @subpackage	Product
845
	 */
846
	function woocommerce_template_single_price() {
847
		wc_get_template( 'single-product/price.php' );
848
	}
849
}
850
if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) {
851
852
	/**
853
	 * Output the product short description (excerpt).
854
	 *
855
	 * @subpackage	Product
856
	 */
857
	function woocommerce_template_single_excerpt() {
858
		wc_get_template( 'single-product/short-description.php' );
859
	}
860
}
861
if ( ! function_exists( 'woocommerce_template_single_meta' ) ) {
862
863
	/**
864
	 * Output the product meta.
865
	 *
866
	 * @subpackage	Product
867
	 */
868
	function woocommerce_template_single_meta() {
869
		wc_get_template( 'single-product/meta.php' );
870
	}
871
}
872
if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) {
873
874
	/**
875
	 * Output the product sharing.
876
	 *
877
	 * @subpackage	Product
878
	 */
879
	function woocommerce_template_single_sharing() {
880
		wc_get_template( 'single-product/share.php' );
881
	}
882
}
883
if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) {
884
885
	/**
886
	 * Output the product sale flash.
887
	 *
888
	 * @subpackage	Product
889
	 */
890
	function woocommerce_show_product_sale_flash() {
891
		wc_get_template( 'single-product/sale-flash.php' );
892
	}
893
}
894
895
if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) {
896
897
	/**
898
	 * Trigger the single product add to cart action.
899
	 *
900
	 * @subpackage	Product
901
	 */
902
	function woocommerce_template_single_add_to_cart() {
903
		global $product;
904
		do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );
905
	}
906
}
907
if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) {
908
909
	/**
910
	 * Output the simple product add to cart area.
911
	 *
912
	 * @subpackage	Product
913
	 */
914
	function woocommerce_simple_add_to_cart() {
915
		wc_get_template( 'single-product/add-to-cart/simple.php' );
916
	}
917
}
918
if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
919
920
	/**
921
	 * Output the grouped product add to cart area.
922
	 *
923
	 * @subpackage	Product
924
	 */
925
	function woocommerce_grouped_add_to_cart() {
926
		global $product;
927
928
		wc_get_template( 'single-product/add-to-cart/grouped.php', array(
929
			'grouped_product'    => $product,
930
			'grouped_products'   => $product->get_children(),
931
			'quantites_required' => false
932
		) );
933
	}
934
}
935
if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) {
936
937
	/**
938
	 * Output the variable product add to cart area.
939
	 *
940
	 * @subpackage	Product
941
	 */
942
	function woocommerce_variable_add_to_cart() {
943
		global $product;
944
945
		// Enqueue variation scripts
946
		wp_enqueue_script( 'wc-add-to-cart-variation' );
947
948
		// Get Available variations?
949
		$get_variations = sizeof( $product->get_children() ) <= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product );
950
951
		// Load the template
952
		wc_get_template( 'single-product/add-to-cart/variable.php', array(
953
			'available_variations' => $get_variations ? $product->get_available_variations() : false,
954
			'attributes'           => $product->get_variation_attributes(),
955
			'selected_attributes'  => $product->get_variation_default_attributes()
956
		) );
957
	}
958
}
959
if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) {
960
961
	/**
962
	 * Output the external product add to cart area.
963
	 *
964
	 * @subpackage	Product
965
	 */
966
	function woocommerce_external_add_to_cart() {
967
		global $product;
968
969
		if ( ! $product->add_to_cart_url() ) {
970
			return;
971
		}
972
973
		wc_get_template( 'single-product/add-to-cart/external.php', array(
974
			'product_url' => $product->add_to_cart_url(),
975
			'button_text' => $product->single_add_to_cart_text()
976
		) );
977
	}
978
}
979
980
if ( ! function_exists( 'woocommerce_quantity_input' ) ) {
981
982
	/**
983
	 * Output the quantity input for add to cart forms.
984
	 *
985
	 * @param  array $args Args for the input
986
	 * @param  WC_Product|null $product
987
	 * @param  boolean $echo Whether to return or echo|string
988
	 */
989
	function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
990
		if ( is_null( $product ) ) {
991
			$product = $GLOBALS['product'];
992
		}
993
994
		$defaults = array(
995
			'input_name'  => 'quantity',
996
			'input_value' => '1',
997
			'max_value'   => apply_filters( 'woocommerce_quantity_input_max', '', $product ),
998
			'min_value'   => apply_filters( 'woocommerce_quantity_input_min', '', $product ),
999
			'step'        => apply_filters( 'woocommerce_quantity_input_step', '1', $product ),
1000
			'pattern'     => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
1001
			'inputmode'   => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
1002
		);
1003
1004
		$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
1005
1006
		// Set min and max value to empty string if not set.
1007
		$args['min_value'] = isset( $args['min_value'] ) ? $args['min_value'] : '';
1008
		$args['max_value'] = isset( $args['max_value'] ) ? $args['max_value'] : '';
1009
1010
		// Apply sanity to min/max args - min cannot be lower than 0
1011
		if ( '' !== $args['min_value'] && is_numeric( $args['min_value'] ) && $args['min_value'] < 0 ) {
1012
			$args['min_value'] = 0; // Cannot be lower than 0
1013
		}
1014
1015
		// Max cannot be lower than 0 or min
1016
		if ( '' !== $args['max_value'] && is_numeric( $args['max_value'] ) ) {
1017
			$args['max_value'] = $args['max_value'] < 0 ? 0 : $args['max_value'];
1018
			$args['max_value'] = $args['max_value'] < $args['min_value'] ? $args['min_value'] : $args['max_value'];
1019
		}
1020
1021
		ob_start();
1022
1023
		wc_get_template( 'global/quantity-input.php', $args );
1024
1025
		if ( $echo ) {
1026
			echo ob_get_clean();
1027
		} else {
1028
			return ob_get_clean();
1029
		}
1030
	}
1031
}
1032
1033
if ( ! function_exists( 'woocommerce_product_description_tab' ) ) {
1034
1035
	/**
1036
	 * Output the description tab content.
1037
	 *
1038
	 * @subpackage	Product/Tabs
1039
	 */
1040
	function woocommerce_product_description_tab() {
1041
		wc_get_template( 'single-product/tabs/description.php' );
1042
	}
1043
}
1044
if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
1045
1046
	/**
1047
	 * Output the attributes tab content.
1048
	 *
1049
	 * @subpackage	Product/Tabs
1050
	 */
1051
	function woocommerce_product_additional_information_tab() {
1052
		wc_get_template( 'single-product/tabs/additional-information.php' );
1053
	}
1054
}
1055
if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
1056
1057
	/**
1058
	 * Output the reviews tab content.
1059
	 * @deprecated  2.4.0 Unused
1060
	 * @subpackage	Product/Tabs
1061
	 */
1062
	function woocommerce_product_reviews_tab() {
1063
		_deprecated_function( 'woocommerce_product_reviews_tab', '2.4', '' );
1064
	}
1065
}
1066
1067
if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
1068
1069
	/**
1070
	 * Add default product tabs to product pages.
1071
	 *
1072
	 * @param array $tabs
1073
	 * @return array
1074
	 */
1075
	function woocommerce_default_product_tabs( $tabs = array() ) {
1076
		global $product, $post;
1077
1078
		// Description tab - shows product content
1079
		if ( $post->post_content ) {
1080
			$tabs['description'] = array(
1081
				'title'    => __( 'Description', 'woocommerce' ),
1082
				'priority' => 10,
1083
				'callback' => 'woocommerce_product_description_tab'
1084
			);
1085
		}
1086
1087
		// Additional information tab - shows attributes
1088
		if ( $product && ( $product->has_attributes() || ( $product->enable_dimensions_display() && ( $product->has_dimensions() || $product->has_weight() ) ) ) ) {
1089
			$tabs['additional_information'] = array(
1090
				'title'    => __( 'Additional Information', 'woocommerce' ),
1091
				'priority' => 20,
1092
				'callback' => 'woocommerce_product_additional_information_tab'
1093
			);
1094
		}
1095
1096
		// Reviews tab - shows comments
1097
		if ( comments_open() ) {
1098
			$tabs['reviews'] = array(
1099
				'title'    => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ),
1100
				'priority' => 30,
1101
				'callback' => 'comments_template'
1102
			);
1103
		}
1104
1105
		return $tabs;
1106
	}
1107
}
1108
1109
if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) {
1110
1111
	/**
1112
	 * Sort tabs by priority.
1113
	 *
1114
	 * @param array $tabs
1115
	 * @return array
1116
	 */
1117
	function woocommerce_sort_product_tabs( $tabs = array() ) {
1118
1119
		// Make sure the $tabs parameter is an array
1120
		if ( ! is_array( $tabs ) ) {
1121
			trigger_error( "Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array." );
1122
			$tabs = array( );
1123
		}
1124
1125
		// Re-order tabs by priority
1126
		if ( ! function_exists( '_sort_priority_callback' ) ) {
1127
			function _sort_priority_callback( $a, $b ) {
1128
				if ( $a['priority'] === $b['priority'] )
1129
					return 0;
1130
				return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
1131
			}
1132
		}
1133
1134
		uasort( $tabs, '_sort_priority_callback' );
1135
1136
		return $tabs;
1137
	}
1138
}
1139
1140
if ( ! function_exists( 'woocommerce_comments' ) ) {
1141
1142
	/**
1143
	 * Output the Review comments template.
1144
	 *
1145
	 * @subpackage	Product
1146
	 * @param WP_Comment $comment
1147
	 * @param array $args
1148
	 * @param int $depth
1149
	 */
1150
	function woocommerce_comments( $comment, $args, $depth ) {
1151
		$GLOBALS['comment'] = $comment;
1152
		wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) );
1153
	}
1154
}
1155
1156
if ( ! function_exists( 'woocommerce_review_display_gravatar' ) ) {
1157
	/**
1158
	 * Display the review authors gravatar
1159
	 *
1160
	 * @param array $comment WP_Comment.
1161
	 * @return void
1162
	 */
1163
	function woocommerce_review_display_gravatar( $comment ) {
1164
		echo get_avatar( $comment, apply_filters( 'woocommerce_review_gravatar_size', '60' ), '' );
1165
	}
1166
}
1167
1168
if ( ! function_exists( 'woocommerce_review_display_rating' ) ) {
1169
	/**
1170
	 * Display the reviewers star rating
1171
	 *
1172
	 * @return void
1173
	 */
1174
	function woocommerce_review_display_rating() {
1175
		wc_get_template( 'single-product/review-rating.php' );
1176
	}
1177
}
1178
1179
if ( ! function_exists( 'woocommerce_review_display_meta' ) ) {
1180
	/**
1181
	 * Display the review authors meta (name, verified owner, review date)
1182
	 *
1183
	 * @return void
1184
	 */
1185
	function woocommerce_review_display_meta() {
1186
		wc_get_template( 'single-product/review-meta.php' );
1187
	}
1188
}
1189
1190
if ( ! function_exists( 'woocommerce_review_display_comment_text' ) ) {
1191
1192
	/**
1193
	 * Display the review content.
1194
	 */
1195
	function woocommerce_review_display_comment_text() {
1196
		echo '<div class="description">';
1197
		comment_text();
1198
		echo '</div>';
1199
	}
1200
}
1201
1202
if ( ! function_exists( 'woocommerce_output_related_products' ) ) {
1203
1204
	/**
1205
	 * Output the related products.
1206
	 *
1207
	 * @subpackage	Product
1208
	 */
1209
	function woocommerce_output_related_products() {
1210
1211
		$args = array(
1212
			'posts_per_page' 	=> 4,
1213
			'columns' 			=> 4,
1214
			'orderby' 			=> 'rand'
1215
		);
1216
1217
		woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) );
1218
	}
1219
}
1220
1221
if ( ! function_exists( 'woocommerce_related_products' ) ) {
1222
1223
	/**
1224
	 * Output the related products.
1225
	 *
1226
	 * @param array Provided arguments
1227
	 * @param bool Columns argument for backwards compat
1228
	 * @param bool Order by argument for backwards compat
1229
	 */
1230
	function woocommerce_related_products( $args = array(), $columns = false, $orderby = false ) {
1231
		if ( ! is_array( $args ) ) {
1232
			_deprecated_argument( __FUNCTION__, '2.1', __( 'Use $args argument as an array instead. Deprecated argument will be removed in WC 2.2.', 'woocommerce' ) );
1233
1234
			$argsvalue = $args;
1235
1236
			$args = array(
1237
				'posts_per_page' => $argsvalue,
1238
				'columns'        => $columns,
1239
				'orderby'        => $orderby,
1240
			);
1241
		}
1242
1243
		$defaults = array(
1244
			'posts_per_page' => 2,
1245
			'columns'        => 2,
1246
			'orderby'        => 'rand'
1247
		);
1248
1249
		$args = wp_parse_args( $args, $defaults );
1250
1251
		wc_get_template( 'single-product/related.php', $args );
1252
	}
1253
}
1254
1255
if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
1256
1257
	/**
1258
	 * Output product up sells.
1259
	 *
1260
	 * @param int $posts_per_page (default: -1)
1261
	 * @param int $columns (default: 4)
1262
	 * @param string $orderby (default: 'rand')
1263
	 */
1264
	function woocommerce_upsell_display( $posts_per_page = '-1', $columns = 4, $orderby = 'rand' ) {
1265
		$args = apply_filters( 'woocommerce_upsell_display_args', array(
1266
			'posts_per_page'	=> $posts_per_page,
1267
			'orderby'			=> apply_filters( 'woocommerce_upsells_orderby', $orderby ),
1268
			'columns'			=> $columns
1269
		) );
1270
1271
		wc_get_template( 'single-product/up-sells.php', $args );
1272
	}
1273
}
1274
1275
/** Cart ******************************************************************/
1276
1277
if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) {
1278
1279
	/**
1280
	 * Output the cart shipping calculator.
1281
	 *
1282
	 * @subpackage	Cart
1283
	 */
1284
	function woocommerce_shipping_calculator() {
1285
		wc_get_template( 'cart/shipping-calculator.php' );
1286
	}
1287
}
1288
1289
if ( ! function_exists( 'woocommerce_cart_totals' ) ) {
1290
1291
	/**
1292
	 * Output the cart totals.
1293
	 *
1294
	 * @subpackage	Cart
1295
	 */
1296
	function woocommerce_cart_totals() {
1297
		if ( is_checkout() ) {
1298
			return;
1299
		}
1300
		wc_get_template( 'cart/cart-totals.php' );
1301
	}
1302
}
1303
1304
if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
1305
1306
	/**
1307
	 * Output the cart cross-sells.
1308
	 *
1309
	 * @param  int $posts_per_page (default: 2)
1310
	 * @param  int $columns (default: 2)
1311
	 * @param  string $orderby (default: 'rand')
1312
	 */
1313
	function woocommerce_cross_sell_display( $posts_per_page = 2, $columns = 2, $orderby = 'rand' ) {
1314
		if ( is_checkout() ) {
1315
			return;
1316
		}
1317
		wc_get_template( 'cart/cross-sells.php', array(
1318
			'posts_per_page' => $posts_per_page,
1319
			'orderby'        => $orderby,
1320
			'columns'        => $columns
1321
		) );
1322
	}
1323
}
1324
1325
if ( ! function_exists( 'woocommerce_button_proceed_to_checkout' ) ) {
1326
1327
	/**
1328
	 * Output the proceed to checkout button.
1329
	 *
1330
	 * @subpackage	Cart
1331
	 */
1332
	function woocommerce_button_proceed_to_checkout() {
1333
		wc_get_template( 'cart/proceed-to-checkout-button.php' );
1334
	}
1335
}
1336
1337 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...
1338
1339
	/**
1340
	 * Output the proceed to checkout button.
1341
	 *
1342
	 * @subpackage	Cart
1343
	 */
1344
	function woocommerce_widget_shopping_cart_button_view_cart() {
1345
		echo '<a href="' . esc_url( wc_get_cart_url() ) . '" class="button wc-forward">' . __( 'View Cart', 'woocommerce' ) . '</a>';
1346
	}
1347
}
1348
1349 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...
1350
1351
	/**
1352
	 * Output the proceed to checkout button.
1353
	 *
1354
	 * @subpackage	Cart
1355
	 */
1356
	function woocommerce_widget_shopping_cart_proceed_to_checkout() {
1357
		echo '<a href="' . esc_url( wc_get_checkout_url() ) . '" class="button checkout wc-forward">' . __( 'Checkout', 'woocommerce' ) . '</a>';
1358
	}
1359
}
1360
1361
/** Mini-Cart *************************************************************/
1362
1363
if ( ! function_exists( 'woocommerce_mini_cart' ) ) {
1364
1365
	/**
1366
	 * Output the Mini-cart - used by cart widget.
1367
	 *
1368
	 * @param array $args
1369
	 */
1370
	function woocommerce_mini_cart( $args = array() ) {
1371
1372
		$defaults = array(
1373
			'list_class' => ''
1374
		);
1375
1376
		$args = wp_parse_args( $args, $defaults );
1377
1378
		wc_get_template( 'cart/mini-cart.php', $args );
1379
	}
1380
}
1381
1382
/** Login *****************************************************************/
1383
1384
if ( ! function_exists( 'woocommerce_login_form' ) ) {
1385
1386
	/**
1387
	 * Output the WooCommerce Login Form.
1388
	 *
1389
	 * @subpackage	Forms
1390
	 * @param array $args
1391
	 */
1392
	function woocommerce_login_form( $args = array() ) {
1393
1394
		$defaults = array(
1395
			'message'  => '',
1396
			'redirect' => '',
1397
			'hidden'   => false
1398
		);
1399
1400
		$args = wp_parse_args( $args, $defaults  );
1401
1402
		wc_get_template( 'global/form-login.php', $args );
1403
	}
1404
}
1405
1406
if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) {
1407
1408
	/**
1409
	 * Output the WooCommerce Checkout Login Form.
1410
	 *
1411
	 * @subpackage	Checkout
1412
	 */
1413
	function woocommerce_checkout_login_form() {
1414
		wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) );
1415
	}
1416
}
1417
1418
if ( ! function_exists( 'woocommerce_breadcrumb' ) ) {
1419
1420
	/**
1421
	 * Output the WooCommerce Breadcrumb.
1422
	 *
1423
	 * @param array $args
1424
	 */
1425
	function woocommerce_breadcrumb( $args = array() ) {
1426
		$args = wp_parse_args( $args, apply_filters( 'woocommerce_breadcrumb_defaults', array(
1427
			'delimiter'   => '&nbsp;&#47;&nbsp;',
1428
			'wrap_before' => '<nav class="woocommerce-breadcrumb">',
1429
			'wrap_after'  => '</nav>',
1430
			'before'      => '',
1431
			'after'       => '',
1432
			'home'        => _x( 'Home', 'breadcrumb', 'woocommerce' )
1433
		) ) );
1434
1435
		$breadcrumbs = new WC_Breadcrumb();
1436
1437
		if ( ! empty( $args['home'] ) ) {
1438
			$breadcrumbs->add_crumb( $args['home'], apply_filters( 'woocommerce_breadcrumb_home_url', home_url() ) );
1439
		}
1440
1441
		$args['breadcrumb'] = $breadcrumbs->generate();
1442
1443
    do_action( 'woocommerce_breadcrumb', $args );
1444
1445
		wc_get_template( 'global/breadcrumb.php', $args );
1446
	}
1447
}
1448
1449
if ( ! function_exists( 'woocommerce_order_review' ) ) {
1450
1451
	/**
1452
	 * Output the Order review table for the checkout.
1453
	 *
1454
	 * @subpackage	Checkout
1455
	 */
1456
	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...
1457
		wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
1458
	}
1459
}
1460
1461
if ( ! function_exists( 'woocommerce_checkout_payment' ) ) {
1462
1463
	/**
1464
	 * Output the Payment Methods on the checkout.
1465
	 *
1466
	 * @subpackage	Checkout
1467
	 */
1468
	function woocommerce_checkout_payment() {
1469
		if ( WC()->cart->needs_payment() ) {
1470
			$available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
1471
			WC()->payment_gateways()->set_current_gateway( $available_gateways );
1472
		} else {
1473
			$available_gateways = array();
1474
		}
1475
1476
		wc_get_template( 'checkout/payment.php', array(
1477
			'checkout'           => WC()->checkout(),
1478
			'available_gateways' => $available_gateways,
1479
			'order_button_text'  => apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) )
1480
		) );
1481
	}
1482
}
1483
1484
if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
1485
1486
	/**
1487
	 * Output the Coupon form for the checkout.
1488
	 *
1489
	 * @subpackage	Checkout
1490
	 */
1491
	function woocommerce_checkout_coupon_form() {
1492
		wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) );
1493
	}
1494
}
1495
1496
if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
1497
1498
	/**
1499
	 * Check if we will be showing products or not (and not sub-categories only).
1500
	 * @subpackage	Loop
1501
	 * @return bool
1502
	 */
1503
	function woocommerce_products_will_display() {
1504
		global $wpdb;
1505
1506
		if ( is_shop() ) {
1507
			return 'subcategories' !== get_option( 'woocommerce_shop_page_display' ) || is_search();
1508
		}
1509
1510
		if ( ! is_product_taxonomy() ) {
1511
			return false;
1512
		}
1513
1514
		if ( is_search() || is_filtered() || is_paged() ) {
1515
			return true;
1516
		}
1517
1518
		$term = get_queried_object();
1519
1520
		if ( is_product_category() ) {
1521
			switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
1522
				case 'subcategories' :
1523
					// Nothing - we want to continue to see if there are products/subcats
1524
				break;
1525
				case 'products' :
1526
				case 'both' :
1527
					return true;
1528
				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...
1529
				default :
1530
					// Default - no setting
1531
					if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) {
1532
						return true;
1533
					}
1534
				break;
1535
			}
1536
		}
1537
1538
		// Begin subcategory logic
1539
		if ( empty( $term->term_id ) || empty( $term->taxonomy ) ) {
1540
			return true;
1541
		}
1542
1543
		$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
1544
1545
		if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) {
1546
			$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 ) );
1547
1548
			if ( $has_children ) {
1549
				// Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
1550
				if ( sizeof( get_objects_in_term( $has_children, $term->taxonomy ) ) > 0 ) {
1551
					$products_will_display = false;
1552
				} else {
1553
					// If we get here, the parents were empty so we're forced to check children
1554
					foreach ( $has_children as $term_id ) {
1555
						$children = get_term_children( $term_id, $term->taxonomy );
1556
1557
						if ( sizeof( get_objects_in_term( $children, $term->taxonomy ) ) > 0 ) {
1558
							$products_will_display = false;
1559
							break;
1560
						}
1561
					}
1562
				}
1563
			} else {
1564
				$products_will_display = true;
1565
			}
1566
		}
1567
1568
		set_transient( $transient_name, $products_will_display, DAY_IN_SECONDS * 30 );
1569
1570
		return $products_will_display;
1571
	}
1572
}
1573
1574
if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
1575
1576
	/**
1577
	 * Display product sub categories as thumbnails.
1578
	 *
1579
	 * @subpackage	Loop
1580
	 * @param array $args
1581
	 * @return null|boolean
1582
	 */
1583
	function woocommerce_product_subcategories( $args = array() ) {
1584
		global $wp_query;
1585
1586
		$defaults = array(
1587
			'before'        => '',
1588
			'after'         => '',
1589
			'force_display' => false
1590
		);
1591
1592
		$args = wp_parse_args( $args, $defaults );
1593
1594
		extract( $args );
1595
1596
		// Main query only
1597
		if ( ! is_main_query() && ! $force_display ) {
1598
			return;
1599
		}
1600
1601
		// Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive
1602
		if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) {
1603
			return;
1604
		}
1605
1606
		// Check categories are enabled
1607
		if ( is_shop() && '' === get_option( 'woocommerce_shop_page_display' ) ) {
1608
			return;
1609
		}
1610
1611
		// Find the category + category parent, if applicable
1612
		$term 			= get_queried_object();
1613
		$parent_id 		= empty( $term->term_id ) ? 0 : $term->term_id;
1614
1615
		if ( is_product_category() ) {
1616
			$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1617
1618
			switch ( $display_type ) {
1619
				case 'products' :
1620
					return;
1621
				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...
1622
				case '' :
1623
					if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
1624
						return;
1625
					}
1626
				break;
1627
			}
1628
		}
1629
1630
		// 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
1631
		$product_categories = get_categories( apply_filters( 'woocommerce_product_subcategories_args', array(
1632
			'parent'       => $parent_id,
1633
			'menu_order'   => 'ASC',
1634
			'hide_empty'   => 0,
1635
			'hierarchical' => 1,
1636
			'taxonomy'     => 'product_cat',
1637
			'pad_counts'   => 1
1638
		) ) );
1639
1640
		if ( ! apply_filters( 'woocommerce_product_subcategories_hide_empty', false ) ) {
1641
			$product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' );
1642
		}
1643
1644
		if ( $product_categories ) {
1645
			echo $before;
1646
1647
			foreach ( $product_categories as $category ) {
1648
				wc_get_template( 'content-product_cat.php', array(
1649
					'category' => $category
1650
				) );
1651
			}
1652
1653
			// If we are hiding products disable the loop and pagination
1654
			if ( is_product_category() ) {
1655
				$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1656
1657
				switch ( $display_type ) {
1658
					case 'subcategories' :
1659
						$wp_query->post_count    = 0;
1660
						$wp_query->max_num_pages = 0;
1661
					break;
1662
					case '' :
1663
						if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) {
1664
							$wp_query->post_count    = 0;
1665
							$wp_query->max_num_pages = 0;
1666
						}
1667
					break;
1668
				}
1669
			}
1670
1671
			if ( is_shop() && 'subcategories' === get_option( 'woocommerce_shop_page_display' ) ) {
1672
				$wp_query->post_count    = 0;
1673
				$wp_query->max_num_pages = 0;
1674
			}
1675
1676
			echo $after;
1677
1678
			return true;
1679
		}
1680
	}
1681
}
1682
1683
if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
1684
1685
	/**
1686
	 * Show subcategory thumbnails.
1687
	 *
1688
	 * @param mixed $category
1689
	 * @subpackage	Loop
1690
	 */
1691
	function woocommerce_subcategory_thumbnail( $category ) {
1692
		$small_thumbnail_size  	= apply_filters( 'subcategory_archive_thumbnail_size', 'shop_catalog' );
1693
		$dimensions    			= wc_get_image_size( $small_thumbnail_size );
1694
		$thumbnail_id  			= get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true  );
1695
1696
		if ( $thumbnail_id ) {
1697
			$image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size  );
1698
			$image = $image[0];
1699
		} else {
1700
			$image = wc_placeholder_img_src();
1701
		}
1702
1703
		if ( $image ) {
1704
			// Prevent esc_url from breaking spaces in urls for image embeds
1705
			// Ref: https://core.trac.wordpress.org/ticket/23605
1706
			$image = str_replace( ' ', '%20', $image );
1707
1708
			echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
1709
		}
1710
	}
1711
}
1712
1713
if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
1714
1715
	/**
1716
	 * Displays order details in a table.
1717
	 *
1718
	 * @param mixed $order_id
1719
	 * @subpackage	Orders
1720
	 */
1721
	function woocommerce_order_details_table( $order_id ) {
1722
		if ( ! $order_id ) return;
1723
1724
		wc_get_template( 'order/order-details.php', array(
1725
			'order_id' => $order_id
1726
		) );
1727
	}
1728
}
1729
1730
1731
if ( ! function_exists( 'woocommerce_order_again_button' ) ) {
1732
1733
	/**
1734
	 * Display an 'order again' button on the view order page.
1735
	 *
1736
	 * @param object $order
1737
	 * @subpackage	Orders
1738
	 */
1739
	function woocommerce_order_again_button( $order ) {
1740
		if ( ! $order || ! $order->has_status( 'completed' ) || ! is_user_logged_in() ) {
1741
			return;
1742
		}
1743
1744
		wc_get_template( 'order/order-again.php', array(
1745
			'order' => $order
1746
		) );
1747
	}
1748
}
1749
1750
/** Forms ****************************************************************/
1751
1752
if ( ! function_exists( 'woocommerce_form_field' ) ) {
1753
1754
	/**
1755
	 * Outputs a checkout/address form field.
1756
	 *
1757
	 * @subpackage	Forms
1758
	 * @param string $key
1759
	 * @param mixed $args
1760
	 * @param string $value (default: null)
1761
	 * @todo This function needs to be broken up in smaller pieces
1762
	 */
1763
	function woocommerce_form_field( $key, $args, $value = null ) {
1764
		$defaults = array(
1765
			'type'              => 'text',
1766
			'label'             => '',
1767
			'description'       => '',
1768
			'placeholder'       => '',
1769
			'maxlength'         => false,
1770
			'required'          => false,
1771
			'autocomplete'      => false,
1772
			'id'                => $key,
1773
			'class'             => array(),
1774
			'label_class'       => array(),
1775
			'input_class'       => array(),
1776
			'return'            => false,
1777
			'options'           => array(),
1778
			'custom_attributes' => array(),
1779
			'validate'          => array(),
1780
			'default'           => '',
1781
		);
1782
1783
		$args = wp_parse_args( $args, $defaults );
1784
		$args = apply_filters( 'woocommerce_form_field_args', $args, $key, $value );
1785
1786
		if ( $args['required'] ) {
1787
			$args['class'][] = 'validate-required';
1788
			$required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce'  ) . '">*</abbr>';
1789
		} else {
1790
			$required = '';
1791
		}
1792
1793
		$args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
1794
1795
		$args['autocomplete'] = ( $args['autocomplete'] ) ? 'autocomplete="' . esc_attr( $args['autocomplete'] ) . '"' : '';
1796
1797
		if ( is_string( $args['label_class'] ) ) {
1798
			$args['label_class'] = array( $args['label_class'] );
1799
		}
1800
1801
		if ( is_null( $value ) ) {
1802
			$value = $args['default'];
1803
		}
1804
1805
		// Custom attribute handling
1806
		$custom_attributes = array();
1807
1808 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...
1809
			foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
1810
				$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
1811
			}
1812
		}
1813
1814
		if ( ! empty( $args['validate'] ) ) {
1815
			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...
1816
				$args['class'][] = 'validate-' . $validate;
1817
			}
1818
		}
1819
1820
		$field = '';
1821
		$label_id = $args['id'];
1822
		$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
1823
1824
		switch ( $args['type'] ) {
1825
			case 'country' :
1826
1827
				$countries = 'shipping_country' === $key ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
1828
1829
				if ( 1 === sizeof( $countries ) ) {
1830
1831
					$field .= '<strong>' . current( array_values( $countries ) ) . '</strong>';
1832
1833
					$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" />';
1834
1835
				} else {
1836
1837
					$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 ) . '>'
1838
							. '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
1839
1840 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...
1841
						$field .= '<option value="' . esc_attr( $ckey ) . '" '. selected( $value, $ckey, false ) . '>'. __( $cvalue, 'woocommerce' ) .'</option>';
1842
					}
1843
1844
					$field .= '</select>';
1845
1846
					$field .= '<noscript><input type="submit" name="woocommerce_checkout_update_totals" value="' . esc_attr__( 'Update country', 'woocommerce' ) . '" /></noscript>';
1847
1848
				}
1849
1850
				break;
1851
			case 'state' :
1852
1853
				/* Get Country */
1854
				$country_key = 'billing_state' === $key ? 'billing_country' : 'shipping_country';
1855
				$current_cc  = WC()->checkout->get_value( $country_key );
1856
				$states      = WC()->countries->get_states( $current_cc );
1857
1858
				if ( is_array( $states ) && empty( $states ) ) {
1859
1860
					$field_container = '<p class="form-row %1$s" id="%2$s" style="display: none">%3$s</p>';
1861
1862
					$field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key )  . '" id="' . esc_attr( $args['id'] ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
1863
1864
				} elseif ( is_array( $states ) ) {
1865
1866
					$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'] . '>
1867
						<option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
1868
1869 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...
1870
						$field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
1871
					}
1872
1873
					$field .= '</select>';
1874
1875
				} else {
1876
1877
					$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 ) . ' />';
1878
1879
				}
1880
1881
				break;
1882
			case 'textarea' :
1883
1884
				$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>';
1885
1886
				break;
1887 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...
1888
1889
				$field = '<label class="checkbox ' . implode( ' ', $args['label_class'] ) .'" ' . implode( ' ', $custom_attributes ) . '>
1890
						<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 ) .' /> '
1891
						 . $args['label'] . $required . '</label>';
1892
1893
				break;
1894
			case 'password' :
1895
			case 'text' :
1896
			case 'email' :
1897
			case 'tel' :
1898 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...
1899
1900
				$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 ) . ' />';
1901
1902
				break;
1903
			case 'select' :
1904
1905
				$options = $field = '';
1906
1907
				if ( ! empty( $args['options'] ) ) {
1908
					foreach ( $args['options'] as $option_key => $option_text ) {
1909
						if ( '' === $option_key ) {
1910
							// If we have a blank option, select2 needs a placeholder
1911
							if ( empty( $args['placeholder'] ) ) {
1912
								$args['placeholder'] = $option_text ? $option_text : __( 'Choose an option', 'woocommerce' );
1913
							}
1914
							$custom_attributes[] = 'data-allow_clear="true"';
1915
						}
1916
						$options .= '<option value="' . esc_attr( $option_key ) . '" '. selected( $value, $option_key, false ) . '>' . esc_attr( $option_text ) .'</option>';
1917
					}
1918
1919
					$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'] . '>
1920
							' . $options . '
1921
						</select>';
1922
				}
1923
1924
				break;
1925
			case 'radio' :
1926
1927
				$label_id = current( array_keys( $args['options'] ) );
1928
1929
				if ( ! empty( $args['options'] ) ) {
1930
					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...
1931
						$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 ) . ' />';
1932
						$field .= '<label for="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" class="radio ' . implode( ' ', $args['label_class'] ) .'">' . $option_text . '</label>';
1933
					}
1934
				}
1935
1936
				break;
1937
		}
1938
1939
		if ( ! empty( $field ) ) {
1940
			$field_html = '';
1941
1942
			if ( $args['label'] && 'checkbox' != $args['type'] ) {
1943
				$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) .'">' . $args['label'] . $required . '</label>';
1944
			}
1945
1946
			$field_html .= $field;
1947
1948
			if ( $args['description'] ) {
1949
				$field_html .= '<span class="description">' . esc_html( $args['description'] ) . '</span>';
1950
			}
1951
1952
			$container_class = 'form-row ' . esc_attr( implode( ' ', $args['class'] ) );
1953
			$container_id = esc_attr( $args['id'] ) . '_field';
1954
1955
			$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
1956
1957
			$field = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
1958
		}
1959
1960
		$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );
1961
1962
		if ( $args['return'] ) {
1963
			return $field;
1964
		} else {
1965
			echo $field;
1966
		}
1967
	}
1968
}
1969
1970
if ( ! function_exists( 'get_product_search_form' ) ) {
1971
1972
	/**
1973
	 * Display product search form.
1974
	 *
1975
	 * Will first attempt to locate the product-searchform.php file in either the child or.
1976
	 * the parent, then load it. If it doesn't exist, then the default search form.
1977
	 * will be displayed.
1978
	 *
1979
	 * The default searchform uses html5.
1980
	 *
1981
	 * @subpackage	Forms
1982
	 * @param bool $echo (default: true)
1983
	 * @return string
1984
	 */
1985
	function get_product_search_form( $echo = true  ) {
1986
		ob_start();
1987
1988
		do_action( 'pre_get_product_search_form'  );
1989
1990
		wc_get_template( 'product-searchform.php' );
1991
1992
		$form = apply_filters( 'get_product_search_form', ob_get_clean() );
1993
1994
		if ( $echo ) {
1995
			echo $form;
1996
		} else {
1997
			return $form;
1998
		}
1999
	}
2000
}
2001
2002
if ( ! function_exists( 'woocommerce_output_auth_header' ) ) {
2003
2004
	/**
2005
	 * Output the Auth header.
2006
	 */
2007
	function woocommerce_output_auth_header() {
2008
		wc_get_template( 'auth/header.php' );
2009
	}
2010
}
2011
2012
if ( ! function_exists( 'woocommerce_output_auth_footer' ) ) {
2013
2014
	/**
2015
	 * Output the Auth footer.
2016
	 */
2017
	function woocommerce_output_auth_footer() {
2018
		wc_get_template( 'auth/footer.php' );
2019
	}
2020
}
2021
2022
if ( ! function_exists( 'woocommerce_single_variation' ) ) {
2023
2024
	/**
2025
	 * Output placeholders for the single variation.
2026
	 */
2027
	function woocommerce_single_variation() {
2028
		echo '<div class="woocommerce-variation single_variation"></div>';
2029
	}
2030
}
2031
2032
if ( ! function_exists( 'woocommerce_single_variation_add_to_cart_button' ) ) {
2033
2034
	/**
2035
	 * Output the add to cart button for variations.
2036
	 */
2037
	function woocommerce_single_variation_add_to_cart_button() {
2038
		wc_get_template( 'single-product/add-to-cart/variation-add-to-cart-button.php' );
2039
	}
2040
}
2041
2042
if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
2043
2044
	/**
2045
	 * Output a list of variation attributes for use in the cart forms.
2046
	 *
2047
	 * @param array $args
2048
	 * @since 2.4.0
2049
	 */
2050
	function wc_dropdown_variation_attribute_options( $args = array() ) {
2051
		$args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array(
2052
			'options'          => false,
2053
			'attribute'        => false,
2054
			'product'          => false,
2055
			'selected' 	       => false,
2056
			'name'             => '',
2057
			'id'               => '',
2058
			'class'            => '',
2059
			'show_option_none' => __( 'Choose an option', 'woocommerce' )
2060
		) );
2061
2062
		$options   = $args['options'];
2063
		$product   = $args['product'];
2064
		$attribute = $args['attribute'];
2065
		$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
2066
		$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );
2067
		$class     = $args['class'];
2068
2069
		if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
2070
			$attributes = $product->get_variation_attributes();
2071
			$options    = $attributes[ $attribute ];
2072
		}
2073
2074
		$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '">';
2075
2076
		if ( $args['show_option_none'] ) {
2077
			$html .= '<option value="">' . esc_html( $args['show_option_none'] ) . '</option>';
2078
		}
2079
2080
		if ( ! empty( $options ) ) {
2081
			if ( $product && taxonomy_exists( $attribute ) ) {
2082
				// Get terms if this is a taxonomy - ordered. We need the names too.
2083
				$terms = wc_get_product_terms( $product->id, $attribute, array( 'fields' => 'all' ) );
2084
2085 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...
2086
					if ( in_array( $term->slug, $options ) ) {
2087
						$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>';
2088
					}
2089
				}
2090
			} else {
2091
				foreach ( $options as $option ) {
2092
					// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
2093
					$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
2094
					$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
2095
				}
2096
			}
2097
		}
2098
2099
		$html .= '</select>';
2100
2101
		echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
2102
	}
2103
}
2104
2105
if ( ! function_exists( 'woocommerce_account_content' ) ) {
2106
2107
	/**
2108
	 * My Account content output.
2109
	 */
2110
	function woocommerce_account_content() {
2111
		global $wp;
2112
2113
		foreach ( $wp->query_vars as $key => $value ) {
2114
			// Ignore pagename param.
2115
			if ( 'pagename' === $key ) {
2116
				continue;
2117
			}
2118
2119
			if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
2120
				do_action( 'woocommerce_account_' . $key . '_endpoint', $value );
2121
				return;
2122
			}
2123
		}
2124
2125
		// No endpoint found? Default to dashboard.
2126
		wc_get_template( 'myaccount/dashboard.php', array(
2127
			'current_user' => get_user_by( 'id', get_current_user_id() ),
2128
		) );
2129
	}
2130
}
2131
2132
if ( ! function_exists( 'woocommerce_account_navigation' ) ) {
2133
2134
	/**
2135
	 * My Account navigation template.
2136
	 */
2137
	function woocommerce_account_navigation() {
2138
		wc_get_template( 'myaccount/navigation.php' );
2139
	}
2140
}
2141
2142
if ( ! function_exists( 'woocommerce_account_orders' ) ) {
2143
2144
	/**
2145
	 * My Account > Orders template.
2146
	 *
2147
	 * @param int $current_page Current page number.
2148
	 */
2149
	function woocommerce_account_orders( $current_page ) {
2150
		$current_page    = empty( $current_page ) ? 1 : absint( $current_page );
2151
		$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 'customer' => get_current_user_id(), 'page' => $current_page, 'paginate' => true ) ) );
2152
2153
		wc_get_template(
2154
			'myaccount/orders.php',
2155
			array(
2156
				'current_page' => absint( $current_page ),
2157
				'customer_orders' => $customer_orders,
2158
				'has_orders' => 0 < $customer_orders->total,
2159
			)
2160
		);
2161
	}
2162
}
2163
2164
if ( ! function_exists( 'woocommerce_account_view_order' ) ) {
2165
2166
	/**
2167
	 * My Account > View order template.
2168
	 *
2169
	 * @param int $order_id Order ID.
2170
	 */
2171
	function woocommerce_account_view_order( $order_id ) {
2172
		WC_Shortcode_My_Account::view_order( absint( $order_id ) );
2173
	}
2174
}
2175
2176
if ( ! function_exists( 'woocommerce_account_downloads' ) ) {
2177
2178
	/**
2179
	 * My Account > Downloads template.
2180
	 */
2181
	function woocommerce_account_downloads() {
2182
		wc_get_template( 'myaccount/downloads.php' );
2183
	}
2184
}
2185
2186
if ( ! function_exists( 'woocommerce_account_edit_address' ) ) {
2187
2188
	/**
2189
	 * My Account > Edit address template.
2190
	 *
2191
	 * @param string $type Address type.
2192
	 */
2193
	function woocommerce_account_edit_address( $type ) {
2194
		$type = wc_edit_address_i18n( sanitize_title( $type ), true );
2195
2196
		WC_Shortcode_My_Account::edit_address( $type );
2197
	}
2198
}
2199
2200
if ( ! function_exists( 'woocommerce_account_payment_methods' ) ) {
2201
2202
	/**
2203
	 * My Account > Downloads template.
2204
	 */
2205
	function woocommerce_account_payment_methods() {
2206
		wc_get_template( 'myaccount/payment-methods.php' );
2207
	}
2208
}
2209
2210
if ( ! function_exists( 'woocommerce_account_add_payment_method' ) ) {
2211
2212
	/**
2213
	 * My Account > Add payment method template.
2214
	 */
2215
	function woocommerce_account_add_payment_method() {
2216
		WC_Shortcode_My_Account::add_payment_method();
2217
	}
2218
}
2219
2220
if ( ! function_exists( 'woocommerce_account_edit_account' ) ) {
2221
2222
	/**
2223
	 * My Account > Edit account template.
2224
	 */
2225
	function woocommerce_account_edit_account() {
2226
		WC_Shortcode_My_Account::edit_account();
2227
	}
2228
}
2229