Completed
Push — master ( 78ca4a...a32dd1 )
by Claudio
19s
created

wc-template-functions.php ➔ woocommerce_account_navigation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 20 and the first side effect is on line 14.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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' ) );
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 === $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' );
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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
 *
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
		$feed = add_query_arg('product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ));
153
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
	} elseif ( is_tax( 'product_tag' ) ) {
157
158
		$term = get_term_by('slug', esc_attr( get_query_var('product_tag') ), 'product_tag');
159
160
		$feed = add_query_arg('product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ));
161
162
		echo '<link rel="alternate" type="application/rss+xml"  title="' . sprintf(__( 'New products tagged %s', 'woocommerce' ), urlencode($term->name)) . '" href="' . esc_url( $feed ) . '" />';
163
164
	}
165
}
166
167
/**
168
 * Output generator tag to aid debugging.
169
 *
170
 * @access public
171
 */
172
function wc_generator_tag( $gen, $type ) {
173
	switch ( $type ) {
174
		case 'html':
175
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '">';
176
			break;
177
		case 'xhtml':
178
			$gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '" />';
179
			break;
180
	}
181
	return $gen;
182
}
183
184
/**
185
 * Add body classes for WC pages.
186
 *
187
 * @param  array $classes
188
 * @return array
189
 */
190
function wc_body_class( $classes ) {
191
	$classes = (array) $classes;
192
193
	if ( is_woocommerce() ) {
194
		$classes[] = 'woocommerce';
195
		$classes[] = 'woocommerce-page';
196
	}
197
198
	elseif ( is_checkout() ) {
199
		$classes[] = 'woocommerce-checkout';
200
		$classes[] = 'woocommerce-page';
201
	}
202
203
	elseif ( is_cart() ) {
204
		$classes[] = 'woocommerce-cart';
205
		$classes[] = 'woocommerce-page';
206
	}
207
208
	elseif ( is_account_page() ) {
209
		$classes[] = 'woocommerce-account';
210
		$classes[] = 'woocommerce-page';
211
	}
212
213
	if ( is_store_notice_showing() ) {
214
		$classes[] = 'woocommerce-demo-store';
215
	}
216
217
	foreach ( WC()->query->query_vars as $key => $value ) {
218
		if ( is_wc_endpoint_url( $key ) ) {
219
			$classes[] = 'woocommerce-' . sanitize_html_class( $key );
220
		}
221
	}
222
223
	return array_unique( $classes );
224
}
225
226
/**
227
 * Display the classes for the product cat div.
228
 *
229
 * @since 2.4.0
230
 * @param string|array $class One or more classes to add to the class list.
231
 * @param object $category object Optional.
232
 */
233
function wc_product_cat_class( $class = '', $category = null ) {
234
	// Separates classes with a single space, collates classes for post DIV
235
	echo 'class="' . esc_attr( join( ' ', wc_get_product_cat_class( $class, $category ) ) ) . '"';
236
}
237
238
/**
239
 * Get classname for loops based on $woocommerce_loop global.
240
 * @since 2.6.0
241
 * @return string
242
 */
243
function wc_get_loop_class() {
244
	global $woocommerce_loop;
245
246
	$woocommerce_loop['loop']    = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1   : 1;
247
	$woocommerce_loop['columns'] = ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 );
248
249
	if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) {
250
		return 'first';
251
	} elseif ( 0 === $woocommerce_loop['loop'] % $woocommerce_loop['columns'] ) {
252
		return 'last';
253
	} else {
254
		return '';
255
	}
256
}
257
258
/**
259
 * Get the classes for the product cat div.
260
 *
261
 * @since 2.4.0
262
 * @param string|array $class One or more classes to add to the class list.
263
 * @param object $category object Optional.
264
 */
265
function wc_get_product_cat_class( $class = '', $category = null ) {
266
	$classes   = is_array( $class ) ? $class : array_map( 'trim', explode( ' ', $class ) );
267
	$classes[] = 'product-category';
268
	$classes[] = 'product';
269
	$classes[] = wc_get_loop_class();
270
	$classes   = apply_filters( 'product_cat_class', $classes, $class, $category );
271
272
	return array_unique( array_filter( $classes ) );
273
}
274
275
/**
276
 * Adds extra post classes for products.
277
 *
278
 * @since 2.1.0
279
 * @param array $classes
280
 * @param string|array $class
281
 * @param int $post_id
282
 * @return array
283
 */
284
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...
285
	if ( ! $post_id || 'product' !== get_post_type( $post_id ) ) {
286
		return $classes;
287
	}
288
289
	$product = wc_get_product( $post_id );
290
291
	if ( $product ) {
292
		$classes[] = wc_get_loop_class();
293
		$classes[] = $product->stock_status;
294
295
		if ( $product->is_on_sale() ) {
296
			$classes[] = 'sale';
297
		}
298
		if ( $product->is_featured() ) {
299
			$classes[] = 'featured';
300
		}
301
		if ( $product->is_downloadable() ) {
302
			$classes[] = 'downloadable';
303
		}
304
		if ( $product->is_virtual() ) {
305
			$classes[] = 'virtual';
306
		}
307
		if ( $product->is_sold_individually() ) {
308
			$classes[] = 'sold-individually';
309
		}
310
		if ( $product->is_taxable() ) {
311
			$classes[] = 'taxable';
312
		}
313
		if ( $product->is_shipping_taxable() ) {
314
			$classes[] = 'shipping-taxable';
315
		}
316
		if ( $product->is_purchasable() ) {
317
			$classes[] = 'purchasable';
318
		}
319
		if ( $product->get_type() ) {
320
			$classes[] = "product-type-" . $product->get_type();
321
		}
322
		if ( $product->is_type( 'variable' ) ) {
323
			if ( $product->has_default_attributes() ) {
324
				$classes[] = 'has-default-attributes';
325
			}
326
			if ( $product->has_child() ) {
327
				$classes[] = 'has-children';
328
			}
329
		}
330
	}
331
332
	if ( false !== ( $key = array_search( 'hentry', $classes ) ) ) {
333
		unset( $classes[ $key ] );
334
	}
335
336
	return $classes;
