PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/includes/wc-template-functions.php

https://github.com/azhar37/woocommerce
PHP | 1824 lines | 952 code | 335 blank | 537 comment | 232 complexity | 4597c4ea1fb2e1abf0afdb6db9d9cbf9 MD5 | raw file
Possible License(s): GPL-3.0, BSD-3-Clause, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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.1.0
  11. */
  12. if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
  13. /**
  14. * Handle redirects before content is output - hooked into template_redirect so is_page works.
  15. *
  16. * @return void
  17. */
  18. function wc_template_redirect() {
  19. global $wp_query, $wp;
  20. // When default permalinks are enabled, redirect shop page to post type archive url
  21. if ( ! empty( $_GET['page_id'] ) && get_option( 'permalink_structure' ) == "" && $_GET['page_id'] == wc_get_page_id( 'shop' ) ) {
  22. wp_safe_redirect( get_post_type_archive_link('product') );
  23. exit;
  24. }
  25. // When on the checkout with an empty cart, redirect to cart page
  26. elseif ( is_page( wc_get_page_id( 'checkout' ) ) && sizeof( WC()->cart->get_cart() ) == 0 && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) ) {
  27. wp_redirect( get_permalink( wc_get_page_id( 'cart' ) ) );
  28. exit;
  29. }
  30. // Logout
  31. elseif ( isset( $wp->query_vars['customer-logout'] ) ) {
  32. wp_redirect( str_replace( '&amp;', '&', wp_logout_url( get_permalink( wc_get_page_id( 'myaccount' ) ) ) ) );
  33. exit;
  34. }
  35. // Redirect to the product page if we have a single product
  36. elseif ( is_search() && is_post_type_archive( 'product' ) && apply_filters( 'woocommerce_redirect_single_search_result', true ) && $wp_query->post_count == 1 ) {
  37. $product = get_product( $wp_query->post );
  38. if ( $product->is_visible() ) {
  39. wp_safe_redirect( get_permalink( $product->id ), 302 );
  40. exit;
  41. }
  42. }
  43. // Ensure payment gateways are loaded early
  44. elseif ( is_add_payment_method_page() ) {
  45. WC()->payment_gateways();
  46. }
  47. // Checkout pages handling
  48. elseif ( is_checkout() ) {
  49. // Buffer the checkout page
  50. ob_start();
  51. // Ensure gateways and shipping methods are loaded early
  52. WC()->payment_gateways();
  53. WC()->shipping();
  54. }
  55. }
  56. add_action( 'template_redirect', 'wc_template_redirect' );
  57. /**
  58. * When the_post is called, put product data into a global.
  59. *
  60. * @param mixed $post
  61. * @return WC_Product
  62. */
  63. function wc_setup_product_data( $post ) {
  64. unset( $GLOBALS['product'] );
  65. if ( is_int( $post ) )
  66. $post = get_post( $post );
  67. if ( empty( $post->post_type ) || ! in_array( $post->post_type, array( 'product', 'product_variation' ) ) )
  68. return;
  69. $GLOBALS['product'] = get_product( $post );
  70. return $GLOBALS['product'];
  71. }
  72. add_action( 'the_post', 'wc_setup_product_data' );
  73. if ( ! function_exists( 'woocommerce_reset_loop' ) ) {
  74. /**
  75. * Reset the loop's index and columns when we're done outputting a product loop.
  76. *
  77. * @access public
  78. * @subpackage Loop
  79. * @return void
  80. */
  81. function woocommerce_reset_loop() {
  82. global $woocommerce_loop;
  83. // Reset loop/columns globals when starting a new loop
  84. $woocommerce_loop['loop'] = $woocommerce_loop['columns'] = '';
  85. }
  86. }
  87. add_filter( 'loop_end', 'woocommerce_reset_loop' );
  88. /**
  89. * Products RSS Feed.
  90. *
  91. * @access public
  92. * @return void
  93. */
  94. function wc_products_rss_feed() {
  95. // Product RSS
  96. if ( is_post_type_archive( 'product' ) || is_singular( 'product' ) ) {
  97. $feed = get_post_type_archive_feed_link( 'product' );
  98. echo '<link rel="alternate" type="application/rss+xml" title="' . __( 'New products', 'woocommerce' ) . '" href="' . esc_attr( $feed ) . '" />';
  99. } elseif ( is_tax( 'product_cat' ) ) {
  100. $term = get_term_by('slug', esc_attr( get_query_var('product_cat') ), 'product_cat');
  101. $feed = add_query_arg('product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ));
  102. echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf(__( 'New products added to %s', 'woocommerce' ), urlencode($term->name)) . '" href="' . esc_attr( $feed ) . '" />';
  103. } elseif ( is_tax( 'product_tag' ) ) {
  104. $term = get_term_by('slug', esc_attr( get_query_var('product_tag') ), 'product_tag');
  105. $feed = add_query_arg('product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ));
  106. echo '<link rel="alternate" type="application/rss+xml" title="' . sprintf(__( 'New products tagged %s', 'woocommerce' ), urlencode($term->name)) . '" href="' . esc_attr( $feed ) . '" />';
  107. }
  108. }
  109. /**
  110. * Output generator tag to aid debugging.
  111. *
  112. * @access public
  113. * @return void
  114. */
  115. function wc_generator_tag( $gen, $type ) {
  116. switch ( $type ) {
  117. case 'html':
  118. $gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '">';
  119. break;
  120. case 'xhtml':
  121. $gen .= "\n" . '<meta name="generator" content="WooCommerce ' . esc_attr( WC_VERSION ) . '" />';
  122. break;
  123. }
  124. return $gen;
  125. }
  126. /**
  127. * Add body classes for WC pages
  128. *
  129. * @param array $classes
  130. * @return array
  131. */
  132. function wc_body_class( $classes ) {
  133. $classes = (array) $classes;
  134. if ( is_woocommerce() ) {
  135. $classes[] = 'woocommerce';
  136. $classes[] = 'woocommerce-page';
  137. }
  138. elseif ( is_checkout() ) {
  139. $classes[] = 'woocommerce-checkout';
  140. $classes[] = 'woocommerce-page';
  141. }
  142. elseif ( is_cart() ) {
  143. $classes[] = 'woocommerce-cart';
  144. $classes[] = 'woocommerce-page';
  145. }
  146. elseif ( is_account_page() ) {
  147. $classes[] = 'woocommerce-account';
  148. $classes[] = 'woocommerce-page';
  149. }
  150. if ( is_store_notice_showing() ) {
  151. $classes[] = 'woocommerce-demo-store';
  152. }
  153. return array_unique( $classes );
  154. }
  155. /**
  156. * Adds extra post classes for products
  157. *
  158. * @since 2.1.0
  159. * @param array $classes
  160. * @param string|array $class
  161. * @param int $post_id
  162. * @return array
  163. */
  164. function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
  165. if ( ! $post_id || get_post_type( $post_id ) !== 'product' )
  166. return $classes;
  167. $product = get_product( $post_id );
  168. if ( $product ) {
  169. if ( $product->is_on_sale() ) {
  170. $classes[] = 'sale';
  171. }
  172. if ( $product->is_featured() ) {
  173. $classes[] = 'featured';
  174. }
  175. if ( $product->is_downloadable() ) {
  176. $classes[] = 'downloadable';
  177. }
  178. if ( $product->is_virtual() ) {
  179. $classes[] = 'virtual';
  180. }
  181. if ( $product->is_sold_individually() ) {
  182. $classes[] = 'sold-individually';
  183. }
  184. if ( $product->is_taxable() ) {
  185. $classes[] = 'taxable';
  186. }
  187. if ( $product->is_shipping_taxable() ) {
  188. $classes[] = 'shipping-taxable';
  189. }
  190. if ( $product->is_purchasable() ) {
  191. $classes[] = 'purchasable';
  192. }
  193. if ( isset( $product->product_type ) ) {
  194. $classes[] = "product-type-" . $product->product_type;
  195. }
  196. // add category slugs
  197. $categories = wp_get_post_terms( $product->id, "product_cat" );
  198. if ( ! empty( $categories ) ) {
  199. foreach ($categories as $key => $value) {
  200. $classes[] = "product-cat-" . $value->slug;
  201. }
  202. }
  203. // add tag slugs
  204. $tags = wp_get_post_terms( $product->id, "product_tag" );
  205. if ( ! empty( $tags ) ) {
  206. foreach ($tags as $key => $value) {
  207. $classes[] = "product-tag-" . $value->slug;
  208. }
  209. }
  210. $classes[] = $product->stock_status;
  211. }
  212. if ( ( $key = array_search( 'hentry', $classes ) ) !== false ) {
  213. unset( $classes[ $key ] );
  214. }
  215. return $classes;
  216. }
  217. /** Template pages ********************************************************/
  218. if ( ! function_exists( 'woocommerce_content' ) ) {
  219. /**
  220. * Output WooCommerce content.
  221. *
  222. * This function is only used in the optional 'woocommerce.php' template
  223. * which people can add to their themes to add basic woocommerce support
  224. * without hooks or modifying core templates.
  225. *
  226. * @access public
  227. * @return void
  228. */
  229. function woocommerce_content() {
  230. if ( is_singular( 'product' ) ) {
  231. while ( have_posts() ) : the_post();
  232. wc_get_template_part( 'content', 'single-product' );
  233. endwhile;
  234. } else { ?>
  235. <?php if ( apply_filters( 'woocommerce_show_page_title', true ) ) : ?>
  236. <h1 class="page-title"><?php woocommerce_page_title(); ?></h1>
  237. <?php endif; ?>
  238. <?php do_action( 'woocommerce_archive_description' ); ?>
  239. <?php if ( have_posts() ) : ?>
  240. <?php do_action('woocommerce_before_shop_loop'); ?>
  241. <?php woocommerce_product_loop_start(); ?>
  242. <?php woocommerce_product_subcategories(); ?>
  243. <?php while ( have_posts() ) : the_post(); ?>
  244. <?php wc_get_template_part( 'content', 'product' ); ?>
  245. <?php endwhile; // end of the loop. ?>
  246. <?php woocommerce_product_loop_end(); ?>
  247. <?php do_action('woocommerce_after_shop_loop'); ?>
  248. <?php elseif ( ! woocommerce_product_subcategories( array( 'before' => woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?>
  249. <?php wc_get_template( 'loop/no-products-found.php' ); ?>
  250. <?php endif;
  251. }
  252. }
  253. }
  254. /** Global ****************************************************************/
  255. if ( ! function_exists( 'woocommerce_output_content_wrapper' ) ) {
  256. /**
  257. * Output the start of the page wrapper.
  258. *
  259. * @access public
  260. * @return void
  261. */
  262. function woocommerce_output_content_wrapper() {
  263. wc_get_template( 'global/wrapper-start.php' );
  264. }
  265. }
  266. if ( ! function_exists( 'woocommerce_output_content_wrapper_end' ) ) {
  267. /**
  268. * Output the end of the page wrapper.
  269. *
  270. * @access public
  271. * @return void
  272. */
  273. function woocommerce_output_content_wrapper_end() {
  274. wc_get_template( 'global/wrapper-end.php' );
  275. }
  276. }
  277. if ( ! function_exists( 'woocommerce_get_sidebar' ) ) {
  278. /**
  279. * Get the shop sidebar template.
  280. *
  281. * @access public
  282. * @return void
  283. */
  284. function woocommerce_get_sidebar() {
  285. wc_get_template( 'global/sidebar.php' );
  286. }
  287. }
  288. if ( ! function_exists( 'woocommerce_demo_store' ) ) {
  289. /**
  290. * Adds a demo store banner to the site if enabled
  291. *
  292. * @access public
  293. * @return void
  294. */
  295. function woocommerce_demo_store() {
  296. if ( !is_store_notice_showing() )
  297. return;
  298. $notice = get_option( 'woocommerce_demo_store_notice' );
  299. if ( empty( $notice ) )
  300. $notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
  301. echo apply_filters( 'woocommerce_demo_store', '<p class="demo_store">' . $notice . '</p>' );
  302. }
  303. }
  304. /** Loop ******************************************************************/
  305. if ( ! function_exists( 'woocommerce_page_title' ) ) {
  306. /**
  307. * woocommerce_page_title function.
  308. *
  309. * @param boolean $echo
  310. * @return string
  311. */
  312. function woocommerce_page_title( $echo = true ) {
  313. if ( is_search() ) {
  314. $page_title = sprintf( __( 'Search Results: &ldquo;%s&rdquo;', 'woocommerce' ), get_search_query() );
  315. if ( get_query_var( 'paged' ) )
  316. $page_title .= sprintf( __( '&nbsp;&ndash; Page %s', 'woocommerce' ), get_query_var( 'paged' ) );
  317. } elseif ( is_tax() ) {
  318. $page_title = single_term_title( "", false );
  319. } else {
  320. $shop_page_id = wc_get_page_id( 'shop' );
  321. $page_title = get_the_title( $shop_page_id );
  322. }
  323. $page_title = apply_filters( 'woocommerce_page_title', $page_title );
  324. if ( $echo )
  325. echo $page_title;
  326. else
  327. return $page_title;
  328. }
  329. }
  330. if ( ! function_exists( 'woocommerce_product_loop_start' ) ) {
  331. /**
  332. * Output the start of a product loop. By default this is a UL
  333. *
  334. * @access public
  335. * @param bool $echo
  336. * @return string
  337. */
  338. function woocommerce_product_loop_start( $echo = true ) {
  339. ob_start();
  340. wc_get_template( 'loop/loop-start.php' );
  341. if ( $echo )
  342. echo ob_get_clean();
  343. else
  344. return ob_get_clean();
  345. }
  346. }
  347. if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
  348. /**
  349. * Output the end of a product loop. By default this is a UL
  350. *
  351. * @access public
  352. * @param bool $echo
  353. * @return string
  354. */
  355. function woocommerce_product_loop_end( $echo = true ) {
  356. ob_start();
  357. wc_get_template( 'loop/loop-end.php' );
  358. if ( $echo )
  359. echo ob_get_clean();
  360. else
  361. return ob_get_clean();
  362. }
  363. }
  364. if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
  365. /**
  366. * Show an archive description on taxonomy archives
  367. *
  368. * @access public
  369. * @subpackage Archives
  370. * @return void
  371. */
  372. function woocommerce_taxonomy_archive_description() {
  373. if ( is_tax( array( 'product_cat', 'product_tag' ) ) && get_query_var( 'paged' ) == 0 ) {
  374. $description = apply_filters( 'the_content', term_description() );
  375. if ( $description ) {
  376. echo '<div class="term-description">' . $description . '</div>';
  377. }
  378. }
  379. }
  380. }
  381. if ( ! function_exists( 'woocommerce_product_archive_description' ) ) {
  382. /**
  383. * Show a shop page description on product archives
  384. *
  385. * @access public
  386. * @subpackage Archives
  387. * @return void
  388. */
  389. function woocommerce_product_archive_description() {
  390. if ( is_post_type_archive( 'product' ) && get_query_var( 'paged' ) == 0 ) {
  391. $shop_page = get_post( wc_get_page_id( 'shop' ) );
  392. if ( $shop_page ) {
  393. $description = apply_filters( 'the_content', $shop_page->post_content );
  394. if ( $description ) {
  395. echo '<div class="page-description">' . $description . '</div>';
  396. }
  397. }
  398. }
  399. }
  400. }
  401. if ( ! function_exists( 'woocommerce_template_loop_add_to_cart' ) ) {
  402. /**
  403. * Get the add to cart template for the loop.
  404. *
  405. * @access public
  406. * @subpackage Loop
  407. * @return void
  408. */
  409. function woocommerce_template_loop_add_to_cart() {
  410. wc_get_template( 'loop/add-to-cart.php' );
  411. }
  412. }
  413. if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) {
  414. /**
  415. * Get the product thumbnail for the loop.
  416. *
  417. * @access public
  418. * @subpackage Loop
  419. * @return void
  420. */
  421. function woocommerce_template_loop_product_thumbnail() {
  422. echo woocommerce_get_product_thumbnail();
  423. }
  424. }
  425. if ( ! function_exists( 'woocommerce_template_loop_price' ) ) {
  426. /**
  427. * Get the product price for the loop.
  428. *
  429. * @access public
  430. * @subpackage Loop
  431. * @return void
  432. */
  433. function woocommerce_template_loop_price() {
  434. wc_get_template( 'loop/price.php' );
  435. }
  436. }
  437. if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) {
  438. /**
  439. * Display the average rating in the loop
  440. *
  441. * @access public
  442. * @subpackage Loop
  443. * @return void
  444. */
  445. function woocommerce_template_loop_rating() {
  446. wc_get_template( 'loop/rating.php' );
  447. }
  448. }
  449. if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) {
  450. /**
  451. * Get the sale flash for the loop.
  452. *
  453. * @access public
  454. * @subpackage Loop
  455. * @return void
  456. */
  457. function woocommerce_show_product_loop_sale_flash() {
  458. wc_get_template( 'loop/sale-flash.php' );
  459. }
  460. }
  461. if ( ! function_exists( 'woocommerce_get_product_schema' ) ) {
  462. /**
  463. * Get a products Schema
  464. * @return string
  465. */
  466. function woocommerce_get_product_schema() {
  467. global $post, $product;
  468. $schema = "Product";
  469. // Downloadable product schema handling
  470. if ( $product->is_downloadable() ) {
  471. switch ( $product->download_type ) {
  472. case 'application' :
  473. $schema = "SoftwareApplication";
  474. break;
  475. case 'music' :
  476. $schema = "MusicAlbum";
  477. break;
  478. default :
  479. $schema = "Product";
  480. break;
  481. }
  482. }
  483. return 'http://schema.org/' . $schema;
  484. }
  485. }
  486. if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) {
  487. /**
  488. * Get the product thumbnail, or the placeholder if not set.
  489. *
  490. * @access public
  491. * @subpackage Loop
  492. * @param string $size (default: 'shop_catalog')
  493. * @param int $placeholder_width (default: 0)
  494. * @param int $placeholder_height (default: 0)
  495. * @return string
  496. */
  497. function woocommerce_get_product_thumbnail( $size = 'shop_catalog', $placeholder_width = 0, $placeholder_height = 0 ) {
  498. global $post;
  499. if ( has_post_thumbnail() )
  500. return get_the_post_thumbnail( $post->ID, $size );
  501. elseif ( wc_placeholder_img_src() )
  502. return wc_placeholder_img( $size );
  503. }
  504. }
  505. if ( ! function_exists( 'woocommerce_result_count' ) ) {
  506. /**
  507. * Output the result count text (Showing x - x of x results).
  508. *
  509. * @access public
  510. * @subpackage Loop
  511. * @return void
  512. */
  513. function woocommerce_result_count() {
  514. wc_get_template( 'loop/result-count.php' );
  515. }
  516. }
  517. if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) {
  518. /**
  519. * Output the product sorting options.
  520. *
  521. * @access public
  522. * @subpackage Loop
  523. * @return void
  524. */
  525. function woocommerce_catalog_ordering() {
  526. $orderby = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
  527. wc_get_template( 'loop/orderby.php', array( 'orderby' => $orderby ) );
  528. }
  529. }
  530. if ( ! function_exists( 'woocommerce_pagination' ) ) {
  531. /**
  532. * Output the pagination.
  533. *
  534. * @access public
  535. * @subpackage Loop
  536. * @return void
  537. */
  538. function woocommerce_pagination() {
  539. wc_get_template( 'loop/pagination.php' );
  540. }
  541. }
  542. /** Single Product ********************************************************/
  543. if ( ! function_exists( 'woocommerce_show_product_images' ) ) {
  544. /**
  545. * Output the product image before the single product summary.
  546. *
  547. * @access public
  548. * @subpackage Product
  549. * @return void
  550. */
  551. function woocommerce_show_product_images() {
  552. wc_get_template( 'single-product/product-image.php' );
  553. }
  554. }
  555. if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) {
  556. /**
  557. * Output the product thumbnails.
  558. *
  559. * @access public
  560. * @subpackage Product
  561. * @return void
  562. */
  563. function woocommerce_show_product_thumbnails() {
  564. wc_get_template( 'single-product/product-thumbnails.php' );
  565. }
  566. }
  567. if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) {
  568. /**
  569. * Output the product tabs.
  570. *
  571. * @access public
  572. * @subpackage Product/Tabs
  573. * @return void
  574. */
  575. function woocommerce_output_product_data_tabs() {
  576. wc_get_template( 'single-product/tabs/tabs.php' );
  577. }
  578. }
  579. if ( ! function_exists( 'woocommerce_template_single_title' ) ) {
  580. /**
  581. * Output the product title.
  582. *
  583. * @access public
  584. * @subpackage Product
  585. * @return void
  586. */
  587. function woocommerce_template_single_title() {
  588. wc_get_template( 'single-product/title.php' );
  589. }
  590. }
  591. if ( ! function_exists( 'woocommerce_template_single_rating' ) ) {
  592. /**
  593. * Output the product rating.
  594. *
  595. * @access public
  596. * @subpackage Product
  597. * @return void
  598. */
  599. function woocommerce_template_single_rating() {
  600. wc_get_template( 'single-product/rating.php' );
  601. }
  602. }
  603. if ( ! function_exists( 'woocommerce_template_single_price' ) ) {
  604. /**
  605. * Output the product price.
  606. *
  607. * @access public
  608. * @subpackage Product
  609. * @return void
  610. */
  611. function woocommerce_template_single_price() {
  612. wc_get_template( 'single-product/price.php' );
  613. }
  614. }
  615. if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) {
  616. /**
  617. * Output the product short description (excerpt).
  618. *
  619. * @access public
  620. * @subpackage Product
  621. * @return void
  622. */
  623. function woocommerce_template_single_excerpt() {
  624. wc_get_template( 'single-product/short-description.php' );
  625. }
  626. }
  627. if ( ! function_exists( 'woocommerce_template_single_meta' ) ) {
  628. /**
  629. * Output the product meta.
  630. *
  631. * @access public
  632. * @subpackage Product
  633. * @return void
  634. */
  635. function woocommerce_template_single_meta() {
  636. wc_get_template( 'single-product/meta.php' );
  637. }
  638. }
  639. if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) {
  640. /**
  641. * Output the product sharing.
  642. *
  643. * @access public
  644. * @subpackage Product
  645. * @return void
  646. */
  647. function woocommerce_template_single_sharing() {
  648. wc_get_template( 'single-product/share.php' );
  649. }
  650. }
  651. if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) {
  652. /**
  653. * Output the product sale flash.
  654. *
  655. * @access public
  656. * @subpackage Product
  657. * @return void
  658. */
  659. function woocommerce_show_product_sale_flash() {
  660. wc_get_template( 'single-product/sale-flash.php' );
  661. }
  662. }
  663. if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) {
  664. /**
  665. * Trigger the single product add to cart action.
  666. *
  667. * @access public
  668. * @subpackage Product
  669. * @return void
  670. */
  671. function woocommerce_template_single_add_to_cart() {
  672. global $product;
  673. do_action( 'woocommerce_' . $product->product_type . '_add_to_cart' );
  674. }
  675. }
  676. if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) {
  677. /**
  678. * Output the simple product add to cart area.
  679. *
  680. * @access public
  681. * @subpackage Product
  682. * @return void
  683. */
  684. function woocommerce_simple_add_to_cart() {
  685. wc_get_template( 'single-product/add-to-cart/simple.php' );
  686. }
  687. }
  688. if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
  689. /**
  690. * Output the grouped product add to cart area.
  691. *
  692. * @access public
  693. * @subpackage Product
  694. * @return void
  695. */
  696. function woocommerce_grouped_add_to_cart() {
  697. global $product;
  698. wc_get_template( 'single-product/add-to-cart/grouped.php', array(
  699. 'grouped_product' => $product,
  700. 'grouped_products' => $product->get_children(),
  701. 'quantites_required' => false
  702. ) );
  703. }
  704. }
  705. if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) {
  706. /**
  707. * Output the variable product add to cart area.
  708. *
  709. * @access public
  710. * @subpackage Product
  711. * @return void
  712. */
  713. function woocommerce_variable_add_to_cart() {
  714. global $product;
  715. // Enqueue variation scripts
  716. wp_enqueue_script( 'wc-add-to-cart-variation' );
  717. // Load the template
  718. wc_get_template( 'single-product/add-to-cart/variable.php', array(
  719. 'available_variations' => $product->get_available_variations(),
  720. 'attributes' => $product->get_variation_attributes(),
  721. 'selected_attributes' => $product->get_variation_default_attributes()
  722. ) );
  723. }
  724. }
  725. if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) {
  726. /**
  727. * Output the external product add to cart area.
  728. *
  729. * @access public
  730. * @subpackage Product
  731. * @return void
  732. */
  733. function woocommerce_external_add_to_cart() {
  734. global $product;
  735. if ( ! $product->get_product_url() )
  736. return;
  737. wc_get_template( 'single-product/add-to-cart/external.php', array(
  738. 'product_url' => $product->get_product_url(),
  739. 'button_text' => $product->single_add_to_cart_text()
  740. ) );
  741. }
  742. }
  743. if ( ! function_exists( 'woocommerce_quantity_input' ) ) {
  744. /**
  745. * Output the quantity input for add to cart forms.
  746. *
  747. * @param array $args Args for the input
  748. * @param WC_Product|null $product
  749. * @param boolean $echo Whether to return or echo
  750. * @return void|string
  751. */
  752. function woocommerce_quantity_input( $args = array(), $product = null, $echo = true ) {
  753. if ( is_null( $product ) )
  754. $product = $GLOBALS['product'];
  755. $defaults = array(
  756. 'input_name' => 'quantity',
  757. 'input_value' => '1',
  758. 'max_value' => apply_filters( 'woocommerce_quantity_input_max', '', $product ),
  759. 'min_value' => apply_filters( 'woocommerce_quantity_input_min', '', $product ),
  760. 'step' => apply_filters( 'woocommerce_quantity_input_step', '1', $product )
  761. );
  762. $args = apply_filters( 'woocommerce_quantity_input_args', wp_parse_args( $args, $defaults ), $product );
  763. ob_start();
  764. wc_get_template( 'global/quantity-input.php', $args );
  765. if ( $echo ) {
  766. echo ob_get_clean();
  767. } else {
  768. return ob_get_clean();
  769. }
  770. }
  771. }
  772. if ( ! function_exists( 'woocommerce_product_description_tab' ) ) {
  773. /**
  774. * Output the description tab content.
  775. *
  776. * @access public
  777. * @subpackage Product/Tabs
  778. * @return void
  779. */
  780. function woocommerce_product_description_tab() {
  781. wc_get_template( 'single-product/tabs/description.php' );
  782. }
  783. }
  784. if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) {
  785. /**
  786. * Output the attributes tab content.
  787. *
  788. * @access public
  789. * @subpackage Product/Tabs
  790. * @return void
  791. */
  792. function woocommerce_product_additional_information_tab() {
  793. wc_get_template( 'single-product/tabs/additional-information.php' );
  794. }
  795. }
  796. if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
  797. /**
  798. * Output the reviews tab content.
  799. *
  800. * @access public
  801. * @subpackage Product/Tabs
  802. * @return void
  803. */
  804. function woocommerce_product_reviews_tab() {
  805. wc_get_template( 'single-product/tabs/reviews.php' );
  806. }
  807. }
  808. if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
  809. /**
  810. * Add default product tabs to product pages.
  811. *
  812. * @access public
  813. * @param array $tabs
  814. * @return array
  815. */
  816. function woocommerce_default_product_tabs( $tabs = array() ) {
  817. global $product, $post;
  818. // Description tab - shows product content
  819. if ( $post->post_content ) {
  820. $tabs['description'] = array(
  821. 'title' => __( 'Description', 'woocommerce' ),
  822. 'priority' => 10,
  823. 'callback' => 'woocommerce_product_description_tab'
  824. );
  825. }
  826. // Additional information tab - shows attributes
  827. if ( $product && ( $product->has_attributes() || ( $product->enable_dimensions_display() && ( $product->has_dimensions() || $product->has_weight() ) ) ) ) {
  828. $tabs['additional_information'] = array(
  829. 'title' => __( 'Additional Information', 'woocommerce' ),
  830. 'priority' => 20,
  831. 'callback' => 'woocommerce_product_additional_information_tab'
  832. );
  833. }
  834. // Reviews tab - shows comments
  835. if ( comments_open() ) {
  836. $tabs['reviews'] = array(
  837. 'title' => sprintf( __( 'Reviews (%d)', 'woocommerce' ), get_comments_number( $post->ID ) ),
  838. 'priority' => 30,
  839. 'callback' => 'comments_template'
  840. );
  841. }
  842. return $tabs;
  843. }
  844. }
  845. if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) {
  846. /**
  847. * Sort tabs by priority
  848. *
  849. * @access public
  850. * @param array $tabs
  851. * @return array
  852. */
  853. function woocommerce_sort_product_tabs( $tabs = array() ) {
  854. // Make sure the $tabs parameter is an array
  855. if ( ! is_array( $tabs ) ) {
  856. trigger_error( "Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array." );
  857. $tabs = array( );
  858. }
  859. // Re-order tabs by priority
  860. if ( ! function_exists( '_sort_priority_callback' ) ) {
  861. function _sort_priority_callback( $a, $b ) {
  862. if ( $a['priority'] == $b['priority'] )
  863. return 0;
  864. return ( $a['priority'] < $b['priority'] ) ? -1 : 1;
  865. }
  866. }
  867. uasort( $tabs, '_sort_priority_callback' );
  868. return $tabs;
  869. }
  870. }
  871. if ( ! function_exists( 'woocommerce_comments' ) ) {
  872. /**
  873. * Output the Review comments template.
  874. *
  875. * @access public
  876. * @subpackage Product
  877. * @return void
  878. */
  879. function woocommerce_comments( $comment, $args, $depth ) {
  880. $GLOBALS['comment'] = $comment;
  881. wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) );
  882. }
  883. }
  884. if ( ! function_exists( 'woocommerce_output_related_products' ) ) {
  885. /**
  886. * Output the related products.
  887. *
  888. * @access public
  889. * @subpackage Product
  890. * @return void
  891. */
  892. function woocommerce_output_related_products() {
  893. $args = array(
  894. 'posts_per_page' => 2,
  895. 'columns' => 2,
  896. 'orderby' => 'rand'
  897. );
  898. woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) );
  899. }
  900. }
  901. if ( ! function_exists( 'woocommerce_related_products' ) ) {
  902. /**
  903. * Output the related products.
  904. *
  905. * @access public
  906. * @param array Provided arguments
  907. * @param bool Columns argument for backwards compat
  908. * @param bool Order by argument for backwards compat
  909. * @return void
  910. */
  911. function woocommerce_related_products( $args = array(), $columns = false, $orderby = false ) {
  912. if ( ! is_array( $args ) ) {
  913. _deprecated_argument( __FUNCTION__, '2.1', __( 'Use $args argument as an array instead. Deprecated argument will be removed in WC 2.2.', 'woocommerce' ) );
  914. $argsvalue = $args;
  915. $args = array(
  916. 'posts_per_page' => $argsvalue,
  917. 'columns' => $columns,
  918. 'orderby' => $orderby,
  919. );
  920. }
  921. $defaults = array(
  922. 'posts_per_page' => 2,
  923. 'columns' => 2,
  924. 'orderby' => 'rand'
  925. );
  926. $args = wp_parse_args( $args, $defaults );
  927. wc_get_template( 'single-product/related.php', $args );
  928. }
  929. }
  930. if ( ! function_exists( 'woocommerce_upsell_display' ) ) {
  931. /**
  932. * Output product up sells.
  933. *
  934. * @access public
  935. * @param int $posts_per_page (default: -1)
  936. * @param int $columns (default: 2)
  937. * @param string $orderby (default: 'rand')
  938. * @return void
  939. */
  940. function woocommerce_upsell_display( $posts_per_page = '-1', $columns = 2, $orderby = 'rand' ) {
  941. wc_get_template( 'single-product/up-sells.php', array(
  942. 'posts_per_page' => $posts_per_page,
  943. 'orderby' => apply_filters( 'woocommerce_upsells_orderby', $orderby ),
  944. 'columns' => $columns
  945. ) );
  946. }
  947. }
  948. /** Cart ******************************************************************/
  949. if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) {
  950. /**
  951. * Output the cart shipping calculator.
  952. *
  953. * @access public
  954. * @subpackage Cart
  955. * @return void
  956. */
  957. function woocommerce_shipping_calculator() {
  958. wc_get_template( 'cart/shipping-calculator.php' );
  959. }
  960. }
  961. if ( ! function_exists( 'woocommerce_cart_totals' ) ) {
  962. /**
  963. * Output the cart totals.
  964. *
  965. * @access public
  966. * @subpackage Cart
  967. * @return void
  968. */
  969. function woocommerce_cart_totals() {
  970. wc_get_template( 'cart/cart-totals.php' );
  971. }
  972. }
  973. if ( ! function_exists( 'woocommerce_cross_sell_display' ) ) {
  974. /**
  975. * Output the cart cross-sells.
  976. *
  977. * @param integer $posts_per_page
  978. * @param integer $columns
  979. * @param string $orderby
  980. */
  981. function woocommerce_cross_sell_display( $posts_per_page = 2, $columns = 2, $orderby = 'rand' ) {
  982. wc_get_template( 'cart/cross-sells.php', array(
  983. 'posts_per_page' => $posts_per_page,
  984. 'orderby' => $orderby,
  985. 'columns' => $columns
  986. ) );
  987. }
  988. }
  989. /** Mini-Cart *************************************************************/
  990. if ( ! function_exists( 'woocommerce_mini_cart' ) ) {
  991. /**
  992. * Output the Mini-cart - used by cart widget
  993. *
  994. * @access public
  995. * @return void
  996. */
  997. function woocommerce_mini_cart( $args = array() ) {
  998. $defaults = array(
  999. 'list_class' => ''
  1000. );
  1001. $args = wp_parse_args( $args, $defaults );
  1002. wc_get_template( 'cart/mini-cart.php', $args );
  1003. }
  1004. }
  1005. /** Login *****************************************************************/
  1006. if ( ! function_exists( 'woocommerce_login_form' ) ) {
  1007. /**
  1008. * Output the WooCommerce Login Form
  1009. *
  1010. * @access public
  1011. * @subpackage Forms
  1012. * @return void
  1013. */
  1014. function woocommerce_login_form( $args = array() ) {
  1015. $defaults = array(
  1016. 'message' => '',
  1017. 'redirect' => '',
  1018. 'hidden' => false
  1019. );
  1020. $args = wp_parse_args( $args, $defaults );
  1021. wc_get_template( 'global/form-login.php', $args );
  1022. }
  1023. }
  1024. if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) {
  1025. /**
  1026. * Output the WooCommerce Checkout Login Form
  1027. *
  1028. * @access public
  1029. * @subpackage Checkout
  1030. * @return void
  1031. */
  1032. function woocommerce_checkout_login_form() {
  1033. wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) );
  1034. }
  1035. }
  1036. if ( ! function_exists( 'woocommerce_breadcrumb' ) ) {
  1037. /**
  1038. * Output the WooCommerce Breadcrumb
  1039. *
  1040. * @access public
  1041. * @return void
  1042. */
  1043. function woocommerce_breadcrumb( $args = array() ) {
  1044. $defaults = apply_filters( 'woocommerce_breadcrumb_defaults', array(
  1045. 'delimiter' => ' &#47; ',
  1046. 'wrap_before' => '<nav class="woocommerce-breadcrumb" ' . ( is_single() ? 'itemprop="breadcrumb"' : '' ) . '>',
  1047. 'wrap_after' => '</nav>',
  1048. 'before' => '',
  1049. 'after' => '',
  1050. 'home' => _x( 'Home', 'breadcrumb', 'woocommerce' ),
  1051. ) );
  1052. $args = wp_parse_args( $args, $defaults );
  1053. wc_get_template( 'global/breadcrumb.php', $args );
  1054. }
  1055. }
  1056. if ( ! function_exists( 'woocommerce_order_review' ) ) {
  1057. /**
  1058. * Output the Order review table for the checkout.
  1059. *
  1060. * @access public
  1061. * @subpackage Checkout
  1062. * @return void
  1063. */
  1064. function woocommerce_order_review() {
  1065. wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) );
  1066. }
  1067. }
  1068. if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) {
  1069. /**
  1070. * Output the Coupon form for the checkout.
  1071. *
  1072. * @access public
  1073. * @subpackage Checkout
  1074. * @return void
  1075. */
  1076. function woocommerce_checkout_coupon_form() {
  1077. wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) );
  1078. }
  1079. }
  1080. if ( ! function_exists( 'woocommerce_products_will_display' ) ) {
  1081. /**
  1082. * Check if we will be showing products or not (and not subcats only)
  1083. *
  1084. * @access public
  1085. * @subpackage Loop
  1086. * @return bool
  1087. */
  1088. function woocommerce_products_will_display() {
  1089. if ( is_shop() )
  1090. return get_option( 'woocommerce_shop_page_display' ) != 'subcategories';
  1091. if ( ! is_product_taxonomy() )
  1092. return false;
  1093. if ( is_search() || is_filtered() || is_paged() )
  1094. return true;
  1095. $term = get_queried_object();
  1096. if ( is_product_category() ) {
  1097. switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) {
  1098. case 'subcategories' :
  1099. // Nothing - we want to continue to see if there are products/subcats
  1100. break;
  1101. case 'products' :
  1102. case 'both' :
  1103. return true;
  1104. break;
  1105. default :
  1106. // Default - no setting
  1107. if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' )
  1108. return true;
  1109. break;
  1110. }
  1111. }
  1112. // Begin subcategory logic
  1113. global $wpdb;
  1114. $parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
  1115. $taxonomy = empty( $term->taxonomy ) ? '' : $term->taxonomy;
  1116. $products_will_display = true;
  1117. if ( ! $parent_id && ! $taxonomy ) {
  1118. return true;
  1119. }
  1120. if ( false === ( $products_will_display = get_transient( 'wc_products_will_display_' . $parent_id ) ) ) {
  1121. $has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $parent_id, $taxonomy ) );
  1122. if ( $has_children ) {
  1123. // Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false.
  1124. if ( sizeof( get_objects_in_term( $has_children, $taxonomy ) ) > 0 ) {
  1125. $products_will_display = false;
  1126. } else {
  1127. // If we get here, the parents were empty so we're forced to check children
  1128. foreach ( $has_children as $term ) {
  1129. $children = get_term_children( $term, $taxonomy );
  1130. if ( sizeof( get_objects_in_term( $children, $taxonomy ) ) > 0 ) {
  1131. $products_will_display = false;
  1132. break;
  1133. }
  1134. }
  1135. }
  1136. } else {
  1137. $products_will_display = true;
  1138. }
  1139. }
  1140. set_transient( 'wc_products_will_display_' . $parent_id, $products_will_display, YEAR_IN_SECONDS );
  1141. return $products_will_display;
  1142. }
  1143. }
  1144. if ( ! function_exists( 'woocommerce_product_subcategories' ) ) {
  1145. /**
  1146. * Display product sub categories as thumbnails.
  1147. *
  1148. * @access public
  1149. * @subpackage Loop
  1150. * @param array $args
  1151. * @return bool
  1152. */
  1153. function woocommerce_product_subcategories( $args = array() ) {
  1154. global $wp_query;
  1155. $defaults = array(
  1156. 'before' => '',
  1157. 'after' => '',
  1158. 'force_display' => false
  1159. );
  1160. $args = wp_parse_args( $args, $defaults );
  1161. extract( $args );
  1162. // Main query only
  1163. if ( ! is_main_query() && ! $force_display ) return;
  1164. // Don't show when filtering, searching or when on page > 1 and ensure we're on a product archive
  1165. if ( is_search() || is_filtered() || is_paged() || ( ! is_product_category() && ! is_shop() ) ) return;
  1166. // Check categories are enabled
  1167. if ( is_shop() && get_option( 'woocommerce_shop_page_display' ) == '' ) return;
  1168. // Find the category + category parent, if applicable
  1169. $term = get_queried_object();
  1170. $parent_id = empty( $term->term_id ) ? 0 : $term->term_id;
  1171. if ( is_product_category() ) {
  1172. $display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
  1173. switch ( $display_type ) {
  1174. case 'products' :
  1175. return;
  1176. break;
  1177. case '' :
  1178. if ( get_option( 'woocommerce_category_archive_display' ) == '' )
  1179. return;
  1180. break;
  1181. }
  1182. }
  1183. // NOTE: using child_of instead of parent - this is not ideal but due to a WP bug ( http://core.trac.wordpress.org/ticket/15626 ) pad_counts won't work
  1184. $args = apply_filters( 'woocommerce_product_subcategories_args', array(
  1185. 'child_of' => $parent_id,
  1186. 'menu_order' => 'ASC',
  1187. 'hide_empty' => 1,
  1188. 'hierarchical' => 1,
  1189. 'taxonomy' => 'product_cat',
  1190. 'pad_counts' => 1
  1191. ) );
  1192. $product_categories = get_categories( $args );
  1193. $product_category_found = false;
  1194. if ( $product_categories ) {
  1195. foreach ( $product_categories as $category ) {
  1196. if ( $category->parent != $parent_id ) {
  1197. continue;
  1198. }
  1199. if ( $args['hide_empty'] && $category->count == 0 ) {
  1200. continue;
  1201. }
  1202. if ( ! $product_category_found ) {
  1203. // We found a category
  1204. $product_category_found = true;
  1205. echo $before;
  1206. }
  1207. wc_get_template( 'content-product_cat.php', array(
  1208. 'category' => $category
  1209. ) );
  1210. }
  1211. }
  1212. // If we are hiding products disable the loop and pagination
  1213. if ( $product_category_found ) {
  1214. if ( is_product_category() ) {
  1215. $display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true );
  1216. switch ( $display_type ) {
  1217. case 'subcategories' :
  1218. $wp_query->post_count = 0;
  1219. $wp_query->max_num_pages = 0;
  1220. break;
  1221. case '' :
  1222. if ( get_option( 'woocommerce_category_archive_display' ) == 'subcategories' ) {
  1223. $wp_query->post_count = 0;
  1224. $wp_query->max_num_pages = 0;
  1225. }
  1226. break;
  1227. }
  1228. }
  1229. if ( is_shop() && get_option( 'woocommerce_shop_page_display' ) == 'subcategories' ) {
  1230. $wp_query->post_count = 0;
  1231. $wp_query->max_num_pages = 0;
  1232. }
  1233. echo $after;
  1234. return true;
  1235. }
  1236. }
  1237. }
  1238. if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
  1239. /**
  1240. * Show subcategory thumbnails.
  1241. *
  1242. * @access public
  1243. * @param mixed $category
  1244. * @subpackage Loop
  1245. * @return void
  1246. */
  1247. function woocommerce_subcategory_thumbnail( $category ) {
  1248. $small_thumbnail_size = apply_filters( 'single_product_small_thumbnail_size', 'shop_catalog' );
  1249. $dimensions = wc_get_image_size( $small_thumbnail_size );
  1250. $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
  1251. if ( $thumbnail_id ) {
  1252. $image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size );
  1253. $image = $image[0];
  1254. } else {
  1255. $image = wc_placeholder_img_src();
  1256. }
  1257. if ( $image ) {
  1258. // Prevent esc_url from breaking spaces in urls for image embeds
  1259. // Ref: http://core.trac.wordpress.org/ticket/23605
  1260. $image = str_replace( ' ', '%20', $image );
  1261. echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
  1262. }
  1263. }
  1264. }
  1265. if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
  1266. /**
  1267. * Displays order details in a table.
  1268. *
  1269. * @access public
  1270. * @param mixed $order_id
  1271. * @subpackage Orders
  1272. * @return void
  1273. */
  1274. function woocommerce_order_details_table( $order_id ) {
  1275. if ( ! $order_id ) return;
  1276. wc_get_template( 'order/order-details.php', array(
  1277. 'order_id' => $order_id
  1278. ) );
  1279. }
  1280. }
  1281. if ( ! function_exists( 'woocommerce_order_again_button' ) ) {
  1282. /**
  1283. * Display an 'order again' button on the view order page.
  1284. *
  1285. * @access public
  1286. * @param object $order
  1287. * @subpackage Orders
  1288. * @return void
  1289. */
  1290. function woocommerce_order_again_button( $order ) {
  1291. if ( ! $order || $order->status != 'completed' )
  1292. return;
  1293. ?>
  1294. <p class="order-again">
  1295. <a href="<?php echo wp_nonce_url( add_query_arg( 'order_again', $order->id ) , 'woocommerce-order_again' ); ?>" class="button"><?php _e( 'Order Again', 'woocommerce' ); ?></a>
  1296. </p>
  1297. <?php
  1298. }
  1299. }
  1300. /** Forms ****************************************************************/
  1301. if ( ! function_exists( 'woocommerce_form_field' ) ) {
  1302. /**
  1303. * Outputs a checkout/address form field.
  1304. *
  1305. * @access public
  1306. * @subpackage Forms
  1307. * @param mixed $key
  1308. * @param mixed $args
  1309. * @param string $value (default: null)
  1310. * @return void
  1311. * @todo This function needs to be broken up in smaller pieces
  1312. */
  1313. function woocommerce_form_field( $key, $args, $value = null ) {
  1314. $defaults = array(
  1315. 'type' => 'text',
  1316. 'label' => '',
  1317. 'placeholder' => '',
  1318. 'maxlength' => false,
  1319. 'required' => false,
  1320. 'class' => array(),
  1321. 'label_class' => array(),
  1322. 'input_class' => array(),
  1323. 'return' => false,
  1324. 'options' => array(),
  1325. 'custom_attributes' => array(),
  1326. 'validate' => array(),
  1327. 'default' => '',
  1328. );
  1329. $args = wp_parse_args( $args, $defaults );
  1330. if ( ( ! empty( $args['clear'] ) ) ) $after = '<div class="clear"></div>'; else $after = '';
  1331. if ( $args['required'] ) {
  1332. $args['class'][] = 'validate-required';
  1333. $required = ' <abbr class="required" title="' . esc_attr__( 'required', 'woocommerce' ) . '">*</abbr>';
  1334. } else {
  1335. $required = '';
  1336. }
  1337. $args['maxlength'] = ( $args['maxlength'] ) ? 'maxlength="' . absint( $args['maxlength'] ) . '"' : '';
  1338. if ( is_string( $args['label_class'] ) )
  1339. $args['label_class'] = array( $args['label_class'] );
  1340. if ( is_null( $value ) )
  1341. $value = $args['default'];
  1342. // Custom attribute handling
  1343. $custom_attributes = array();
  1344. if ( ! empty( $args['custom_attributes'] ) && is_array( $args['custom_attributes'] ) )
  1345. foreach ( $args['custom_attributes'] as $attribute => $attribute_value )
  1346. $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
  1347. if ( ! empty( $args['validate'] ) )
  1348. foreach( $args['validate'] as $validate )
  1349. $args['class'][] = 'validate-' . $validate;
  1350. switch ( $args['type'] ) {
  1351. case "country" :
  1352. $countries = $key == 'shipping_country' ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries();
  1353. if ( sizeof( $countries ) == 1 ) {
  1354. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1355. if ( $args['label'] )
  1356. $field .= '<label class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . '</label>';
  1357. $field .= '<strong>' . current( array_values( $countries ) ) . '</strong>';
  1358. $field .= '<input type="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="' . current( array_keys($countries ) ) . '" ' . implode( ' ', $custom_attributes ) . ' class="country_to_state" />';
  1359. $field .= '</p>' . $after;
  1360. } else {
  1361. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">'
  1362. . '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required . '</label>'
  1363. . '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="country_to_state country_select" ' . implode( ' ', $custom_attributes ) . '>'
  1364. . '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
  1365. foreach ( $countries as $ckey => $cvalue )
  1366. $field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
  1367. $field .= '</select>';
  1368. $field .= '<noscript><input type="submit" name="woocommerce_checkout_update_totals" value="' . __( 'Update country', 'woocommerce' ) . '" /></noscript>';
  1369. $field .= '</p>' . $after;
  1370. }
  1371. break;
  1372. case "state" :
  1373. /* Get Country */
  1374. $country_key = $key == 'billing_state'? 'billing_country' : 'shipping_country';
  1375. if ( isset( $_POST[ $country_key ] ) ) {
  1376. $current_cc = wc_clean( $_POST[ $country_key ] );
  1377. } elseif ( is_user_logged_in() ) {
  1378. $current_cc = get_user_meta( get_current_user_id() , $country_key, true );
  1379. if ( ! $current_cc) {
  1380. $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_country()) ? WC()->customer->get_country() : WC()->countries->get_base_country());
  1381. }
  1382. } elseif ( $country_key == 'billing_country' ) {
  1383. $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_country()) ? WC()->customer->get_country() : WC()->countries->get_base_country());
  1384. } else {
  1385. $current_cc = apply_filters('default_checkout_country', (WC()->customer->get_shipping_country()) ? WC()->customer->get_shipping_country() : WC()->countries->get_base_country());
  1386. }
  1387. $states = WC()->countries->get_states( $current_cc );
  1388. if ( is_array( $states ) && empty( $states ) ) {
  1389. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field" style="display: none">';
  1390. if ( $args['label'] )
  1391. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required . '</label>';
  1392. $field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
  1393. $field .= '</p>' . $after;
  1394. } elseif ( is_array( $states ) ) {
  1395. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1396. if ( $args['label'] )
  1397. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
  1398. $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="state_select" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '">
  1399. <option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
  1400. foreach ( $states as $ckey => $cvalue )
  1401. $field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
  1402. $field .= '</select>';
  1403. $field .= '</p>' . $after;
  1404. } else {
  1405. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1406. if ( $args['label'] )
  1407. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
  1408. $field .= '<input type="text" class="input-text ' . implode( ' ', $args['input_class'] ) .'" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
  1409. $field .= '</p>' . $after;
  1410. }
  1411. break;
  1412. case "textarea" :
  1413. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1414. if ( $args['label'] )
  1415. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
  1416. $field .= '<textarea name="' . esc_attr( $key ) . '" class="input-text ' . implode( ' ', $args['input_class'] ) .'" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '"' . ( empty( $args['custom_attributes']['rows'] ) ? ' rows="2"' : '' ) . ( empty( $args['custom_attributes']['cols'] ) ? ' cols="5"' : '' ) . implode( ' ', $custom_attributes ) . '>'. esc_textarea( $value ) .'</textarea>
  1417. </p>' . $after;
  1418. break;
  1419. case "checkbox" :
  1420. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">
  1421. <input type="' . esc_attr( $args['type'] ) . '" class="input-checkbox" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" value="1" '.checked( $value, 1, false ) .' />
  1422. <label for="' . esc_attr( $key ) . '" class="checkbox ' . implode( ' ', $args['label_class'] ) .'" ' . implode( ' ', $custom_attributes ) . '>' . $args['label'] . $required . '</label>
  1423. </p>' . $after;
  1424. break;
  1425. case "password" :
  1426. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1427. if ( $args['label'] )
  1428. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
  1429. $field .= '<input type="password" class="input-text ' . implode( ' ', $args['input_class'] ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />
  1430. </p>' . $after;
  1431. break;
  1432. case "text" :
  1433. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1434. if ( $args['label'] )
  1435. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label'] . $required . '</label>';
  1436. $field .= '<input type="text" class="input-text ' . implode( ' ', $args['input_class'] ) .'" name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" '.$args['maxlength'].' value="' . esc_attr( $value ) . '" ' . implode( ' ', $custom_attributes ) . ' />
  1437. </p>' . $after;
  1438. break;
  1439. case "select" :
  1440. $options = '';
  1441. if ( ! empty( $args['options'] ) )
  1442. foreach ( $args['options'] as $option_key => $option_text )
  1443. $options .= '<option value="' . esc_attr( $option_key ) . '" '. selected( $value, $option_key, false ) . '>' . esc_attr( $option_text ) .'</option>';
  1444. $field = '<p class="form-row ' . esc_attr( implode( ' ', $args['class'] ) ) .'" id="' . esc_attr( $key ) . '_field">';
  1445. if ( $args['label'] )
  1446. $field .= '<label for="' . esc_attr( $key ) . '" class="' . implode( ' ', $args['label_class'] ) .'">' . $args['label']. $required . '</label>';
  1447. $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $key ) . '" class="select" ' . implode( ' ', $custom_attributes ) . '>
  1448. ' . $options . '
  1449. </select>
  1450. </p>' . $after;
  1451. break;
  1452. default :
  1453. $field = apply_filters( 'woocommerce_form_field_' . $args['type'], '', $key, $args, $value );
  1454. break;
  1455. }
  1456. if ( $args['return'] ) return $field; else echo $field;
  1457. }
  1458. }
  1459. if ( ! function_exists( 'get_product_search_form' ) ) {
  1460. /**
  1461. * Output Product search forms.
  1462. *
  1463. * @access public
  1464. * @subpackage Forms
  1465. * @param bool $echo (default: true)
  1466. * @return string
  1467. * @todo This function needs to be broken up in smaller pieces
  1468. */
  1469. function get_product_search_form( $echo = true ) {
  1470. do_action( 'get_product_search_form' );
  1471. $search_form_template = locate_t

Large files files are truncated, but you can click here to view the full file