337
}
338
339
/** Template pages ********************************************************/
340
341
if ( ! function_exists( 'woocommerce_content' ) ) {
342
343
	/**
344
	 * Output WooCommerce content.
345
	 *
346
	 * This function is only used in the optional 'woocommerce.php' template.
347
	 * which people can add to their themes to add basic woocommerce support.
348
	 * without hooks or modifying core templates.
349
	 *
350
	 */
351
	function woocommerce_content() {
352
353
		if ( is_singular( 'product' ) ) {
354
355
			while ( have_posts() ) : the_post();
356
357
				wc_get_template_part( 'content', 'single-product' );
358
359
			endwhile;
360
361
		} else { ?>
362
363
			<?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
364
365
				<h1 class="page-title"><?php woocommerce_page_title(); ?></h1>
366
367
			<?php endif; ?>
368
369
			<?php do_action( 'woocommerce_archive_description' ); ?>
370
371 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...
372
373
				<?php do_action('woocommerce_before_shop_loop'); ?>
374
375
				<?php woocommerce_product_loop_start(); ?>
376
377
					<?php woocommerce_product_subcategories(); ?>
378
379
					<?php while ( have_posts() ) : the_post(); ?>
380
381
						<?php wc_get_template_part( 'content', 'product' ); ?>
382
383
					<?php endwhile; // end of the loop. ?>
384
385
				<?php woocommerce_product_loop_end(); ?>
386
387
				<?php do_action('woocommerce_after_shop_loop'); ?>
388
389
			<?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
390
391
				<?php wc_get_template( 'loop/no-products-found.php' ); ?>
392
393
			<?php endif;
394
395
		}
396
	}
397
}
398
399
/** Global ****************************************************************/
400
401
if ( ! function_exists( 'woocommerce_output_content_wrapper' ) ) {
402
403
	/**
404
	 * Output the start of the page wrapper.
405
	 *
406
	 */
407
	function woocommerce_output_content_wrapper() {
408
		wc_get_template( 'global/wrapper-start.php' );
409
	}
410
}
411
if ( ! function_exists( 'woocommerce_output_content_wrapper_end' ) ) {
412
413
	/**
414
	 * Output the end of the page wrapper.
415
	 *
416
	 */
417
	function woocommerce_output_content_wrapper_end() {
418
		wc_get_template( 'global/wrapper-end.php' );
419
	}
420
}
421
422
if ( ! function_exists( 'woocommerce_get_sidebar' ) ) {
423
424
	/**
425
	 * Get the shop sidebar template.
426
	 *
427
	 */
428
	function woocommerce_get_sidebar() {
429
		wc_get_template( 'global/sidebar.php' );
430
	}
431
}
432
433
if ( ! function_exists( 'woocommerce_demo_store' ) ) {
434
435
	/**
436
	 * Adds a demo store banner to the site if enabled.
437
	 *
438
	 */
439
	function woocommerce_demo_store() {
440
		if ( ! is_store_notice_showing() ) {
441
			return;
442
		}
443
444
		$notice = get_option( 'woocommerce_demo_store_notice' );
445
446
		if ( empty( $notice ) ) {
447
			$notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
448
		}
449
450
		echo apply_filters( 'woocommerce_demo_store', '<p class="demo_store">' . wp_kses_post( $notice ) . '</p>'  );
451
	}
452
}
453
454
/** Loop ******************************************************************/
455
456
if ( ! function_exists( 'woocommerce_page_title' ) ) {
457
458
	/**
459
	 * woocommerce_page_title function.
460
	 *
461
	 * @param  bool $echo
462
	 * @return string
463
	 */
464
	function woocommerce_page_title( $echo = true ) {
465
466
		if ( is_search() ) {
467
			$page_title = sprintf( __( 'Search Results: &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() );
468
469
			if ( get_query_var( 'paged' ) )
470
				$page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'woocommerce' ), get_query_var( 'paged' ) );
471
472
		} elseif ( is_tax() ) {
473
474
			$page_title = single_term_title( "", false );
475
476
		} else {
477
478
			$shop_page_id = wc_get_page_id( 'shop' );
479
			$page_title   = get_the_title( $shop_page_id );
480
481
		}
482
483
		$page_title = apply_filters( 'woocommerce_page_title', $page_title );
484
485
		if ( $echo )
486
	    	echo $page_title;
487
	    else
488
	    	return $page_title;
489
	}
490
}
491
492
if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
493
494
	/**
495
	 * Output the start of a product loop. By default this is a UL.
496
	 *
497
	 * @param bool $echo
498
	 * @return string
499
	 */
500
	function woocommerce_product_loop_start( $echo = true ) {
501
		ob_start();
502
		$GLOBALS['woocommerce_loop']['loop'] = 0;
503
		wc_get_template( 'loop/loop-start.php' );
504
		if ( $echo )
505
			echo ob_get_clean();
506
		else
507
			return ob_get_clean();
508
	}
509
}
510
if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
511
512
	/**
513
	 * Output the end of a product loop. By default this is a UL.
514
	 *
515
	 * @param bool $echo
516
	 * @return string
517
	 */
518
	function woocommerce_product_loop_end( $echo = true ) {
519
		ob_start();
520
521
		wc_get_template( 'loop/loop-end.php' );
522
523
		if ( $echo )
524
			echo ob_get_clean();
525
		else
526
			return ob_get_clean();
527
	}
528
}
529
if (  ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
530
531
	/**
532
	 * Show the product title in the product loop. By default this is an H3.
533
	 */
534
	function woocommerce_template_loop_product_title() {
535
		echo '<h3>' . get_the_title() . '</h3>';
536
	}
537
}
538
if (  ! function_exists( 'woocommerce_template_loop_category_title' ) ) {
539
540
	/**
541
	 * Show the subcategory title in the product loop.
542
	 */
543
	function woocommerce_template_loop_category_title( $category ) {
544
		?>
545
		<h3>
546
			<?php
547
				echo $category->name;
548
549
				if ( $category->count > 0 )
550
					echo apply_filters( 'woocommerce_subcategory_count_html', ' <mark class="count">(' . $category->count . ')</mark>', $category );
551
			?>
552
		</h3>
553
		<?php
554
	}
555
}
556
/**
557
 * Insert the opening anchor tag for products in the loop.
558
 */
559
function woocommerce_template_loop_product_link_open() {
560
	echo '<a href="' . get_the_permalink() . '" class="woocommerce-LoopProduct-link">';
561
}
562
/**
563
 * Insert the opening anchor tag for products in the loop.
564
 */
565
function woocommerce_template_loop_product_link_close() {
566
	echo '</a>';
567
}
568
/**
569
 * Insert the opening anchor tag for categories in the loop.
570
 */
571
function woocommerce_template_loop_category_link_open( $category ) {
572
	echo '<a href="' . get_term_link( $category, 'product_cat' ) . '">';
573
}
574
/**
575
 * Insert the opening anchor tag for categories in the loop.
576
 */
577
function woocommerce_template_loop_category_link_close() {
578
	echo '</a>';
579
}
580
if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
581
582
	/**
583
	 * Show an archive description on taxonomy archives.
584
	 *
585
	 * @subpackage	Archives
586
	 */
587
	function woocommerce_taxonomy_archive_description() {
588
		if ( is_tax( array( 'product_cat', 'product_tag' ) ) && 0 === absint( get_query_var( 'paged' ) ) ) {
589
			$description = wc_format_content( term_description() );
590
			if ( $description ) {
591
				echo '<div class="term-description">' . $description . '</div>';
592
			}
593
		}
594
	}
595
}
596
if ( ! function_exists( 'woocommerce_product_archive_description' ) ) {
597
598
	/**
599
	 * Show a shop page description on product archives.
600
	 *
601
	 * @subpackage	Archives
602
	 */
603
	function woocommerce_product_archive_description() {
604
		if ( is_post_type_archive( 'product' ) && 0 === absint( get_query_var( 'paged' ) ) ) {
605
			$shop_page   = get_post( wc_get_page_id( 'shop' ) );
606
			if ( $shop_page ) {
607
				$description = wc_format_content( $shop_page->post_content );
608
				if ( $description ) {
609
					echo '<div class="page-description">' . $description . '</div>';
610
				}
611
			}
612
		}
613
	}
614
}
615
616
if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
617
618
	/**
619
	 * Get the add to cart template for the loop.
620
	 *
621
	 * @subpackage	Loop
622
	 */
623
	function woocommerce_template_loop_add_to_cart( $args = array() ) {
624
		global $product;
625
626
		if ( $product ) {
627
			$defaults = array(
628
				'quantity' => 1,
629
				'class'    => implode( ' ', array_filter( array(
630
						'button',
631
						'product_type_' . $product->product_type,
632
						$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '',
633
						$product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : ''
634
				) ) )
635
			);
636
637
			$args = apply_filters( 'woocommerce_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product );
638
639
			wc_get_template( 'loop/add-to-cart.php', $args );
640
		}
641
	}
642
}
643
if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) {
644
645
	/**
646
	 * Get the product thumbnail for the loop.
647
	 *
648
	 * @subpackage	Loop
649
	 */
650
	function woocommerce_template_loop_product_thumbnail() {
651
		echo woocommerce_get_product_thumbnail();
652
	}
653
}
654
if ( ! function_exists( 'woocommerce_template_loop_price' ) ) {
655
656
	/**
657
	 * Get the product price for the loop.
658
	 *
659
	 * @subpackage	Loop
660
	 */
661
	function woocommerce_template_loop_price() {
662
		wc_get_template( 'loop/price.php' );
663
	}
664
}
665
if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) {
666
667
	/**
668
	 * Display the average rating in the loop.
669
	 *
670
	 * @subpackage	Loop
671
	 */
672
	function woocommerce_template_loop_rating() {
673
		wc_get_template( 'loop/rating.php' );
674
	}
675
}
676
if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) {
677
678
	/**
679
	 * Get the sale flash for the loop.
680
	 *
681
	 * @subpackage	Loop
682
	 */
683
	function woocommerce_show_product_loop_sale_flash() {
684
		wc_get_template( 'loop/sale-flash.php' );
685
	}
686
}
687
688
if ( ! function_exists( 'woocommerce_get_product_schema' ) ) {
689
690
	/**
691
	 * Get a products Schema.
692
	 * @return string
693
	 */
694
	function woocommerce_get_product_schema() {
695
		global $product;
696
697
		$schema = "Product";
698
699
		// Downloadable product schema handling
700
		if ( $product->is_downloadable() ) {
701
			switch ( $product->download_type ) {
702
				case 'application' :
703
					$schema = "SoftwareApplication";
704
				break;
705
				case 'music' :
706
					$schema = "MusicAlbum";
707
				break;
708
				default :
709
					$schema = "Product";
710
				break;
711
			}
712
		}
713
714
		return 'http://schema.org/' . $schema;
715
	}
716
}
717
718
if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
719
720
	/**
721
	 * Get the product thumbnail, or the placeholder if not set.
722
	 *
723
	 * @subpackage	Loop
724
	 * @param string $size (default: 'shop_catalog')
725
	 * @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0)
726
	 * @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0)
727
	 * @return string
728
	 */
729
	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...
730
		global $post;
731
		$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
732
733
		if ( has_post_thumbnail() ) {
734
			$props = wc_get_product_attachment_props( get_post_thumbnail_id(), $post );
735
			return get_the_post_thumbnail( $post->ID, $image_size, array(
736
				'title'	 => $props['title'],
737
				'alt'    => $props['alt'],
738
			) );
739
		} elseif ( wc_placeholder_img_src() ) {
740
			return wc_placeholder_img( $image_size );
741
		}
742
	}
743
}
744
745
if ( ! function_exists( 'woocommerce_result_count' ) ) {
746
747
	/**
748
	 * Output the result count text (Showing x - x of x results).
749
	 *
750
	 * @subpackage	Loop
751
	 */
752
	function woocommerce_result_count() {
753
		wc_get_template( 'loop/result-count.php' );
754
	}
755
}
756
757
if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
758
759
	/**
760
	 * Output the product sorting options.
761
	 *
762
	 * @subpackage	Loop
763
	 */
764
	function woocommerce_catalog_ordering() {
765
		global $wp_query;
766
767
		if ( 1 === $wp_query->found_posts || ! woocommerce_products_will_display() ) {
768
			return;
769
		}
770
771
		$orderby                 = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
772
		$show_default_orderby    = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
773
		$catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array(
774
			'menu_order' => __( 'Default sorting', 'woocommerce' ),
775
			'popularity' => __( 'Sort by popularity', 'woocommerce' ),
776
			'rating'     => __( 'Sort by average rating', 'woocommerce' ),
777
			'date'       => __( 'Sort by newness', 'woocommerce' ),
778
			'price'      => __( 'Sort by price: low to high', 'woocommerce' ),
779
			'price-desc' => __( 'Sort by price: high to low', 'woocommerce' )
780
		) );
781
782
		if ( ! $show_default_orderby ) {
783
			unset( $catalog_orderby_options['menu_order'] );
784
		}
785
786
		if ( 'no' === get_option( 'woocommerce_enable_review_rating' ) ) {
787
			unset( $catalog_orderby_options['rating'] );
788
		}
789
790
		wc_get_template( 'loop/orderby.php', array( 'catalog_orderby_options' => $catalog_orderby_options, 'orderby' => $orderby, 'show_default_orderby' => $show_default_orderby ) );
791
	}
792
}
793
794
if ( ! function_exists( 'woocommerce_pagination' ) ) {
795
796
	/**
797
	 * Output the pagination.
798
	 *
799
	 * @subpackage	Loop
800
	 */
801
	function woocommerce_pagination() {
802
		wc_get_template( 'loop/pagination.php' );
803
	}
804
}
805
806
/** Single Product ********************************************************/
807
808
if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
809
810
	/**
811
	 * Output the product image before the single product summary.
812
	 *
813
	 * @subpackage	Product
814
	 */
815
	function woocommerce_show_product_images() {
816
		wc_get_template( 'single-product/product-image.php' );
817
	}
818
}
819
if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) {
820
821
	/**
822
	 * Output the product thumbnails.
823
	 *
824
	 * @subpackage	Product
825
	 */
826
	function woocommerce_show_product_thumbnails() {
827
		wc_get_template( 'single-product/product-thumbnails.php' );
828
	}
829
}
830
if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
831
832
	/**
833
	 * Output the product tabs.
834
	 *
835
	 * @subpackage	Product/Tabs
836
	 */
837
	function woocommerce_output_product_data_tabs() {
838
		wc_get_template( 'single-product/tabs/tabs.php' );
839
	}
840
}
841
if ( ! function_exists( 'woocommerce_template_single_title' ) ) {
842
843
	/**
844
	 * Output the product title.
845
	 *
846
	 * @subpackage	Product
847
	 */
848
	function woocommerce_template_single_title() {
849
		wc_get_template( 'single-product/title.php' );
850
	}
851
}
852
if ( ! function_exists( 'woocommerce_template_single_rating' ) ) {
853
854
	/**
855
	 * Output the product rating.
856
	 *
857
	 * @subpackage	Product
858
	 */
859
	function woocommerce_template_single_rating() {
860
		wc_get_template( 'single-product/rating.php' );
861
	}
862
}
863
if ( ! function_exists( 'woocommerce_template_single_price' ) ) {
864
865
	/**
866
	 * Output the product price.
867
	 *
868
	 * @subpackage	Product
869
	 */
870
	function woocommerce_template_single_price() {
871
		wc_get_template( 'single-product/price.php' );
872
	}
873
}
874
if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) {
875
876
	/**
877
	 * Output the product short description (excerpt).
878
	 *
879
	 * @subpackage	Product
880
	 */
881
	function woocommerce_template_single_excerpt() {
882
		wc_get_template( 'single-product/short-description.php' );
883
	}
884
}
885
if ( ! function_exists( 'woocommerce_template_single_meta' ) ) {
886
887
	/**
888
	 * Output the product meta.
889
	 *
890
	 * @subpackage	Product
891
	 */
892
	function woocommerce_template_single_meta() {
893
		wc_get_template( 'single-product/meta.php' );
894
	}
895
}
896
if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) {
897
898
	/**
899
	 * Output the product sharing.
900
	 *
901
	 * @subpackage	Product
902
	 */
903
	function woocommerce_template_single_sharing() {
904
		wc_get_template( 'single-product/share.php' );
905
	}
906
}
907
if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) {
908
909
	/**
910
	 * Output the product sale flash.
911
	 *
912
	 * @subpackage	Product
913
	 */
914
	function woocommerce_show_product_sale_flash() {
915
		wc_get_template( 'single-product/sale-flash.php' );
916
	}
917
}
918
919
if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) {
920
921
	/**
922
	 * Trigger the single product add to cart action.
923
	 *
924
	 * @subpackage	Product
925
	 */
926
	function woocommerce_template_single_add_to_cart() {
927
		global $product;
928
		do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );
929
	}
930
}
931
if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) {
932
933
	/**
934
	 * Output the simple product add to cart area.
935
	 *
936
	 * @subpackage	Product
937
	 */
938
	function woocommerce_simple_add_to_cart() {
939
		wc_get_template( 'single-product/add-to-cart/simple.php' );
940
	}
941
}
942
if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
943
944
	/**
945
	 * Output the grouped product add to cart area.
946
	 *
947
	 * @subpackage	Product
948
	 */
949
	function woocommerce_grouped_add_to_cart() {
950
		global $product;
951
952
		wc_get_template( 'single-product/add-to-cart/grouped.php', array(
953
			'grouped_product'    => $product,
954
			'grouped_products'   => $product->get_children(),
955
			'quantites_required' => false
956
		) );
957
	}
958
}
959
if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) {
960
961
	/**
962
	 * Output the variable product add to cart area.
963
	 *
964
	 * @subpackage	Product
965
	 */
966
	function woocommerce_variable_add_to_cart() {
967
		global $product;
968
969
		// Enqueue variation scripts
970
		wp_enqueue_script( 'wc-add-to-cart-variation' );
971
972
		// Get Available variations?
973
		$get_variations = sizeof( $product->get_children() ) <= apply_filters( 'woocommerce_ajax_variation_threshold', 30, $product );
974
975
		// Load the template
976
		wc_get_template( 'single-product/add-to-cart/variable.php', array(
977
			'available_variations' => $get_variations ? $product->get_available_variations() : false,
978
			'attributes'           => $product->get_variation_attributes(),
979
			'selected_attributes'  => $product->get_variation_default_attributes()
980
		) );
981
	}
982
}
983
if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) {
984
985
	/**
986
	 * Output the external product add to cart area.
987
	 *
988
	 * @subpackage	Product
989
	 */
990
	function woocommerce_external_add_to_cart() {
991
		global $product;
992
993
		if ( ! $product->add_to_cart_url() ) {
994
			return;
995
		}
996
997
		wc_get_template( 'single-product/add-to-cart/external.php', array(
998
			'product_url' => $product->add_to_cart_url(),
999
			'button_text' => $product->single_add_to_cart_text()
1000
		) );
1001
	}
1002
}
1003
1004
if ( ! function_exists( 'woocommerce_quantity_input' ) ) {
1005
1006
	/**
1007
	 * Output the quantity input for add to cart forms.
1008
	 *
1009
	 * @param  array $args Args for the input
1010
	 * @param  WC_Product|null $product
1011
	 * @param  boolean $echo Whether to return or echo|string
1012
	 */
1013
	function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
1014
		if ( is_null( $product ) ) {
1015
			$product = $GLOBALS['product'];
1016
		}
1017
1018
		$defaults = array(
1019
			'input_name'  => 'quantity',
1020
			'input_value' => '1',
1021
			'max_value'   => apply_filters( 'woocommerce_quantity_input_max', '', $product ),
1022
			'min_value'   => apply_filters( 'woocommerce_quantity_input_min', '', $product ),
1023
			'step'        => apply_filters( 'woocommerce_quantity_input_step', '1', $product ),
1024
			'pattern'     => apply_filters( 'woocommerce_quantity_input_pattern', has_filter( 'woocommerce_stock_amount', 'intval' ) ? '[0-9]*' : '' ),
1025
			'inputmode'   => apply_filters( 'woocommerce_quantity_input_inputmode', has_filter( 'woocommerce_stock_amount', 'intval' ) ? 'numeric' : '' ),
1026
		);
1027
1028
		$args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
1029
1030
		// Apply sanity to min/max args - min cannot be lower than 0
1031
		if ( '' !== $args['min_value'] && is_numeric( $args['min_value'] ) && $args['min_value'] < 0 ) {
1032
			$args['min_value'] = 0; // Cannot be lower than 0
1033
		}
1034
1035
		// Max cannot be lower than 0 or min
1036
		if ( '' !== $args['max_value'] && is_numeric( $args['max_value'] ) ) {
1037
			$args['max_value'] = $args['max_value'] < 0 ? 0 : $args['max_value'];
1038
			$args['max_value'] = $args['max_value'] < $args['min_value'] ? $args['min_value'] : $args['max_value'];
1039
		}
1040
1041
		ob_start();
1042
1043
		wc_get_template( 'global/quantity-input.php', $args );
1044
1045
		if ( $echo ) {
1046
			echo ob_get_clean();
1047
		} else {
1048
			return ob_get_clean();
1049
		}
1050
	}
1051
}
1052
1053
if ( ! function_exists( 'woocommerce_product_description_tab' ) ) {
1054
1055
	/**
1056
	 * Output the description tab content.
1057
	 *
1058
	 * @subpackage	Product/Tabs
1059
	 */
1060
	function woocommerce_product_description_tab() {
1061
		wc_get_template( 'single-product/tabs/description.php' );
1062
	}
1063
}
1064
if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
1065
1066
	/**
1067
	 * Output the attributes tab content.
1068
	 *
1069
	 * @subpackage	Product/Tabs
1070
	 */
1071
	function woocommerce_product_additional_information_tab() {
1072
		wc_get_template( 'single-product/tabs/additional-information.php' );
1073
	}
1074
}
1075
if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
1076
1077
	/**
1078
	 * Output the reviews tab content.
1079
	 * @deprecated  2.4.0 Unused
1080
	 * @subpackage	Product/Tabs
1081
	 */
1082
	function woocommerce_product_reviews_tab() {
1083
		_deprecated_function( 'woocommerce_product_reviews_tab', '2.4', '' );
1084
	}
1085
}
1086
1087
if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
1088
1089
	/**
1090
	 * Add default product tabs to product pages.
1091
	 *
1092
	 * @param array $tabs
1093
	 * @return array
1094
	 */
1095
	function woocommerce_default_product_tabs( $tabs = array() ) {
1096
		global $product, $post;
1097
1098
		// Description tab - shows product content
1099
		if ( $post->post_content ) {
1100
			$tabs['description'] = array(
1101
				'title'    => __( 'Description', 'woocommerce' ),
1102
				'priority' => 10,
1103
				'callback' => 'woocommerce_product_description_tab'
1104
			);
1105
		}
1106
1107
		// Additional information tab - shows attributes
1108
		if ( $product && ( $product->has_attributes() || ( $product->enable_dimensions_display() && ( $product->has_dimensions() || $product->has_weight() ) ) ) ) {
1109
			$tabs['additional_information'] = array(
1110
				'title'    => __( 'Additional Information', 'woocommerce' ),
1111
				'priority' => 20,
1112
				'callback' => 'woocommerce_product_additional_information_tab'
1113
			);
1114
		}
1115
1116
		// Reviews tab - shows comments
1117
		if ( comments_open() ) {
1118
			$tabs['reviews'] = array(
1119
				'title'    => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ),
1120
				'priority' => 30,
1121
				'callback' => 'comments_template'
1122
			);
1123
		}
1124
1125
		return $tabs;
1126
	}
1127
}
1128
1129
if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) {
1130
1131
	/**
1132
	 * Sort tabs by priority.
1133
	 *
1134
	 * @param array $tabs
1135
	 * @return array
1136
	 */
1137
	function woocommerce_sort_product_tabs( $tabs = array() ) {
1138
1139
		// Make sure the $tabs parameter is an array
1140
		if ( ! is_array( $tabs ) ) {
1141
			trigger_error( "Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array." );
1142
			$tabs = array( );
1143
		}
1144
1145
		// Re-order tabs by priority
1146
		if ( ! function_exists( '_sort_priority_callback' ) ) {
1147
			function _sort_priority_callback( $a, $b ) {
1148
				if ( $a['priority'] === $b['priority'] )
1149
			        return 0;
1150
			    return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
1151
			}
1152
		}
1153
1154
		uasort( $tabs, '_sort_priority_callback' );
1155
1156
		return $tabs;
1157
	}
1158
}
1159
1160
if ( ! function_exists( 'woocommerce_comments' ) ) {
1161
1162
	/**
1163
	 * Output the Review comments template.
1164
	 *
1165
	 * @subpackage	Product
1166
	 * @param WP_Comment $comment
1167
	 * @param array $args
1168
	 * @param int $depth
1169
	 */
1170
	function woocommerce_comments( $comment, $args, $depth ) {
1171
		$GLOBALS['comment'] = $comment;
1172
		wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) );
1173
	}
1174
}
1175
1176
if ( ! function_exists( 'woocommerce_review_display_gravatar' ) ) {
1177
	/**
1178
	 * Display the review authors gravatar
1179
	 *
1180
	 * @param array $comment WP_Comment.
1181
	 * @return void
1182
	 */
1183
	function woocommerce_review_display_gravatar( $comment ) {
1184
		echo get_avatar( $comment, apply_filters( 'woocommerce_review_gravatar_size', '60' ), '' );
1185
	}
1186
}
1187
1188
if ( ! function_exists( 'woocommerce_review_display_rating' ) ) {
1189
	/**
1190
	 * Display the reviewers star rating
1191
	 *
1192
	 * @return void
1193
	 */
1194
	function woocommerce_review_display_rating() {
1195
		wc_get_template( 'single-product/review-rating.php' );
1196
	}
1197
}
1198
1199
if ( ! function_exists( 'woocommerce_review_display_meta' ) ) {
1200
	/**
1201
	 * Display the review authors meta (name, verified owner, review date)
1202
	 *
1203
	 * @return void
1204
	 */
1205
	function woocommerce_review_display_meta() {
1206
		wc_get_template( 'single-product/review-meta.php' );
1207
	}
1208
}
1209
1210
if ( ! function_exists( 'woocommerce_review_display_comment_text' ) ) {
1211
	/**
1212
	 * Display the review content
1213
	 *
1214
	 * @return void
1215
	 */
1216
	function woocommerce_review_display_comment_text() {
1217
		echo '<div itemprop="description" class="description">' . comment_text() . '</div>';
1218
	}
1219
}
1220
1221
if ( ! function_exists( 'woocommerce_output_related_products' ) ) {
1222
1223
	/**
1224
	 * Output the related products.
1225
	 *
1226
	 * @subpackage	Product
1227
	 */
1228
	function woocommerce_output_related_products() {
1229
1230
		$args = array(
1231
			'posts_per_page' 	=> 4,
1232
			'columns' 			=> 4,
1233
			'orderby' 			=> 'rand'
1234
		);
1235
1236
		woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) );
1237
	}
1238
}
1239
1240
if ( ! function_exists( 'woocommerce_related_products' ) ) {
1241
1242
	/**
1243
	 * Output the related products.
1244
	 *
1245
	 * @param array Provided arguments
1246
	 * @param bool Columns argument for backwards compat
1247
	 * @param bool Order by argument for backwards compat
1248
	 */
1249
	function woocommerce_related_products( $args = array(), $columns = false, $orderby = false ) {
1250
		if ( ! is_array( $args ) ) {
1251
			_deprecated_argument( __FUNCTION__, '2.1', __( 'Use $args argument as an array instead. Deprecated argument will be removed in WC 2.2.', 'woocommerce' ) );
1252
1253
			$argsvalue = $args;
1254
1255
			$args = array(
1256
				'posts_per_page' => $argsvalue,
1257
				'columns'        => $columns,
1258
				'orderby'        => $orderby,
1259
			);
1260
		}
1261
1262
		$defaults = array(
1263
			'posts_per_page' => 2,
1264
			'columns'        => 2,
1265
			'orderby'        => 'rand'
1266
		);
1267
1268
		$args = wp_parse_args( $args, $defaults );
1269
1270
		wc_get_template( 'single-product/related.php', $args );
1271
	}
1272
}
1273
1274
if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
1275
1276
	/**
1277
	 * Output product up sells.
1278
	 *
1279
	 * @param int $posts_per_page (default: -1)
1280
	 * @param int $columns (default: 4)
1281
	 * @param string $orderby (default: 'rand')
1282
	 */
1283
	function woocommerce_upsell_display( $posts_per_page = '-1', $columns = 4, $orderby = 'rand' ) {
1284
		$args = apply_filters( 'woocommerce_upsell_display_args', array(
1285
			'posts_per_page'	=> $posts_per_page,
1286
			'orderby'			=> apply_filters( 'woocommerce_upsells_orderby', $orderby ),
1287
			'columns'			=> $columns
1288
		) );
1289
1290
		wc_get_template( 'single-product/up-sells.php', $args );
1291
	}
1292
}
1293
1294
/** Cart ******************************************************************/
1295
1296
if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) {
1297
1298
	/**
1299
	 * Output the cart shipping calculator.
1300
	 *
1301
	 * @subpackage	Cart
1302
	 */
1303
	function woocommerce_shipping_calculator() {
1304
		wc_get_template( 'cart/shipping-calculator.php' );
1305
	}
1306
}
1307
1308
if ( ! function_exists( 'woocommerce_cart_totals' ) ) {
1309
1310
	/**
1311
	 * Output the cart totals.
1312
	 *
1313
	 * @subpackage	Cart
1314
	 */
1315
	function woocommerce_cart_totals() {
1316
		wc_get_template( 'cart/cart-totals.php' );
1317
	}
1318
}
1319
1320
if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
1321
1322
	/**
1323
	 * Output the cart cross-sells.
1324
	 *
1325
	 * @param  int $posts_per_page (default: 2)
1326
	 * @param  int $columns (default: 2)
1327
	 * @param  string $orderby (default: 'rand')
1328
	 */
1329
	function woocommerce_cross_sell_display( $posts_per_page = 2, $columns = 2, $orderby = 'rand' ) {
1330
		wc_get_template( 'cart/cross-sells.php', array(
1331
				'posts_per_page' => $posts_per_page,
1332
				'orderby'        => $orderby,
1333
				'columns'        => $columns
1334
			) );
1335
	}
1336
}
1337
1338
if ( ! function_exists( 'woocommerce_button_proceed_to_checkout' ) ) {
1339
1340
	/**
1341
	 * Output the proceed to checkout button.
1342
	 *
1343
	 * @subpackage	Cart
1344
	 */
1345
	function woocommerce_button_proceed_to_checkout() {
1346
		wc_get_template( 'cart/proceed-to-checkout-button.php' );
1347
	}
1348
}
1349
1350
1351
1352
/** Mini-Cart *************************************************************/
1353
1354
if ( ! function_exists( 'woocommerce_mini_cart' ) ) {
1355
1356
	/**
1357
	 * Output the Mini-cart - used by cart widget.
1358
	 *
1359
	 * @param array $args
1360
	 */
1361
	function woocommerce_mini_cart( $args = array() ) {
1362
1363
		$defaults = array(
1364
			'list_class' => ''
1365
		);
1366
1367
		$args = wp_parse_args( $args, $defaults );
1368
1369
		wc_get_template( 'cart/mini-cart.php', $args );
1370
	}
1371
}
1372
1373
/** Login *****************************************************************/
1374
1375
if ( ! function_exists( 'woocommerce_login_form' ) ) {
1376
1377
	/**
1378
	 * Output the WooCommerce Login Form.
1379
	 *
1380
	 * @subpackage	Forms
1381
	 * @param array $args
1382
	 */
1383
	function woocommerce_login_form( $args = array() ) {
1384
1385
		$defaults = array(
1386
			'message'  => '',
1387
			'redirect' => '',
1388
			'hidden'   => false
1389
		);
1390
1391
		$args = wp_parse_args( $args, $defaults  );
1392
1393
		wc_get_template( 'global/form-login.php', $args );
1394
	}
1395
}
1396
1397
if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) {
1398
1399
	/**
1400
	 * Output the WooCommerce Checkout Login Form.
1401
	 *
1402
	 * @subpackage	Checkout
1403
	 */
1404
	function woocommerce_checkout_login_form() {
1405
		wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) );
1406
	}
1407
}
1408
1409
if ( ! function_exists( 'woocommerce_breadcrumb' ) ) {
1410
1411
	/**
1412
	 * Output the WooCommerce Breadcrumb.
1413
	 *
1414
	 * @param array $args
1415
	 */
1416
	function woocommerce_breadcrumb( $args = array() ) {
1417
		$args = wp_parse_args( $args, apply_filters( 'woocommerce_breadcrumb_defaults', array(
1418
			'delimiter'   => '&nbsp;&#47;&nbsp;',
1419
			'wrap_before' => '<nav class="woocommerce-breadcrumb" ' . ( is_single() ? 'itemprop="breadcrumb"' : '' ) . '>',
1420
			'wrap_after'  => '</nav>',
1421
			'before'      => '',
1422
			'after'       => '',
1423
			'home'        => _x( 'Home', 'breadcrumb', 'woocommerce' )
1424
		) ) );
1425
1426
		$breadcrumbs = new WC_Breadcrumb();
1427
1428
		if ( $args['home'] ) {
1429
			$breadcrumbs->add_crumb( $args['home'], apply_filters( 'woocommerce_breadcrumb_home_url', home_url() ) );
1430
		}
1431
1432
		$args['breadcrumb'] = $breadcrumbs->generate();
1433
1434
		wc_get_template( 'global/breadcrumb.php', $args );
1435
	}
1436
}
1437
1438
if ( ! function_exists( 'woocommerce_order_review' ) ) {
1439
1440
	/**
1441
	 * Output the Order review table for the checkout.
1442
	 *
1443
	 * @subpackage	Checkout
1444
	 */
1445
	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...
1446
		wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
1447
	}
1448
}
1449
1450
if ( ! function_exists( 'woocommerce_checkout_payment' ) ) {
1451
1452
	/**
1453
	 * Output the Payment Methods on the checkout.
1454
	 *
1455
	 * @subpackage	Checkout
1456
	 */
1457
	function woocommerce_checkout_payment() {
1458
		if ( WC()->cart->needs_payment() ) {
1459
			$available_gateways = WC()->payment_gateways()->get_available_payment_gateways();
1460
			WC()->payment_gateways()->set_current_gateway( $available_gateways );
1461
		} else {
1462
			$available_gateways = array();
0 ignored issues
show
Unused Code introduced by
$available_gateways is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1463
		}
1464
1465
		wc_get_template( 'checkout/payment.php', array(
1466
			'checkout'           => WC()->checkout(),
1467
			'available_gateways' => WC()->payment_gateways()->get_available_payment_gateways(),
1468
			'order_button_text'  => apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) )
1469
		) );
1470
	}
1471
}
1472
1473
if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
1474
1475
	/**
1476
	 * Output the Coupon form for the checkout.
1477
	 *
1478
	 * @subpackage	Checkout
1479
	 */
1480
	function woocommerce_checkout_coupon_form() {
1481
		wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) );
1482
	}
1483
}
1484
1485
if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
1486
1487
	/**
1488
	 * Check if we will be showing products or not (and not sub-categories only).
1489
	 * @subpackage	Loop
1490
	 * @return bool
1491
	 */
1492
	function woocommerce_products_will_display() {
1493
		global $wpdb;
1494
1495
		if ( is_shop() ) {
1496
			return 'subcategories' !== get_option( 'woocommerce_shop_page_display' ) || is_search();
1497
		}
1498
1499
		if ( ! is_product_taxonomy() ) {
1500
			return false;
1501
		}
1502
1503
		if ( is_search() || is_filtered() || is_paged() ) {
1504
			return true;
1505
		}
1506
1507
		$term = get_queried_object();
1508
1509
		if ( is_product_category() ) {
1510
			switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
1511
				case 'subcategories' :
1512
					// Nothing - we want to continue to see if there are products/subcats
1513
				break;
1514
				case 'products' :
1515
				case 'both' :
1516
					return true;
1517
				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...
1518
				default :
1519
					// Default - no setting
1520
					if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) {
1521
						return true;
1522
					}
1523
				break;
1524
			}
1525
		}
1526
1527
		// Begin subcategory logic
1528
		if ( empty( $term->term_id ) || empty( $term->taxonomy ) ) {
1529
			return true;
1530
		}
1531
1532
		$transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' );
1533
1534
		if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) {
1535
			$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 ) );
1536
1537
			if ( $has_children ) {
1538
				// Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
1539
				if ( sizeof( get_objects_in_term( $has_children, $term->taxonomy ) ) > 0 ) {
1540
					$products_will_display = false;
1541
				} else {
1542
					// If we get here, the parents were empty so we're forced to check children
1543
					foreach ( $has_children as $term_id ) {
1544
						$children = get_term_children( $term_id, $term->taxonomy );
1545
1546
						if ( sizeof( get_objects_in_term( $children, $term->taxonomy ) ) > 0 ) {
1547
							$products_will_display = false;
1548
							break;
1549
						}
1550
					}
1551
				}
1552
			} else {
1553
				$products_will_display = true;
1554
			}
1555
		}
1556
1557
		set_transient( $transient_name, $products_will_display, DAY_IN_SECONDS * 30 );
1558
1559
		return $products_will_display;
1560
	}
1561
}
1562
1563
if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
1564
1565
	/**
1566
	 * Display product sub categories as thumbnails.
1567
	 *
1568
	 * @subpackage	Loop
1569
	 * @param array $args
1570
	 * @return null|boolean
1571
	 */
1572
	function woocommerce_product_subcategories( $args = array() ) {
1573
		global $wp_query;
1574
1575
		$defaults = array(
1576
			'before'        => '',
1577
			'after'         => '',
1578
			'force_display' => false
1579
		);
1580
1581
		$args = wp_parse_args( $args, $defaults );
1582
1583
		extract( $args );
1584
1585
		// Main query only
1586
		if ( ! is_main_query() && ! $force_display ) {
1587
			return;
1588
		}
1589
1590
		// Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive
1591
		if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) {
1592
			return;
1593
		}
1594
1595
		// Check categories are enabled
1596
		if ( is_shop() && '' === get_option( 'woocommerce_shop_page_display' ) ) {
1597
			return;
1598
		}
1599
1600
		// Find the category + category parent, if applicable
1601
		$term 			= get_queried_object();
1602
		$parent_id 		= empty( $term->term_id ) ? 0 : $term->term_id;
1603
1604
		if ( is_product_category() ) {
1605
			$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1606
1607
			switch ( $display_type ) {
1608
				case 'products' :
1609
					return;
1610
				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...
1611
				case '' :
1612
					if ( '' === get_option( 'woocommerce_category_archive_display' ) ) {
1613
						return;
1614
					}
1615
				break;
1616
			}
1617
		}
1618
1619
		// 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
1620
		$product_categories = get_categories( apply_filters( 'woocommerce_product_subcategories_args', array(
1621
			'parent'       => $parent_id,
1622
			'menu_order'   => 'ASC',
1623
			'hide_empty'   => 0,
1624
			'hierarchical' => 1,
1625
			'taxonomy'     => 'product_cat',
1626
			'pad_counts'   => 1
1627
		) ) );
1628
1629
		if ( ! apply_filters( 'woocommerce_product_subcategories_hide_empty', false ) ) {
1630
			$product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' );
1631
		}
1632
1633
		if ( $product_categories ) {
1634
			echo $before;
1635
1636
			foreach ( $product_categories as $category ) {
1637
				wc_get_template( 'content-product_cat.php', array(
1638
					'category' => $category
1639
				) );
1640
			}
1641
1642
			// If we are hiding products disable the loop and pagination
1643
			if ( is_product_category() ) {
1644
				$display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
1645
1646
				switch ( $display_type ) {
1647
					case 'subcategories' :
1648
						$wp_query->post_count    = 0;
1649
						$wp_query->max_num_pages = 0;
1650
					break;
1651
					case '' :
1652
						if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) {
1653
							$wp_query->post_count    = 0;
1654
							$wp_query->max_num_pages = 0;
1655
						}
1656
					break;
1657
				}
1658
			}
1659
1660
			if ( is_shop() && 'subcategories' === get_option( 'woocommerce_shop_page_display' ) ) {
1661
				$wp_query->post_count    = 0;
1662
				$wp_query->max_num_pages = 0;
1663
			}
1664
1665
			echo $after;
1666
1667
			return true;
1668
		}
1669
	}
1670
}
1671
1672
if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
1673
1674
	/**
1675
	 * Show subcategory thumbnails.
1676
	 *
1677
	 * @param mixed $category
1678
	 * @subpackage	Loop
1679
	 */
1680
	function woocommerce_subcategory_thumbnail( $category ) {
1681
		$small_thumbnail_size  	= apply_filters( 'subcategory_archive_thumbnail_size', 'shop_catalog' );
1682
		$dimensions    			= wc_get_image_size( $small_thumbnail_size );
1683
		$thumbnail_id  			= get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true  );
1684
1685
		if ( $thumbnail_id ) {
1686
			$image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size  );
1687
			$image = $image[0];
1688
		} else {
1689
			$image = wc_placeholder_img_src();
1690
		}
1691
1692
		if ( $image ) {
1693
			// Prevent esc_url from breaking spaces in urls for image embeds
1694
			// Ref: https://core.trac.wordpress.org/ticket/23605
1695
			$image = str_replace( ' ', '%20', $image );
1696
1697
			echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
1698
		}
1699
	}
1700
}
1701
1702
if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
1703
1704
	/**
1705
	 * Displays order details in a table.
1706
	 *
1707
	 * @param mixed $order_id
1708
	 * @subpackage	Orders
1709
	 */
1710
	function woocommerce_order_details_table( $order_id ) {
1711
		if ( ! $order_id ) return;
1712
1713
		wc_get_template( 'order/order-details.php', array(
1714
			'order_id' => $order_id
1715
		) );
1716
	}
1717
}
1718
1719
1720
if ( ! function_exists( 'woocommerce_order_again_button' ) ) {
1721
1722
	/**
1723
	 * Display an 'order again' button on the view order page.
1724
	 *
1725
	 * @param object $order
1726
	 * @subpackage	Orders
1727
	 */
1728
	function woocommerce_order_again_button( $order ) {
1729
		if ( ! $order || ! $order->has_status( 'completed' ) || ! is_user_logged_in() ) {
1730
			return;
1731
		}
1732
1733
		wc_get_template( 'order/order-again.php', array(
1734
			'order' => $order
1735
		) );
1736
	}
1737
}
1738
1739
/** Forms ****************************************************************/
1740
1741
if ( ! function_exists( 'woocommerce_form_field' ) ) {
1742
1743
	/**
1744
	 * Outputs a checkout/address form field.
1745
	 *
1746
	 * @subpackage	Forms
1747
	 * @param string $key
1748
	 * @param mixed $args
1749
	 * @param string $value (default: null)
1750
	 * @todo This function needs to be broken up in smaller pieces
1751
	 */
1752
	function woocommerce_form_field( $key, $args, $value = null ) {
1753
		$defaults = array(
1754
			'type'              => 'text',
1755
			'label'             => '',
1756
			'description'       => '',
1757
			'placeholder'       => '',
1758
			'maxlength'         => false,
1759
			'required'          => false,
1760
			'autocomplete'      => false,
1761
			'id'                => $key,
1762
			'class'             => array(),
1763
			'label_class'       => array(),
1764
			'input_class'       => array(),
1765
			'return'            => false,
1766
			'options'           => array(),
1767
			'custom_attributes' => array(),
1768
			'validate'          => array(),
1769
			'default'           => '',
1770
		);
1771
1772
		$args = wp_parse_args( $args, $defaults );
1773
		$args = apply_filters( 'woocommerce_form_field_args', $args, $key, $value );
1774
1775
		if ( $args['required'] ) {
1776
			$args['class'][] = 'validate-required';
1777
			$required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce'  ) . '">*</abbr>';
1778
		} else {
1779
			$required = '';
1780
		}
1781
1782
		$args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
1783
1784
		$args['autocomplete'] = ( $args['autocomplete'] ) ? 'autocomplete="' . esc_attr( $args['autocomplete'] ) . '"' : '';
1785
1786
		if ( is_string( $args['label_class'] ) ) {
1787
			$args['label_class'] = array( $args['label_class'] );
1788
		}
1789
1790
		if ( is_null( $value ) ) {
1791
			$value = $args['default'];
1792
		}
1793
1794
		// Custom attribute handling
1795
		$custom_attributes = array();
1796
1797 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...
1798
			foreach ( $args['custom_attributes'] as $attribute => $attribute_value ) {
1799
				$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
1800
			}
1801
		}
1802
1803
		if ( ! empty( $args['validate'] ) ) {
1804
			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...
1805
				$args['class'][] = 'validate-' . $validate;
1806
			}
1807
		}
1808
1809
		$field = '';
1810
		$label_id = $args['id'];
1811
		$field_container = '<p class="form-row %1$s" id="%2$s">%3$s</p>';
1812
1813
		switch ( $args['type'] ) {
1814
			case 'country' :
1815
1816
				$countries = 'shipping_country' === $key ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
1817
1818
				if ( 1 === sizeof( $countries ) ) {
1819
1820
					$field .= '<strong>' . current( array_values( $countries ) ) . '</strong>';
1821
1822
					$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" />';
1823
1824
				} else {
1825
1826
					$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 ) . '>'
1827
							. '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
1828
1829 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...
1830
						$field .= '<option value="' . esc_attr( $ckey ) . '" '. selected( $value, $ckey, false ) . '>'. __( $cvalue, 'woocommerce' ) .'</option>';
1831
					}
1832
1833
					$field .= '</select>';
1834
1835
					$field .= '<noscript><input type="submit" name="woocommerce_checkout_update_totals" value="' . esc_attr__( 'Update country', 'woocommerce' ) . '" /></noscript>';
1836
1837
				}
1838
1839
				break;
1840
			case 'state' :
1841
1842
				/* Get Country */
1843
				$country_key = 'billing_state' === $key ? 'billing_country' : 'shipping_country';
1844
				$current_cc  = WC()->checkout->get_value( $country_key );
1845
				$states      = WC()->countries->get_states( $current_cc );
1846
1847
				if ( is_array( $states ) && empty( $states ) ) {
1848
1849
					$field_container = '<p class="form-row %1$s" id="%2$s" style="display: none">%3$s</p>';
1850
1851
					$field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key )  . '" id="' . esc_attr( $args['id'] ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
1852
1853
				} elseif ( is_array( $states ) ) {
1854
1855
					$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'] . '>
1856
						<option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
1857
1858 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...
1859
						$field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
1860
					}
1861
1862
					$field .= '</select>';
1863
1864
				} else {
1865
1866
					$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 ) . ' />';
1867
1868
				}
1869
1870
				break;
1871
			case 'textarea' :
1872
1873
				$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>';
1874
1875
				break;
1876 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...
1877
1878
				$field = '<label class="checkbox ' . implode( ' ', $args['label_class'] ) .'" ' . implode( ' ', $custom_attributes ) . '>
1879
						<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 ) .' /> '
1880
						 . $args['label'] . $required . '</label>';
1881
1882
				break;
1883
			case 'password' :
1884
			case 'text' :
1885
			case 'email' :
1886
			case 'tel' :
1887 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...
1888
1889
				$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 ) . ' />';
1890
1891
				break;
1892
			case 'select' :
1893
1894
				$options = $field = '';
1895
1896
				if ( ! empty( $args['options'] ) ) {
1897
					foreach ( $args['options'] as $option_key => $option_text ) {
1898
						if ( '' === $option_key ) {
1899
							// If we have a blank option, select2 needs a placeholder
1900
							if ( empty( $args['placeholder'] ) ) {
1901
								$args['placeholder'] = $option_text ? $option_text : __( 'Choose an option', 'woocommerce' );
1902
							}
1903
							$custom_attributes[] = 'data-allow_clear="true"';
1904
						}
1905
						$options .= '<option value="' . esc_attr( $option_key ) . '" '. selected( $value, $option_key, false ) . '>' . esc_attr( $option_text ) .'</option>';
1906
					}
1907
1908
					$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'] . '>
1909
							' . $options . '
1910
						</select>';
1911
				}
1912
1913
				break;
1914
			case 'radio' :
1915
1916
				$label_id = current( array_keys( $args['options'] ) );
1917
1918
				if ( ! empty( $args['options'] ) ) {
1919
					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...
1920
						$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 ) . ' />';
1921
						$field .= '<label for="' . esc_attr( $args['id'] ) . '_' . esc_attr( $option_key ) . '" class="radio ' . implode( ' ', $args['label_class'] ) .'">' . $option_text . '</label>';
1922
					}
1923
				}
1924
1925
				break;
1926
		}
1927
1928
		if ( ! empty( $field ) ) {
1929
			$field_html = '';
1930
1931
			if ( $args['label'] && 'checkbox' != $args['type'] ) {
1932
				$field_html .= '<label for="' . esc_attr( $label_id ) . '" class="' . esc_attr( implode( ' ', $args['label_class'] ) ) .'">' . $args['label'] . $required . '</label>';
1933
			}
1934
1935
			$field_html .= $field;
1936
1937
			if ( $args['description'] ) {
1938
				$field_html .= '<span class="description">' . esc_html( $args['description'] ) . '</span>';
1939
			}
1940
1941
			$container_class = 'form-row ' . esc_attr( implode( ' ', $args['class'] ) );
1942
			$container_id = esc_attr( $args['id'] ) . '_field';
1943
1944
			$after = ! empty( $args['clear'] ) ? '<div class="clear"></div>' : '';
1945
1946
			$field = sprintf( $field_container, $container_class, $container_id, $field_html ) . $after;
1947
		}
1948
1949
		$field = apply_filters( 'woocommerce_form_field_' . $args['type'], $field, $key, $args, $value );
1950
1951
		if ( $args['return'] ) {
1952
			return $field;
1953
		} else {
1954
			echo $field;
1955
		}
1956
	}
1957
}
1958
1959
if ( ! function_exists( 'get_product_search_form' ) ) {
1960
1961
	/**
1962
	 * Display product search form.
1963
	 *
1964
	 * Will first attempt to locate the product-searchform.php file in either the child or.
1965
	 * the parent, then load it. If it doesn't exist, then the default search form.
1966
	 * will be displayed.
1967
	 *
1968
	 * The default searchform uses html5.
1969
	 *
1970
	 * @subpackage	Forms
1971
	 * @param bool $echo (default: true)
1972
	 * @return string
1973
	 */
1974
	function get_product_search_form( $echo = true  ) {
1975
		ob_start();
1976
1977
		do_action( 'pre_get_product_search_form'  );
1978
1979
		wc_get_template( 'product-searchform.php' );
1980
1981
		$form = apply_filters( 'get_product_search_form', ob_get_clean() );
1982
1983
		if ( $echo ) {
1984
			echo $form;
1985
		} else {
1986
			return $form;
1987
		}
1988
	}
1989
}
1990
1991
if ( ! function_exists( 'woocommerce_output_auth_header' ) ) {
1992
1993
	/**
1994
	 * Output the Auth header.
1995
	 */
1996
	function woocommerce_output_auth_header() {
1997
		wc_get_template( 'auth/header.php' );
1998
	}
1999
}
2000
2001
if ( ! function_exists( 'woocommerce_output_auth_footer' ) ) {
2002
2003
	/**
2004
	 * Output the Auth footer.
2005
	 */
2006
	function woocommerce_output_auth_footer() {
2007
		wc_get_template( 'auth/footer.php' );
2008
	}
2009
}
2010
2011
if ( ! function_exists( 'woocommerce_single_variation' ) ) {
2012
2013
	/**
2014
	 * Output placeholders for the single variation.
2015
	 */
2016
	function woocommerce_single_variation() {
2017
		echo '<div class="woocommerce-variation single_variation"></div>';
2018
	}
2019
}
2020
2021
if ( ! function_exists( 'woocommerce_single_variation_add_to_cart_button' ) ) {
2022
2023
	/**
2024
	 * Output the add to cart button for variations.
2025
	 */
2026
	function woocommerce_single_variation_add_to_cart_button() {
2027
		wc_get_template( 'single-product/add-to-cart/variation-add-to-cart-button.php' );
2028
	}
2029
}
2030
2031
if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
2032
2033
	/**
2034
	 * Output a list of variation attributes for use in the cart forms.
2035
	 *
2036
	 * @param array $args
2037
	 * @since 2.4.0
2038
	 */
2039
	function wc_dropdown_variation_attribute_options( $args = array() ) {
2040
		$args = wp_parse_args( apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ), array(
2041
			'options'          => false,
2042
			'attribute'        => false,
2043
			'product'          => false,
2044
			'selected' 	       => false,
2045
			'name'             => '',
2046
			'id'               => '',
2047
			'class'            => '',
2048
			'show_option_none' => __( 'Choose an option', 'woocommerce' )
2049
		) );
2050
2051
		$options   = $args['options'];
2052
		$product   = $args['product'];
2053
		$attribute = $args['attribute'];
2054
		$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
2055
		$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );
2056
		$class     = $args['class'];
2057
2058
		if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
2059
			$attributes = $product->get_variation_attributes();
2060
			$options    = $attributes[ $attribute ];
2061
		}
2062
2063
		$html = '<select id="' . esc_attr( $id ) . '" class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '">';
2064
2065
		if ( $args['show_option_none'] ) {
2066
			$html .= '<option value="">' . esc_html( $args['show_option_none'] ) . '</option>';
2067
		}
2068
2069
		if ( ! empty( $options ) ) {
2070
			if ( $product && taxonomy_exists( $attribute ) ) {
2071
				// Get terms if this is a taxonomy - ordered. We need the names too.
2072
				$terms = wc_get_product_terms( $product->id, $attribute, array( 'fields' => 'all' ) );
2073
2074
				foreach ( $terms as $term ) {
2075
					if ( in_array( $term->slug, $options ) ) {
2076
						$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>';
2077
					}
2078
				}
2079
			} else {
2080
				foreach ( $options as $option ) {
2081
					// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
2082
					$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
2083
					$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
2084
				}
2085
			}
2086
		}
2087
2088
		$html .= '</select>';
2089
2090
		echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
2091
	}
2092
}
2093
2094
if ( ! function_exists( 'woocommerce_account_navigation' ) ) {
2095
2096
	/**
2097
	 * My Account navigation template.
2098
	 */
2099
	function woocommerce_account_navigation() {
2100
		wc_get_template( 'myaccount/navigation.php' );
2101
	}
2102
}
2103
2104
if ( ! function_exists( 'woocommerce_account_orders' ) ) {
2105
2106
	/**
2107
	 * My Account > Orders template.
2108
	 *
2109
	 * @param int $current_page Current page number.
2110
	 */
2111
	function woocommerce_account_orders( $current_page ) {
2112
		$current_page    = empty( $current_page ) ? 1 : absint( $current_page );
2113
		$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 'customer' => get_current_user_id(), 'page' => $current_page, 'paginate' => true ) ) );
2114
2115
		wc_get_template(
2116
			'myaccount/orders.php',
2117
			array(
2118
				'current_page' => absint( $current_page ),
2119
				'customer_orders' => $customer_orders,
2120
				'has_orders' => 0 < $customer_orders->total,
2121
			)
2122
		);
2123
	}
2124
}
2125
2126
if ( ! function_exists( 'woocommerce_account_view_order' ) ) {
2127
2128
	/**
2129
	 * My Account > View order template.
2130
	 *
2131
	 * @param int $order_id Order ID.
2132
	 */
2133
	function woocommerce_account_view_order( $order_id ) {
2134
		WC_Shortcode_My_Account::view_order( absint( $order_id ) );
2135
	}
2136
}
2137
2138
if ( ! function_exists( 'woocommerce_account_downloads' ) ) {
2139
2140
	/**
2141
	 * My Account > Downloads template.
2142
	 */
2143
	function woocommerce_account_downloads() {
2144
		wc_get_template( 'myaccount/downloads.php' );
2145
	}
2146
}
2147
2148
if ( ! function_exists( 'woocommerce_account_edit_address' ) ) {
2149
2150
	/**
2151
	 * My Account > Edit address template.
2152
	 *
2153
	 * @param string $type Address type.
2154
	 */
2155
	function woocommerce_account_edit_address( $type ) {
2156
		$type = wc_edit_address_i18n( sanitize_title( $type ), true );
2157
2158
		WC_Shortcode_My_Account::edit_address( $type );
2159
	}
2160
}
2161
2162
if ( ! function_exists( 'woocommerce_account_payment_methods' ) ) {
2163
2164
	/**
2165
	 * My Account > Downloads template.
2166
	 */
2167
	function woocommerce_account_payment_methods() {
2168
		wc_get_template( 'myaccount/payment-methods.php' );
2169
	}
2170
}
2171
2172
if ( ! function_exists( 'woocommerce_account_add_payment_method' ) ) {
2173
2174
	/**
2175
	 * My Account > Add payment method template.
2176
	 */
2177
	function woocommerce_account_add_payment_method() {
2178
		WC_Shortcode_My_Account::add_payment_method();
2179
	}
2180
}
2181
2182
if ( ! function_exists( 'woocommerce_account_edit_account' ) ) {
2183
2184
	/**
2185
	 * My Account > Edit account template.
2186
	 */
2187
	function woocommerce_account_edit_account() {
2188
		WC_Shortcode_My_Account::edit_account();
2189
	}
2190
}
2191